VC++下使用ADO操作數據庫的智能指針_ConnectionPtr、_RecordsetPtr、_CommandPtr的方法



(1)、引入ADO類

1
2
3
#import "c:\program files\common files\system\ado\msado15.dll" \
    no_namespace \
rename ("EOF", "adoEOF")

(2)、初始化COM

在MFC中可以用AfxOleInit();非MFC環境中用:
CoInitialize(NULL);
CoUnInitialize();

(3)#import 包含後就可以用3個智能指針了
:_ConnectionPtr、_RecordsetPtr和_CommandPtr

1.連接和關閉數據庫

(1)連接

例子:連接Access數據庫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
AfxOleInit();//初始化
HRESULT hr;
try
{
    //hr = m_pConnection.CreateInstance("ADODB.Connection");///創建Connection對象

    hr = m_pConnection.CreateInstance(_uuidof(Connection));///創建Connection實例
    if(SUCCEEDED(hr))
    {
        m_pConnection->ConnectionTimeout = 0;
        hr = m_pConnection->Open( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db.mdb", "", "", adModeUnknown);
        //m_pConnection->PutDefaultDatabase ((_bstr_t)"DB");//設置默認數據庫
 
        m_pCommand.CreateInstance(__uuidof(Command));
        m_pCommand->CommandTimeout = 5;
        m_pCommand->ActiveConnection = m_pConnection;
    }
}
catch(_com_error e)///捕捉異常
{
    CString errormessage;
    errormessage.Format("連接數據庫失敗!\r\n錯誤信息:%s",e.ErrorMessage());
    AfxMessageBox(errormessage);///顯示錯誤信息
}


(2)、關閉

1
2
3
4
5
6
7
8
9
//如果數據庫連接有效
if( m_pConnection->State )
m_pConnection->Close();
m_pConnection = NULL;
 
<span style="color: #ff0000;">(3)、設置連接時間
</span>
//設置連接時間-----------------------------------
pConnection->put_ConnectionTimeout(long(5));


2.打開一個結果集

(1)打開,首先創建一個_RecordsetPtr實例,然後調用Open()得到一條SQL語句的執行結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
_RecordsetPtrm_pRecordset;
m_pRecordset.CreateInstance(__uuidof(Recordset));
 
// 在ADO操作中建議語句中要常用try...catch()來捕獲錯誤信息,
// 因爲它有時會經常出現一些意想不到的錯誤。jingzhou xu
try
{
    m_pRecordset->Open("SELECT * FROM DemoTable",// 查詢DemoTable表中所有字段
        m_pConnection.GetInterfacePtr(),  // 獲取庫接庫的IDispatch指針
        adOpenDynamic,
        adLockOptimistic,
        adCmdText);
}
catch(_com_error *e)
{
    AfxMessageBox(e->ErrorMessage());
}

(2)關閉結果集
m_pRecordset->Close();

3.操作一個結果集

(1)、遍歷(讀取)

a)、用pRecordset->adoEOF來判斷數據庫指針是否已經移到結果集的末尾了;m_pRecordset->BOF判斷是否 在第一條記錄前面:

1
2
3
4
5
6
7
8
9
10
11
while(!m_pRecordset->adoEOF)
{
    var = m_pRecordset->GetCollect("Name");
    if(var.vt != VT_NULL)
        strName = (LPCSTR)_bstr_t(var);
    var = m_pRecordset->GetCollect("Age");
    if(var.vt != VT_NULL)
        strAge = (LPCSTR)_bstr_t(var);
    m_AccessList.AddString( strName + " --> "+strAge );
    m_pRecordset->MoveNext();
}

b)、取得一個字段的值的辦法有兩種辦法

一是

//表示取得第0個字段的值 m_pRecordset->GetCollect(“Name”);

或者 m_pRecordset->GetCollect(_variant_t(long(0));

二是
pRecordset->get_Collect(“COLUMN_NAME”);

或者 pRecordset->get_Collect(long(index));

(2)、添加

a)、調用m_pRecordset->AddNew();
b)、調用m_pRecordset->PutCollect();給每個字段賦值
c)、調用m_pRecordset->Update();確認

(3)、修改
(4)、刪除

a)、把記錄指針移動到要刪除的記錄上,然後調用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Delete(adAffectCurrent) try
{
    // 假設刪除第二條記錄
    m_pRecordset->MoveFirst();
    m_pRecordset->Move(1);
    // 從0開始
    m_pRecordset->Delete(adAffectCurrent);
    // 參數adAffectCurrent爲刪除當前記錄
    m_pRecordset->Update();
}
catch(_com_error *e)
{
    AfxMessageBox(e->ErrorMessage());
}

4.直接執行SQL語句,除了要用到結果集其餘的大部分功能都可以直接用SQL語言實現

(1)、用_CommandPtr和_RecordsetPtr配合

1
2
3
4
5
6
7
8
9
_CommandPtrm_pCommand;
 
