孫鑫VC學(xué)習(xí)筆記:第二十講 (二) ado數(shù)據(jù)庫(kù)編程 收藏
數(shù)據(jù)庫(kù)編程:
COM
[計(jì)] 小型可執(zhí)行程序的擴(kuò)展名, 串行通訊端口
[域] Commercial organizations,商業(yè)組織,公司
The Component Object Model組件對(duì)象模型
ADO的三個(gè)核心對(duì)象
Connection對(duì)象
Connection對(duì)象表示了到數(shù)據(jù)庫(kù)的連接,它管理應(yīng)用程序和數(shù)據(jù)庫(kù)之間的通信。Recordest和Command對(duì)象都有一個(gè)ActiveConnection屬性,該屬性用來飲用Connection對(duì)象。
Command對(duì)象
Command對(duì)象被用來處理重復(fù)執(zhí)行的查詢,或處理需要檢查在存儲(chǔ)過程調(diào)用中的輸出或返回參數(shù)的值的查詢。
Recordset對(duì)象
Recordset對(duì)象被用來獲取數(shù)據(jù)。Recordset對(duì)象存放查詢的結(jié)果,這些結(jié)果又?jǐn)?shù)據(jù)的行(稱為記錄)和列(成為字段)組成。每一列都存放在Recordset的Fields集合中的一個(gè)Filed對(duì)象中
關(guān)于ADO數(shù)據(jù)庫(kù)連接方面知識(shí)的總結(jié)
1、導(dǎo)入庫(kù)文件
使用ADO前必須在工程的stdafx.h文件最后用直接引入符號(hào)#import引入ADO庫(kù)文件,以使編譯器能正確編譯。代碼如下:
#import "C:\Program Files\common files\system\ado\msado15.dll" no_namespace rename("EOF","EndOfFile") rename("BOF","FirstOfFile")
ADO類的定義是作為一種資源存儲(chǔ)在ADO DLL(msado15.dll)中,在其內(nèi)部稱為類型庫(kù)。
類型庫(kù)描述了自治接口,以及C++使用的COM vtable接口。
當(dāng)使用#import指令時(shí),在運(yùn)行時(shí)Visual C++需要從ADO DLL中讀取這個(gè)類型庫(kù),
并以此創(chuàng)建一組C++頭文件。這些頭文件具有.tli 和.tlh擴(kuò)展名,#import引入ADO庫(kù)文件的代碼編譯后,在項(xiàng)目的目錄下生成了這兩個(gè)文件。在C++程序代碼中調(diào)用的ADO類要在這些文件中定義。
程序的第三行指示ADO對(duì)象不使用名稱空間,在有些應(yīng)用程序中,
由于應(yīng)用程序中的對(duì)象與ADO中的對(duì)象之間可能會(huì)出現(xiàn)命名沖突,所以有必要使用名稱空間。
如果要使用名稱空間,則可把第三行程序修改為: rename_namespace("AdoNS")。
第四行代碼將ADO中的EOF(文件結(jié)束)更名為adoEOF,因?yàn)槲募慕Y(jié)尾也是以EOF結(jié)尾的,是為了避免與定義了自己的EOF的其他庫(kù)沖突。 至于改為什么名字,可以根據(jù)自己的命名習(xí)慣自己確定。
2、初始化COM環(huán)境
OLE DB 是基于COM技術(shù)編寫的,ADO是OLE DB基礎(chǔ)之上的用戶程序,
OLE DB是一個(gè)COM組件,在訪問COM組件的時(shí)候需要初始化COM庫(kù),方法如下:
(1) ::CoInitialize(NULL); //初始化OLE/COM庫(kù)環(huán)境
//對(duì)數(shù)據(jù)庫(kù)的訪問在上下代碼之間寫,下面第三步就應(yīng)該寫在這里
::CoUninitialize();//既然初始化了環(huán)境,當(dāng)然一定要記得釋放他了
(2)也可以調(diào)用MFC全局函數(shù)
AfxOleInit();
3、三大指針對(duì)象的定義和創(chuàng)建實(shí)例
(1)
_ConnectionPtr pConnection("ADODB.Connection");
_RecordsetPtr pRecordset("ADODB.Recordset");
_CommandPtr pCommand("ADODN.Command");
(2)
_ConnectionPtr pConnection;
_RecordsetPtr pRecordset;
_CommandPtr pCommand;
pConnection.CreateInstance(__uuidof(Connection));
pRecordset.CreateInstance(__uuidof(Recordset));
pCommand.CreateInstance(__uuidof(Command));
要產(chǎn)生一個(gè)智能指針對(duì)象,其實(shí)在定義的同時(shí)也可以初始化,如:
_ConnectionPtr pConnection(__uuidof(Connection));
_ConnectionPtr 是智能指針
__uuidof() 用來獲取Connection全局唯一標(biāo)識(shí)符
(3)
_ConnectionPtr pConnection;
_RecordsetPtr pRecordset;
_CommandPtr pCommand;
pConnection.CreateInstance("ADODB.Connection");
pRecordset.CreateInstance("ADODB.Recordset");
pCommand.CreateInstance("ADODB.Command");
4、打開一個(gè)連接
pConnection->ConnectionString = "這里的字符串有下面四種寫法";//對(duì)連接字符串賦值
pConnection->Open(ConnectionString,"","",adModeUnknown); //連接數(shù)據(jù)庫(kù)
第二三個(gè)參數(shù)分別為用戶的ID與密碼,
因?yàn)樵谶B接字符串ConnectionCstring中已經(jīng)設(shè)置好了,這里可以為空。
第四個(gè)參數(shù)可以取下面兩個(gè)參數(shù):
adAsyncConnect
異步打開數(shù)據(jù)庫(kù),在ASP中直接用16
adConnectUnspecified
同步打開數(shù)據(jù)庫(kù),在ASP中直接用-1
ConnectionString根據(jù)不同的數(shù)據(jù)源,分別對(duì)應(yīng)不同的寫法
(要記下來很困難,可以在VB中利用ADO控件先連接好,再將其拷貝在VC中,這樣不容易出錯(cuò))
1)
訪問Access 2000
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=databaseName;User ID=userName;Password=userPassWord"
2)
訪問ODBC數(shù)據(jù)
"Provider=MADASQL;DSN=dsnName;UID=userName;PWD=userPassword;"
3)
訪問Oracle數(shù)據(jù)庫(kù)
“Provider=MSDAORA;Data Sourse=serverName;User ID=userName;Password=userPassword;"
4)
訪問MS SQL數(shù)據(jù)庫(kù)
"Provider=SQLOLEDB,Data Source=serverName;Initial Catalog=databaseName;User ID=userName;Password=userPassword;"
5、執(zhí)行SQL命令,得到數(shù)據(jù)
方法1:
pRecordset = pConnection->Execute("Select * from authors",NULL,adCmdText);
方法2:
pRecordset ->Open("Select * from authors",_
variant_t((Idispacth*) pConnection), //設(shè)置活動(dòng)連接
adOpenDynamtic,
//游標(biāo)類型
adLockOptimistic,
//鎖的類型
adCmdText);
方法3:
pCommand->put_ActiveConnection(_variant_t((Idispatch *) pConn);
pCommand->CommandText = "Select * from authors";
pRecordset = pCmd->Execute(NULL,NULL,adCmdText);
得到數(shù)據(jù)之后,做一個(gè)循環(huán)取得數(shù)據(jù):
While (!pRecordset ->adoEOF)
{
Str = pRecordset->GetCollect("au_lname"));
pRst->MoveNext();
}
SQL命令比較多,但是不去考慮細(xì)節(jié),這里只說出通用的方法
CString strSQL;//定義SQL命令串,用來保存SQL語句
strSQL.Format("SQL statement");
然后在每個(gè)要用到SQL命令串的方法中,使用strSQL.AllocSysString()的方法進(jìn)行類型轉(zhuǎn)換
6、com的專用數(shù)據(jù)類型
variant ,bstr ,SafeArray
variant變量的范圍包括很多,它是一種變體類型,主要用于支持自動(dòng)化的語言訪問,
從而在VB中非常方便地使用,但是VC中比較復(fù)雜,它使用_variant_t 進(jìn)行管理
bstr是一種字符串變量,使用_bstr_t進(jìn)行管理,這個(gè)類重載了char *操作符
7、關(guān)閉連接
if(pConnection->State); //不能多次關(guān)閉,否則會(huì)出現(xiàn)錯(cuò)誤
pConnection->Close();
pRecordset->Close();
pCommand.Release();
pConnection.Release();
//釋放引用計(jì)數(shù)
pRecordset.Release();
注意:調(diào)用Close()時(shí)用"->",調(diào)用Release()時(shí)要用".",為什么?
因?yàn)橹悄苤羔?,_ConnectionPtr是一個(gè)重載了->運(yùn)算符的類
_ConnectionPtr:它是一個(gè)接口指針模板。'.'是模板_com_ptr的函數(shù)。->是'接口函數(shù)'調(diào)用。
//forexample:
_ConnectionPtr m_Conn;
m_Conn.CreateInstance(....);//Createinterfaceinstance.
m_Conn->Open(...);//Openaconnectiontodatabase.
'->'是_com_ptr重載了的運(yùn)算符.目的就是為了讓你調(diào)用模板參數(shù)的函數(shù).
8、結(jié)構(gòu)化異常處理
ADO封裝了COM接口,所以需要進(jìn)行錯(cuò)誤處理
如下例:
HRESULT hr;
try
{
hr = m_pConnection.CreateInstance("ADODB.Connection");///創(chuàng)建Connection對(duì)象
if(SUCCEEDED(hr))
{
hr = m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb","","",adModeUnknown);///連接數(shù)據(jù)庫(kù)
///上面一句中連接字串中的Provider是針對(duì)ACCESS2000環(huán)境的,對(duì)于ACCESS97,需要改為:Provider=Microsoft.Jet.OLEDB.3.51; }
}
catch(_com_error e)///捕捉異常
{
CString errormessage;
errormessage.Format("連接數(shù)據(jù)庫(kù)失敗!\r\n錯(cuò)誤信息:%s",e.ErrorMessage());
AfxMessageBox(errormessage);///顯示錯(cuò)誤信息
}
這里介紹了三種對(duì)象通過ADO訪問數(shù)據(jù)庫(kù),它們都可以執(zhí)行SQL語句獲取數(shù)據(jù),但不是管那種方法獲取數(shù)據(jù),最終都將數(shù)據(jù)放置到記錄集對(duì)象當(dāng)中。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。