轉自:http://hi.baidu.com/%CE%D2%B6%CF%C1%CB%CB%BC%C4%EE/blog/item/e057c526c6af6c29c995596e.html
_RecordsetPtr智能指針,它是專門爲通過記錄集操作數據庫而設立的指針,通過該接口可以對數據庫的表內的記錄、字段等進行各種操作。
要搞清楚:數據庫和ADO的記錄集是兩個不同的概念,是存在於不同物理位置的兩個存儲空間。
記錄集相當於是實際數據的一份拷貝。 正因爲記錄集是相對脫離數據庫而存在的, 所以才存在後面將要介紹的Open方法中涉及的光標類型和鎖定類型這兩個問題。
_RecordsetPtr接口的使用方法
1> 創建記錄集對象
- _ConnectionPtr m_pRecordset;
- m_pRecordset.CreateInstance(__uuidof(Recorset));
創建記錄集對象,只是爲它分配內存空間,記錄集中不含任何數據。
2> 打開記錄集
記錄集對象是用來獲得數據庫中的數據並對其操作的,所以還要打開記錄集,從數據庫中取得數據記錄。可有多種方法打開記錄集,如使用_CommondPt::.Execute()來返回一個記錄集,或是用_Recordset::Open()方法來打開一個記錄集;
下面只介紹Open()方法:
函數原型爲:
HRESULT Recordset::Open(const _variant_t& Source,const _variant_t& ActiveConnection,enum CursorTypeEnum CursorType,enum LockTypeEnum LockType,long Options)
參數:
Source是數據查詢字符串;
ActiveConnection是已經建立好的連接(我們需要用Connection對象指針來構造一個_variant_t對象);
CursorType 光標類型,它是枚舉CursorTypeEnum中的一個值;
LockType 鎖定類型 它是枚舉LockTypeEnum中的一個值;
Options 指定Source的類型;
光標類型CursorType,可取如下值之一:
adOpenUnspecified=-1 不作特別指定
adOpenForwardOnly=0 默認值,前滾靜態光標。(這種光標只能向前瀏覽記錄集,比如用MoveNext向前滾動,這種方式可節省資源,提高瀏覽速度,但諸如BookMark、RecordCount、AbsolutePosition、AbsolutePage都不能使用。)
adOpenKeyset=1 鍵集遊標,採用這種光標的記錄集看不到其它用戶的新增、刪除操作,但對於更新原有記錄的操作對你是可見的。
adOpenDynamic=2 動態光標,所有數據庫的操作都會立即在用戶記錄集上反應出來。
adOpenStatic=3 靜態遊標。它爲記錄產生一個靜態備份,其他用戶的新增、刪除、更新操作對你的記錄集來說是不可見的。
LockType鎖定類型,它可以是以下值之一,請看如下枚舉結構
- enum LockTypeEnum
- {
- adLockUnspecified=-1,
- //未指定
- adLockReadOnly=1,
- //只讀記錄集,默認值。無法更改數據。
- adLockPessimistic=2,
- //悲觀鎖定方式。只有在調用Update方法時才鎖定記錄。這是最安全的鎖定機制
- adLockOptimistc=3,
- //樂觀鎖定方式,只有在你調用Update方法時才鎖定記錄。
- adLockBatchOptimistic=4
- //樂觀分批更新。編輯時記錄不會鎖定,更改、插入及刪除是在批處理模式下完成。
- }
Options可以取如下值之一:
adCmdText: 表明CommandText是文本命令。
adCmdTable:表明CommandText是一個表名。
adCmdProc:表明CommandText是一個存儲過程。
adCmdUnknown:未知。
例如:假設m_pConnection是我們已經建立好的連接,我們使用_RecordsetPtr接口的Open方法打開Employees表的記錄集的語句如下:
- m_pRecordset->Open("SELECT * FROM Employees", _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText);
3> 指針的移動
移動記錄指針可以通過MoveFirst()方法移動到第一條記錄,MoveLast()方法移動到最後一條記錄,MovePrevious()方法移動到當前記錄的前一條記錄,MoveNext()方法移動到當前記錄的下一條記錄。也可以使用Move(記錄號)移動記錄指針到需要位置。
注意:Move()方法是相對於當前記錄來移動指針位置的。正值向後移動,負值向前移動。如Move(3),當前記錄是3時,它將從記錄3開始往後再移動3條記錄位置。
兩個_RecordsetPtr屬性:
BOF 屬性表示記錄集第一條記錄之前的遊標,用來判斷記錄集是否爲空
EOF(通常會rename爲adoEOF) 屬性表示記錄集最後一條記錄之後的遊標,用來判斷是否結束
4> 數據的讀取
GetCollect(字段名)來獲取當前記錄指針所指的字段值
返回值的類型爲:_variant_t
5> 數據的更新
用PutCollect(字段名,值)將新值寫入,並Update()更新到數據庫
6> 插入記錄
先移動記錄指針到要插入的位置,用AddNew()插入一條記錄,然後用PutCollect(字段名,值)寫入值,最後用Update()更新到數據庫;
7> 刪除記錄
刪除單條記錄:先移動記錄指針到合適的位置,然後用Delete()方法刪除它(取參數adAffectCurrent,表示操作隻影響當前的記錄),並用Update()來更新數據庫;
8> 關閉記錄集
直接用Close()方法關閉記錄集並賦予其空值。代碼如下:
m_pRecordset->Close();
m_pRecordset=NULL;
類似於_ConnectionPtr的關閉方法;
示例:
例程RecordsetPtr演示使用_RecordsetPtr指針通過記錄集操作數據庫。
打開VC++ 6.0,新建一個基於對話框的工程RecordsetPtr。在對話框IDD_RECORDSETPTR_DIALOG中進行編輯:
使用三個Group Box分成四個部分,第一部分演示如何讀取數據庫數據;第二部分演示如何修改數據庫;第三部分演示如何向數據庫中插入數據;第四部分演示如何刪除數據庫中的數據。
使用ClassWizard給列表框IDC_LIST1創建CListBox變量m_list1:
雙擊IDC_BTN_READREC按鈕,並編輯OnBtnReadrec()函數如下:
- void CRecordsetPtrDlg::OnBtnReadrec()
- {
- _ConnectionPtr m_pConnection;
- _RecordsetPtr m_pRecordset;
- try
- {
- m_pConnection.CreateInstance(__uuidof(Connection));
- m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb","","",adModeUnknown);
- }
- catch(_com_error e)
- {
- CString errormessage;
- errormessage.Format("連接數據庫失敗!/r錯誤信息:%s",e.ErrorMessage());
- AfxMessageBox(errormessage);
- return;
- }
- try
- {
- m_pRecordset.CreateInstance("ADODB.Recordset");
- m_pRecordset->Open("SELECT EmployeeID,FirstName,LastName FROM Employees WHERE City='London'", _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText);
- }
- catch(_com_error &e)
- {
- AfxMessageBox(e.Description());
- }
- _variant_t vEmployeeID,vFirstName,vLastName;
- try
- {
- while(!m_pRecordset->adoEOF)
- {
- vEmployeeID=m_pRecordset->GetCollect(_variant_t((long)0));
- //取得第1列的值,從0開始計數,你也可以直接列出列的名稱,如下一行
- vFirstName=m_pRecordset->GetCollect("FirstName");
- vLastName=m_pRecordset->GetCollect("LastName");
- CString strtemp;
- if(vEmployeeID.vt!=VT_NULL)
- {
- strtemp.Format("%d",vEmployeeID.lVal);
- }
- if(vFirstName.vt!=VT_NULL)
- {
- strtemp+=" ";
- strtemp+=(LPCTSTR)(_bstr_t)vFirstName;
- }
- if(vLastName.vt!=VT_NULL)
- {
- strtemp+=" ";
- strtemp+=(LPCTSTR)(_bstr_t)vLastName;
- }
- m_list1.AddString(strtemp);
- m_list1.AddString("/n");
- m_pRecordset->MoveNext();
- }
- }
- catch(_com_error &e)
- {
- AfxMessageBox(e.Description());
- }
- //釋放資源
- m_pRecordset->Close();
- m_pRecordset=NULL;
- m_pConnection->Close();
- m_pConnection=NULL;
- }
雙擊IDC_BTN_CHANGE按鈕,並編輯OnBtnChange()函數如下:
- void CRecordsetPtrDlg::OnBtnChange()
- {
- <span style="white-space:pre"> </span>...
- try
- {
- m_pRecordset.CreateInstance("ADODB.Recordset");
- m_pRecordset->Open("SELECT EmployeeID,FirstName,LastName FROM Employees WHERE (City='London') AND (EmployeeID=6)",
- _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText);
- }
- catch(_com_error &e)
- {
- AfxMessageBox(e.Description());
- }
- try
- {
- while(!m_pRecordset->adoEOF)
- {
- //更改記錄值
- m_pRecordset->PutCollect("LastName",_variant_t("Jackson"));
- m_pRecordset->MoveNext();
- }
- //刷新到硬盤中
- m_pRecordset->Update();
- }
- catch(_com_error* e)
- {
- AfxMessageBox(e->ErrorMessage());
- }
- <span style="white-space:pre"> </span>...
- }
將記錄指針移動到要修改記錄的位置處,直接用PutCollect(字段名,值)將新值寫入,並Update()更新到數據庫即可。
雙擊IDC_BTN_NEW按鈕,並編輯OnBtnNew()函數如下:
- void CRecordsetPtrDlg::OnBtnNew()
- {
- <span style="white-space:pre"> </span>...
- try
- {
- m_pRecordset.CreateInstance("ADODB.Recordset");
- m_pRecordset->Open("SELECT * FROM Employees", _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText);
- }
- catch(_com_error &e)
- {
- Â Â Â Â Â Â Â Â AfxMessageBox(e.Description());Â Â
- Â Â Â Â }Â Â
-     try Â
- Â Â Â Â {Â Â
- Â Â Â Â Â Â Â Â m_pRecordset->MoveLast();Â Â
- Â Â Â Â Â Â Â Â Â Â
-         //æå ¥è®°å½Â Â
- Â Â Â Â Â Â Â Â m_pRecordset->AddNew();Â Â
-         //å¡«å æ°æ®Â Â
- Â Â Â Â Â Â Â Â m_pRecordset->PutCollect("EmployeeID",_variant_t((long)10));Â Â
- Â Â Â Â Â Â Â Â m_pRecordset->PutCollect("FirstName",_variant_t("Mary"));Â Â
- Â Â Â Â Â Â Â Â m_pRecordset->PutCollect("LastName",_variant_t("Williams"));Â Â
- Â Â Â Â }Â Â
-     catch(_com_error *e) Â
- Â Â Â Â {Â Â
- Â Â Â Â Â Â Â Â AfxMessageBox(e->ErrorMessage());Â Â
- Â Â Â Â }Â Â
- Â Â Â Â Â Â
-     //æ´æ°å°å¤å Â
- Â Â Â Â m_pRecordset->Update();Â Â
-     ... Â
- }Â Â
å ç¨AddNew()æ¹æ³æ°å¢ä¸ä¸ªç©ºè®°å½ï¼åç¨PutCollect(å段åï¼å¼)è¾å ¥æ¯ä¸ªå段çå¼ï¼æåç¨Update()æ´æ°å°æ°æ®åºå³å¯ã
åå»IDC_BTN_DELETEæé®ï¼å¹¶ç¼è¾OnBtnDelete()å½æ°å¦ä¸ï¼
- void CRecordsetPtrDlg::OnBtnDelete() Â
- {Â Â
-     ... Â
-     try Â
- Â Â Â Â {Â Â
- Â Â Â Â Â Â Â Â m_pRecordset.CreateInstance("ADODB.Recordset");Â Â
-         m_pRecordset->Open("SELECT * FROM Employees", _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText); Â
- Â Â Â Â }Â Â
-     catch(_com_error &e) Â
- Â Â Â Â {Â Â
- Â Â Â Â Â Â Â Â AfxMessageBox(e.Description());Â Â
- Â Â Â Â }Â Â
-     try Â
- Â Â Â Â {Â Â
-         //å设å é¤ç¬¬10æ¡è®°å½Â Â
- Â Â Â Â Â Â Â Â m_pRecordset->MoveFirst();Â Â
- Â Â Â Â Â Â Â Â m_pRecordset->Move(9);Â Â
-         //åæ°adAffectCurrent为å é¤å½åè®°å½Â Â
-         m_pRecordset->Delete(<span style="background-color: rgb(204, 204, 204);">adAffectCurrent</span>); Â
- Â Â
-         //æ´æ°å°æ°æ®åºä¸Â Â
- Â Â Â Â Â Â Â Â m_pRecordset->Update();Â Â
- Â Â Â Â }Â Â
-     catch(_com_error *e) Â
- Â Â Â Â {Â Â
- Â Â Â Â Â Â Â Â AfxMessageBox(e->ErrorMessage());Â Â
- Â Â Â Â }Â Â
-     ... Â
- }Â Â
å å°è®°å½æé移å¨å°è¦å é¤çè®°å½çä½ç½®ï¼ç´æ¥ç¨Delete()æ¹æ³å é¤å®ï¼å¹¶ç¨Update()æ¥æ´æ°æ°æ®åºå³å¯ã