聲明:百度以外的公司可以自由轉(zhuǎn)載該文。
正如我上一篇博文提到,ADO這貨和MFC沒有任何關(guān)系,ADO 是一個獨立的組件。所以為了使用ADO 我們就要把ADO引入到MFC中。
ADO是硬盤上的表現(xiàn)形式是 一個名為 msado15.dll的動態(tài)鏈接庫。
第一步:在VS2010 中 創(chuàng)建一個對話框MFC程序。
第二步:在stdafx.h 添加一句代碼 (添加位置是在#include <afxdisp.h> // MFC 自動化類 后面)
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF", "EndOfFile")
下面解釋一個上面代碼的意思。
#import 這個沒啥話說 就是引入的意思, "C:\Program Files\Common Files\System\ADO\msado15.dll" 就是說一個全路徑,就是msado15.dll
這個文件在硬盤中的位置。 如果你的系統(tǒng)沒有做過刻意的更改 ,那么這個路徑應(yīng)該就是他了。
no_namespace , 這是啥意思? 翻譯過來就是不使用命名空間 就是不使用 ADO這個組件自己命名空間 不然你在后面使用ADO的一些 接口的時候
就需要在前面加?xùn)|西(加啥? 我也不知道 ,我也是停別人這么說的)
rename("EOF", "EndOfFile") 這句話 即使重命名 EOF ,為啥要重新命名呢? 這是因為是在MFC里面有EOF這個字眼 但是意思和ADO里面的 EOF不是
一個意思 所以需要重新命名 不然ADO這貨就瘋了。 你可以任意命名 這要不和已有的 名字重復(fù)就好了 這個改名字為EndOfFile(有些哥們呢 喜歡命名為ADOEOF)
××××××××××××××××××××××××××××××××××××××××××××××××××××××××轉(zhuǎn)載×××××××××××××××××××××××××××××××××××××××××××××××××
#import語句實際上相當(dāng)于執(zhí)行了API涵數(shù)LoadTypeLib()。#import語句會在工程可執(zhí)行程序輸出目錄中產(chǎn)生兩個文件,分別為*.tlh(類型庫頭文件)及*.tli(類型庫實現(xiàn)文件),它們分別為每一個接口產(chǎn)生智能指針,并為各種接口方法、枚舉類型,CLSID等進(jìn)行聲明,創(chuàng)建一系列包裝方法。
××××××××××××××××××××××××××××××××××××轉(zhuǎn) ××××××××
好了第二步說完了 ,開始說第三步了。
第三步:如同世界上的其他組件庫一樣 使用前要初始化 使用后卸載(這句話是老師說的 誰能就此展開)
如何初始化呢。
××××××××轉(zhuǎn)載××××××××××××××
在程序初始過程中需要初始化組件,一般可以用CoInitialize(NULL);來實現(xiàn),這種方法在結(jié)束時要關(guān)閉初始化的COM,可以用下面語句CoUnInitialize();來實現(xiàn)。在MFC中還可以采用另一種方法來實現(xiàn)初始化COM,這種方法只需要一條語句便可以自動為我們實現(xiàn)初始化COM和結(jié)束時關(guān)閉COM的操作,語句如下所示:
AfxOleInit()
為了讓程序更完美 建議這樣寫
if(!AfxOleInit())//這就是初始化COM庫 { AfxMessageBox("OLE初始化出錯!"); return FALSE; }
這個函數(shù)可以放置在TheApp對象的初始化函數(shù):InitInstance()中。
PS:如果你不知道theapp的初始化函數(shù) 請 點擊網(wǎng)頁的右上角的X號 因為這篇文章不適合你
××××××××轉(zhuǎn)載××××××××××××××
第四步:做這么多準(zhǔn)備工作 終于可以可以說哦那個ADO了。
首先看一看 ADO的那些東西我我們可以使用。
ADO包含一些頂層的對象:
連接(Connection),代表到數(shù)據(jù)庫的連接
記錄集(Recordset),代表數(shù)據(jù)庫記錄的一個集合
命令(Command),代表一個SQL命令
記錄(Record),代表數(shù)據(jù)的一個集合
流(Stream),代表數(shù)據(jù)的順序集合
錯誤(Error),代表數(shù)據(jù)庫訪問中產(chǎn)生的意外
字段(Field),代表一個數(shù)據(jù)庫字段
參數(shù)(Parameter),代表一個SQL參數(shù)
屬性(Property),保存對象的信息
通常來說我用到了 前三個對象。其他東西我不熟。
第五步:在MFC的對話框程序創(chuàng)建三個對象 ,就是那三個智能指針的對象。
這個對象(其實是否可以稱之為對象 我也不清楚 姑且稱之吧)輸入對話框類
下圖是我創(chuàng)建的結(jié)果
第六步: 剛才那三個智能指針對象 被我創(chuàng)建出來了。
既然創(chuàng)建出來了 就可以用了。在哪里用呢?既然這三個對象屬于對話框類,那么在對話框類的實例化對象中 就可以使用了。
注意以下內(nèi)容是核心代碼。
首先說一下核心代碼的整體思路。
A:鏈接數(shù)據(jù)庫 B:打開記錄集 相當(dāng)于用數(shù)據(jù)庫里面的表給 記錄集賦值 至此 表就存在于 內(nèi)存中了
C:使用ADO的相關(guān)函數(shù) 對記錄集進(jìn)行增刪改查 D:關(guān)掉記錄集 E:斷開鏈接
至此完成一次輪回。
第七步: 建立和數(shù)據(jù)庫的鏈接
打開數(shù)據(jù)庫 也可以稱之為 鏈接數(shù)據(jù)庫
由于數(shù)據(jù)的操作帶有很強的不確定性,所以對數(shù)據(jù)庫的操作大都有錯誤抓取 就是 Try Catch
HRESULT hr; try { //先創(chuàng)建連接實例 hr = m_pConnection.CreateInstance(__uuidof(Connection));//創(chuàng)建Connection對象 if (SUCCEEDED(hr)) { m_pConnection->ConnectionTimeout=600;// 鏈接數(shù)據(jù)庫時間限制 m_pConnection->CommandTimeout=120;// 也許是SQL語句執(zhí)行時間限制 //然后打開數(shù)據(jù)庫 OPEN函數(shù)的參數(shù)是很有講究的 //Open 方法可打開一個到數(shù)據(jù)源的連接。當(dāng)連接打開時,您可以對數(shù)據(jù)源執(zhí)行命令 //一個包含有關(guān)連接的信息的字符串值。該字符串由一系列被分號隔開的 parameter=value 語句組成的。 //一個字符串值,包含建立連接時要使用的用戶名稱。 //一個字符串值,包含建立連接時要使用的密碼。 //一個 ConnectOptionEnum 值,確定應(yīng)在建立連接之后(同步)還是應(yīng)在建立連接之前(異步)返回本方法。 hr = m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Home.mdb","","",adModeUnknown);// //ConnectionString 屬性有 5 個參數(shù): //Provider---》用于連接的提供者的名稱。 //File Name---》提供者特有的文件(例如,持久保留的數(shù)據(jù)源對象)的名稱,這些文件中包含預(yù)置的連接信息。 //Remote Provider--》當(dāng)打開客戶端連接時使用的提供者的名稱。(僅限于遠(yuǎn)程數(shù)據(jù)服務(wù)。) //Remote Server--》當(dāng)打開客戶端連接時使用的服務(wù)器的路徑名稱。(僅限于遠(yuǎn)程數(shù)據(jù)服務(wù)。) //url---》標(biāo)識資源(比如文件或目錄)的絕對 URL。 //打開模式 /* adModeUnknown = 0, adModeRead = 1, adModeWrite = 2, adModeReadWrite = 3, adModeShareDenyRead = 4, adModeShareDenyWrite = 8, adModeShareExclusive = 12, adModeShareDenyNone = 16, adModeRecursive = 4194304 */
} } catch(_com_error e)///捕捉異常 { CString errormessage; errormessage.Format("連接數(shù)據(jù)庫失敗!/r/n錯誤信息:%s",e.ErrorMessage()); AfxMessageBox(errormessage);/// } AfxMessageBox("成功打開數(shù)據(jù)庫");
第八步:創(chuàng)建記錄集
m_pRecordset.CreateInstance(__uuidof(Recordset)); try { m_pRecordset->CursorLocation = adUseClient; //需要把數(shù)據(jù)傳輸給本地,應(yīng)用舉例是斷開數(shù)據(jù)庫進(jìn)行Recordset操作,即內(nèi)存中操作 //而不是寫入遠(yuǎn)端數(shù)據(jù)庫。相反的有 adUseServer 是指直接在數(shù)據(jù)庫中操作。 m_pRecordset->Open("SELECT * FROM Jianghu",//SQL 語句 m_pConnection.GetInterfacePtr(),
adOpenDynamic,//游標(biāo)類型 adLockOptimistic,//樂觀鎖 adCmdText);//命令類型 /* 當(dāng)您首次打開一個 Recordset 時,當(dāng)前記錄指針將指向第一個記錄,同時 BOF 和 EOF 屬性為 False。如果沒有記錄,BOF 和 EOF 屬性為 True
*/ } catch(_com_error *e) { AfxMessageBox(e->ErrorMessage()); } m_MyDataGrid.putref_DataSource(m_pRecordset);//將對象和DataGrid控件鏈接在一起的函數(shù)。 在VC6 是 SetRefDataSource AfxMessageBox("成功打開記錄集");
第九步:給表增加行
// 數(shù)據(jù)庫操作之:增 //特別需要游標(biāo)的位置 和 數(shù)據(jù)庫主鍵不可以重復(fù) 不然報錯 //第一步:定義四個字符串 用于獲取 Edit控件中數(shù)據(jù) CString ID ="2"; CString Name ="風(fēng)清"; CString XingBie ="男"; CString ZhaoShu ="獨孤九劍"; m_CEdit_ID.GetWindowTextA(ID);//獲取編輯框文本,記錄在szText變量中 m_CEdit_Name.GetWindowTextA(Name); m_CEdit_Xingbie.GetWindowTextA(XingBie); m_CEdit_ZhaoShu.GetWindowTextA(ZhaoShu);
//第二步:正是開始庫的操作 try {
//A :選擇游標(biāo)位置 m_pRecordset->MoveFirst();//新建的數(shù)據(jù)會添加到DataGrid的最后一條 但在數(shù)據(jù)庫里面是第一條。 //B:提醒系統(tǒng)我要增肌數(shù)據(jù)了 m_pRecordset->AddNew(); //C: 調(diào)用函數(shù)PutCollect 修改數(shù)據(jù) m_pRecordset->PutCollect("ID",_variant_t(ID)); m_pRecordset->PutCollect("NameGsz",_variant_t(Name)); m_pRecordset->PutCollect("XinBie",_variant_t(XingBie)); m_pRecordset->PutCollect("ZhaoShu",_variant_t(ZhaoShu)); //D: 更新數(shù)據(jù)庫 也可以理解為寫入數(shù)據(jù)庫 m_pRecordset->Update(); } catch (_com_error e) { AfxMessageBox("增加數(shù)據(jù)庫失敗!");///顯示錯誤信息
} AfxMessageBox("增加數(shù)據(jù)庫成功");
|