文章轉自:http://blog.sina.com.cn/s/blog_a43aba5601014z8h.html
一、數據庫操作准備
1、導入ADO動態鏈接庫
在工程的stdafx.h中加入如下語句:
這一語句有何作用呢?其最終作用同我們熟悉的#include類似,編譯的時候系統會為我們生成msado15.tlh和msado15.tli兩個C++頭文件來定義ADO庫,即加載ADO動態庫(msado15.dll)。
其中,no_namespace表明不使用命名空間,rename("EOF","adoEOF")表明把ADO中用到的EOF改為adoEOF,防止發生命名沖突。
注意:該代碼需要在一行中完成,如果寫成兩行或者多行,行末要加上“\”符號,表示把這幾行看成一行,如本例。
2、初始化OLE/COM庫環境
在基於MFC的應用里,初始化OLE/COM庫環境的一個比較好的位置是在應用類的InitInstance成員函數中,而且直接使用AfxOleInit,在退出應用時,該函數也負責COM資源的釋放,將此函數添加在InitInstance中的如下位置:
Return FALSE;
}
......
}
說明:也可以在InitInstance中使用::CoInitialize初始化OLE/COM庫環境,但須在ExitInitInstance中使用::CoUninitialize釋放占用的COM資源,顯然使用AfxOleInit更為方便。
3、連接數據庫
在Doc\View程序中,通常在應用類(App類)中進行數據庫的連接。
1)聲明一個Connection指針
_ConnectionPtr m_pConnection;
注:ADO最重要的三個對象有三個:連接對象(Connection)、命令對象(Command)和記錄集對象(RecordSet)。在使用這三個對象的時候,需要定義與之相對應的智能指針最后是自動進行內存釋放的。
所有的智能指針都是基於_com_ptr_t模板類的,該類封裝了IUnknow接口的3個方法:QueryInterface、Addref和Release。它具有自動計數的機制,即在構造對象時,自動為該對象計數加1。析構對象時,自動調用Release方法。(即該類型的指針在使用后不需要手動釋放內存)(但需要調用Close方法,關閉連接或者記錄集)所以智能指針會使代碼更加簡潔並且不易出錯。
2)創建Connection對象
m_pConnection.CreateInstance(__uuidof(Connection));
m_pConnection.CreateInstance("ADODB.Connection");
上述兩種方法均可。
注意:上面調用_ConnectionPtr接口指針的方法CreateInstance時,用的是“.”而非
“->”。
3)設置連接字符串,以便指定需要的連接
3.1) 使用JET數據庫引擎實現對Acess2000類型的數據庫info.mdb的連接
CString strSQL="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=info.mdb;User ID=admin;Passward=;";
或者
CString strSQL=_T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=info.mdb;User ID=admin;Passward=;");
3.2) 使用OLE DB提供者實現對SQL Server的標准安全連接串
strConnect=_T("Provider=sqloledb;Data Source=MyServerName;"
"Initial Catalog=MyDateBaseName;"
"User ID=MyUserName;Password=MyPassword;");
例程:
注意:上面設置連接字符串的時候,如果過長需要分行時,則每一行都要加上雙引號,在最后加上分號即可。
如果是本地服務器,則DataSource=local或本地服務器名均可
若數據庫沒有設置密碼,在連接字符串中可以將其省略,但User ID不能省
若數據庫和程序文件不在同一文件夾下,直接寫數據庫名即可,在InitialCatalog中不需加上該數據庫的存儲器地址
3.3) 使用OLE DB提供者實現對遠程SQL Server的標准安全連接串
strConnect=_T("Provider=sqloledb;Network Library=DBMSSOCN;"
"Data Source=130.120.110.001,1433;"
"Initial Catalog=MyDateBaseName;"
"User ID=MyUserName;Password=MyPassword;");
4)、使用m_pConnection的Open方法實現對數據庫的連接
在ADO的操作中建議使用try...catch( )來捕獲錯誤信息,因為它有時會經常出現一些意想不到的錯誤
AfxMessageBox(errormessage); //顯示錯誤信息
}
4、關閉連接
一般重載App類的ExitInstace( )函數實現
調用m_pConnection的Close方法關閉連接即可
m_pConnection->Close( );
m_pConnection=NULL;
注意:由於初始化COM庫調用的是AfxOleInit,這種方法初始化COM庫的優點就在於資源 的釋放也是自動進行的,所以不必擔心資源泄漏的問題。
二、數據庫操作
ADO庫中包含的三個基本接口為_ConnectionPtr接口、_CommandPtr接口、_RecordsetPtr接口。
1、_ConnectionPtr接口
該接口返回一個記錄集或一個空指針。
不推薦使用_ConnectionPtr接口返回一個記錄集,對於要返回記錄集的操作通常用_RecordsetPtr來實現,而且使用_ConnectionPtr時要想得到記錄數目必須遍歷所有記錄,但使用_RecordsetPtr時則不需要。
2、_CommandPtr接口
該接口返回一個記錄集。
它提供了一種簡單的方法來執行返回記錄集的存儲過程和SQL語句。
在使用_CommandPtr接口時,可以利用全局_ConnectionPtr接口,也可以在_CommandPtr
接口里直接使用連接串。如果只執行一次或者幾次數據庫訪問操作,后者是比較好的選擇。但是,如果頻繁訪問數據庫,並要返回很多記錄集,那么應該使用全局_ConnectionPtr接口創建一個數據庫連接,然后使用_CommandPtr接口執行存儲過程和SQL語句。
3、_RecordsetPtr接口
該接口是一個記錄集對象。
與前兩種對象相比,注意:可以使用Recordset對象來執行查詢命令,但如果查詢或者存儲過程是需要參數的,這時就只能使用Command對象。
使用Recordset對象操作數據庫:
假定已經成功使用Connection對象創建了數據源的連接,連接指針為m_pConnection。
1)創建記錄集
聲明記錄集指針 _RecordsetPtr m_pRecordset;
創建記錄集 m_pRecordset.CreateInstance(__uuidof(Recordset));
2)打開記錄集
記錄集指針創建完畢后,調用該指針的Open方法打開記錄集。
該函數聲明如下:
HRESULT Recordset15::Open ( const _variant_t & Source,
const _variant_t & ActiveConnection,
enum CursorTypeEnum CursorType,
enum LockTypeEnum LockType,
long Options ) ;
各個參數的含義如下:
參數Source:為_variant_t類型的引用,可以為有效的Command對象、SQL語句、表名、存儲過程調用等。
參數ActiveConnection:為_variant_t類型的引用,為已經建立好的連接。
參數CursorType:用於設置在打開Recordset時提供者應使用的游標類型,它可取CursorTypeEnum 中的任一值,默認值為adOpenForwardOnly。
參數 LockType:用於設置在打開Recordset時提供者應使用的鎖定類型,它可取枚舉LockTypeEnum中的任一值,默認值為adLockReadOnly。
參數 Options:用於設置獲取Source(即Open第一個參數)的方式,其類型long。
= "select * from mytablename";
m_pRecordset->Open ( _variant_t (strSQL),
adOpenDynamic,
adCmdText ) ;
m_pConnection.GetInterfacePtr( ),
adOpenDynamic,
adLockOptimistic,
adCmdTable ) ;
直接使用表名作為第一個參數,此時Options應為adCmdTable
3)遍歷記錄集
一般在返回記錄集時,通常要遍歷結果記錄集,以便查看或編輯某一條記錄,Recoreset指針提供了幾個用於實現遍歷的方法。
注意:為了避免發生異常,一般在使用MoveFirst、MovePrev之前,需要使用記錄集的指針BOF屬性來檢測當前的記錄集指針是否位於第一條記錄之前;在使用MoveLast、MoveNext之前需要使用記錄集指針的EOF屬性來檢測當前的記錄集指針是否位於最后一條記錄之后。
4)記錄集定位
記錄集接口類提供了兩種定位方法:絕對定位和書簽定位
前者通過設置或者獲取AbsolutePosition屬性即可,其值從1開始,並且當前記錄為記錄集中第一條記錄時等於1
對於后者可以通過設置或獲取BookMark屬性即可
5)訪問記錄集
最簡單的方法是直接使用如下語句:
m_pRecordset->GetCollect (字段名);
設置字段值:
m_pRecordset->PutCollect (字段名,新值);
兩個方法的原型:
_variant_t GetCollect ( const _variant_t & Index )
void PutCollect ( const _variant_t & Index , const _variant_t &pvar )
其中:參數Index可以是字符串表示字段名,也可以是整型,表示字段對應的序號。
pvar表示要寫入的變量值。
例如:
_variant_t var;
var=m_pRentRecordset->GetCollect(long(0)); 都可以
6)記錄集更新
更新記錄集包括添加新的記錄、編輯當前記錄和刪除當前記錄
記錄集接口指針對這三種操作分別提供了相應的方法
編輯當前記錄:Edit
刪除當前記錄:Delete
注意:記錄集接口指針針對AddNew以及Edit方法提供了Update方法,用於在數據庫中更新新添加或者編輯后的記錄。
AddNew方法:用於添加新紀錄(該添加是直接在表的末尾續加的),該方法可以使用參數,在參數中指定要添加的新紀錄;也可以不使用參數,而在后面使用PutCollect方法,並需使用Update函數保存新紀錄。
Update方法:用於保存從調用AddNew方法以來所作的任何更改。
m_pRecordset->PutCollect("單位地址",_variant_t(m_strComAddr));
//更新數據庫-將新紀錄存入數據庫
m_pRecordset->Update();
7)記錄集關閉
在對記錄集的操作完成后,必須及時關閉記錄集。
{
m_pRecordset ->Close( );
m_pRecordset =NULL;
}