m_pCommand.CreateInstance(__uuidof(Command));
// 將庫連接賦於它
m_pCommand->ActiveConnection = m_pConnection;
// SQL語句
m_pCommand->CommandText = "SELECT * FROM DemoTable";
// 執行SQL語句,返回記錄集
m_pRecordset = m_pCommand->Execute(NULL, NULL,adCmdText);


(2)、直接用_ConnectionPtr執行SQL語句

1
2
3
_RecordsetPtr Connection15::Execute ( _bstr_t CommandText,
                                     VARIANT * RecordsAffected,
                                     long Options )

其中CommandText是命令字串,通常是SQL命令。
參數RecordsAffected是操作完成後所影響的行數,
參數Options表示CommandText中內容的類型,Options可以取如下值之一:
adCmdText:表明CommandText是文本命令
adCmdTable:表明CommandText是一個表名
adCmdProc:表明CommandText是一個存儲過程
adCmdUnknown:未知

例子:
_variant_t RecordsAffected;
m_pConnection->Execute(“UPDATE users SET old = old+1″,&RecordsAffected,adCmdText);
5.調用存儲過程

(1)、利用_CommandPtr

1
2
3
4
5
_CommandPtrm_pCommand;
m_pCommand.CreateInstance(__uuidof(Command));
m_pCommand->ActiveConnection = m_pConnection;  // 將庫連接賦於它
m_pCommand->CommandText = "Demo";
m_pCommand->Execute(NULL,NULL, adCmdStoredProc);

(2)、直接用_ConnectionPtr直接調用(見4.(2))

6.遍歷數據庫中的所有表名

_ConnectionPtr m_pConnect;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
_RecordsetPtr pSet;
HRESULT hr;
try
{
    hr = m_pConnect.CreateInstance("ADODB.Connection");
    if(SUCCEEDED(hr))
    {
        CString dd;
        dd.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s",file);
        hr = m_pConnect->Open((_bstr_t)dd,"","",adModeUnknown);
        pSet = m_pConnect->OpenSchema(adSchemaTables);
        while(!(pSet->adoEOF))
        {
            //獲取表格
            _bstr_t table_name = pSet->Fields->GetItem("TABLE_NAME")->Value;
 
            //獲取表格類型
            _bstr_t table_type = pSet->Fields->GetItem("TABLE_TYPE")->Value;
 
            //過濾一下,只輸出表格名稱,其他的省略
            if ( strcmp(((LPCSTR)table_type),"TABLE")==0){
                CString tt;
                tt.Format("%s",(LPCSTR)table_name);
                AfxMessageBox(tt);
            }
            pSet->MoveNext();
        }
        pSet->Close();
    }
    m_pConnect->Close();
}catch(_com_error e)///捕捉異常
{
    CString errormessage;
    errormessage.Format("連接數據庫失敗!rn錯誤信息:%s",e.ErrorMessage());
 
    AfxMessageBox(errormessage);
    return -1;
}


7.遍歷一個表中的所有字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Field *   field = NULL;
HRESULT   hr;
Fields *  fields = NULL;
hr = m_pRecordset->get_Fields (&fields);//得到記錄集的字段集和
 
if(SUCCEEDED(hr))
fields->get_Count(&ColCount);
 
//得到記錄集的字段集合中的字段的總個數
for(i=0;iItem[i]->get_Name(&bstrColName);//得到記錄集//中的字段名
strColName=bstrColName;
nameField = strColName;
m_FieldsList.AddString(nameField);
}
if(SUCCEEDED(hr))
fields->Release();//釋放指針

附:

1、_variant_t

(1)、一般傳給這3個指針的值都不是MFC直接支持的數據類型,而要用_variant_t轉換一下
_variant_t(XX)可以把大多數類型的變量轉換成適合的類型傳入:
(2)、_variant_t var;_variant_t -> long: (long)var;
_variant_t -> CString: CString strValue = (LPCSTR)_bstr_t(var);
CString -> _variant_t: _variant_t(strSql);
2、BSTR寬字符串與CString相互轉換

BSTR bstr;
CString strSql;
CString -> BSTR: bstr = strSql.AllocSysString();
BSTR -> CString: strSql = (LPCSTR)bstr;
3、_bstr_t與CString相互轉換

_bstr_t bstr;
CString strSql;
CString -> _bstr_t: bstr = (_bstr_t)strSql;
_bstr_t -> CString: strSql = (LPCSTR)bstr;
4、關於時間

Access:表示時間的字符串#2004-4-5#
Sql:表示時間的字符串”2004-4-5”
DateField(時間字段) select * from my_table where DateField > #2004-4-10#

1
2
3
4
5
6
7
8
9
10
11
try
{
    m_pCommand->CommandText = "INSERT INTO tTest(age) VALUES('23f2') ";
    m_pRecordset = m_pCommand->Execute(NULL,NULL, adCmdText);
}
catch(_com_error e)///捕捉異常
{
    CString errormessage;
    errormessage.Format("連接數據庫失敗!\r\n錯誤信息:%s",e.ErrorMessage());
    AfxMessageBox(errormessage);///顯示錯誤信息
}

來源:http://blog.csdn.net/umbrella1984/archive/2005/05/29/383628.aspx

   


_RecordsetPtr m_pRecordset;//創建一個_RecordsetPtr m_pRecordset.CreateInstance("ADODB.Recordset"); //創建一個實例 try {      m_pRecordset->Open(

"SELECT * FROM duty",                                               //sql查詢語句
   m_pConnection.GetInterfacePtr(),                               //得到sql連接的指針

//Const adOpenDynamic = 2 '動態遊標功能最強,但耗資源也最多。用戶對記錄說做的修改,增加或刪除記錄都將反映到記錄集中。支持全功能瀏覽(ACCESS不支持)。   
   adOpenDynamic,   

//Const adLockOptimistic = 3 '只有在調用Update方法時才鎖定記錄集,而在此前的其他操作仍可對當前記錄進行更改、插入和刪除 等                                                      

   adLockOptimistic,

//AdCmdText 將 CommandText 作爲命令或存儲過程調用的文本化定義進行計算。
   adCmdText); 
}
catch(_com_error e)
{
   //cout<<e->ErrorMessage()<<endl;
   AfxMessageBox("Create Instance failed!");
   return;
}

 

內容一:

'定義數據庫連接的一些常量 
Const adOpenForwardOnly = 0 '(默認值)遊標只向前瀏覽記錄,不支持分頁、Recordset、BookMark 
Const adOpenKeyset = 1 '鍵集遊標,其他用戶對記錄說做的修改將反映到記錄集中,但其他用戶增加或刪除記錄不會反映到記錄集中。支持分頁、Recordset、BookMark 
Const adOpenDynamic = 2 '動態遊標功能最強,但耗資源也最多。用戶對記錄說做的修改,增加或刪除記錄都將反映到記錄集中。支持全功能瀏覽(ACCESS不支持)。 
Const adOpenStatic = 3 '靜態遊標,只是數據的一個快照,用戶對記錄說做的修改,增加或刪除記錄都不會反映到記錄集中。支持向前或向後移動 

Const adLockReadOnly = 1 '(默認值)鎖定類型,默認的,只讀,不能作任何修改 
Const adLockPessimistic = 2 '當編輯時立即鎖定記錄,最安全的方式 
Const adLockOptimistic = 3 '只有在調用Update方法時才鎖定記錄集,而在此前的其他操作仍可對當前記錄進行更改、插入和刪除等 
Const adLockBatchOptimistic = 4 '當編輯時記錄不會被鎖定,而更改、插入和刪除是在批處理方式下完成的 
Const adCmdText = &H0001 
Const adCmdTable = &H0002 
%> 
Open 方法 (ADO Recordset) 
打開遊標。 
語法 
recordset.Open Source, ActiveConnection, CursorType, LockType, Options

內容二:

CommandType 屬性 
指示 Command 對象的類型。 
設置和返回值 
設置或返回以下某個 CommandTypeEnum 值。 

常量 說明 
AdCmdText 將 CommandText 作爲命令或存儲過程調用的文本化定義進行計算。 
AdCmdTable 將 CommandText 作爲其列全部由內部生成的 SQL 查詢返回的表格的名稱進行計算。 
AdCmdTableDirect 將 CommandText 作爲其列全部返回的表格的名稱進行計算。 
AdCmdStoredProc 將 CommandText 作爲存儲過程名進行計算。 
AdCmdUnknown 默認值。CommandText 屬性中的命令類型未知。 
adCmdFile 將 CommandText 作爲持久 Recordset 文件名進行計算。 
AdExecuteNoRecords 指示 CommandText 爲不返回行的命令或存儲過程(例如,插入數據的命令)。如果檢索任意行,則將丟棄這些行且並不返回。它總是與 adCmdText 或 adCmdStoredProc 進行組合。 

說明 
使用 CommandType 屬性可優化 CommandText 屬性的計算。 

如果 CommandType 屬性的值等於 adCmdUnknown(默認值),系統的性能將會降低,因爲 ADO 必須調用提供者以確定 CommandText 屬性是 SQL 語句、還是存儲過程或表格名稱。如果知道正在使用的命令的類型,可通過設置 CommandType 屬性指令 ADO 直接轉到相關代碼。如果 CommandType 屬性與 CommandText 屬性中的命令類型不匹配,調用 Execute 方法時將產生錯誤。 

adExecuteNoRecords 常量通過最小化內部處理來提高性能。該常量不獨立使用,它總是與 adCmdText 或 adCmdStoredProc 組合(如adCmdText+adExecuteNoRecords) 一起使用。如果與 Recordset.Open 一起使用 adExecuteNoRecords,或者該方法使用 Command 對象都將產生錯誤。

發佈了34 篇原創文章 · 獲贊 7 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章