ADO接口之_RecordsetPtr

轉自:http://hi.baidu.com/%CE%D2%B6%CF%C1%CB%CB%BC%C4%EE/blog/item/e057c526c6af6c29c995596e.html

_RecordsetPtr智能指針,它是專門爲通過記錄集操作數據庫而設立的指針,通過該接口可以對數據庫的表內的記錄、字段等進行各種操作。

要搞清楚:數據庫和ADO的記錄集是兩個不同的概念,是存在於不同物理位置的兩個存儲空間。

                   記錄集相當於是實際數據的一份拷貝。 正因爲記錄集是相對脫離數據庫而存在的, 所以才存在後面將要介紹的Open方法中涉及的光標類型和鎖定類型這兩個問題。

_RecordsetPtr接口的使用方法

1> 創建記錄集對象

[cpp] view plain copy
  1. _ConnectionPtr m_pRecordset;  
  2. 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鎖定類型,它可以是以下值之一,請看如下枚舉結構

[cpp] view plain copy
  1. enum LockTypeEnum  
  2. {  
  3.     adLockUnspecified=-1,  
  4.     //未指定  
  5.     adLockReadOnly=1,  
  6.     //只讀記錄集,默認值。無法更改數據。  
  7.     adLockPessimistic=2,  
  8.     //悲觀鎖定方式。只有在調用Update方法時才鎖定記錄。這是最安全的鎖定機制  
  9.     adLockOptimistc=3,  
  10.     //樂觀鎖定方式,只有在你調用Update方法時才鎖定記錄。  
  11.     adLockBatchOptimistic=4   
  12.     //樂觀分批更新。編輯時記錄不會鎖定,更改、插入及刪除是在批處理模式下完成。  
  13. }  
關於光標和鎖定類型,對於一般用戶,建議您只作簡單瞭解,後面將進一步進行解說。

Options可以取如下值之一:

adCmdText: 表明CommandText是文本命令。

adCmdTable:表明CommandText是一個表名。

adCmdProc:表明CommandText是一個存儲過程。

adCmdUnknown:未知。

例如:假設m_pConnection是我們已經建立好的連接,我們使用_RecordsetPtr接口的Open方法打開Employees表的記錄集的語句如下:

[cpp] view plain copy
  1. 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()函數如下:

[cpp] view plain copy
  1. void CRecordsetPtrDlg::OnBtnReadrec()  
  2. {  
  3.     _ConnectionPtr m_pConnection;  
  4.     _RecordsetPtr m_pRecordset;  
  5.     try  
  6.     {  
  7.         m_pConnection.CreateInstance(__uuidof(Connection));  
  8.         m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb","","",adModeUnknown);  
  9.     }  
  10.     catch(_com_error e)  
  11.     {  
  12.         CString errormessage;  
  13.         errormessage.Format("連接數據庫失敗!/r錯誤信息:%s",e.ErrorMessage());  
  14.         AfxMessageBox(errormessage);  
  15.         return;  
  16.     }  
  17.     try  
  18.     {  
  19.         m_pRecordset.CreateInstance("ADODB.Recordset");  
  20.         m_pRecordset->Open("SELECT EmployeeID,FirstName,LastName FROM Employees WHERE City='London'", _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText);  
  21.     }  
  22.     catch(_com_error &e)  
  23.     {  
  24.         AfxMessageBox(e.Description());  
  25.     }  
  26.   
  27.     _variant_t vEmployeeID,vFirstName,vLastName;  
  28.     try  
  29.     {  
  30.         while(!m_pRecordset->adoEOF)  
  31.         {  
  32.             vEmployeeID=m_pRecordset->GetCollect(_variant_t((long)0));  
  33.             //取得第1列的值,從0開始計數,你也可以直接列出列的名稱,如下一行  
  34.             vFirstName=m_pRecordset->GetCollect("FirstName");  
  35.             vLastName=m_pRecordset->GetCollect("LastName");  
  36.   
  37.             CString strtemp;  
  38.             if(vEmployeeID.vt!=VT_NULL)  
  39.             {  
  40.                 strtemp.Format("%d",vEmployeeID.lVal);  
  41.             }  
  42.             if(vFirstName.vt!=VT_NULL)  
  43.             {  
  44.                 strtemp+=" ";  
  45.                 strtemp+=(LPCTSTR)(_bstr_t)vFirstName;  
  46.             }  
  47.             if(vLastName.vt!=VT_NULL)  
  48.             {  
  49.                 strtemp+=" ";  
  50.                 strtemp+=(LPCTSTR)(_bstr_t)vLastName;  
  51.             }  
  52.           
  53.             m_list1.AddString(strtemp);  
  54.             m_list1.AddString("/n");  
  55.             m_pRecordset->MoveNext();  
  56.         }  
  57.     }  
  58.     catch(_com_error &e)  
  59.     {  
  60.         AfxMessageBox(e.Description());  
  61.     }  
  62.   
  63.     //釋放資源  
  64.     m_pRecordset->Close();  
  65.     m_pRecordset=NULL;  
  66.     m_pConnection->Close();  
  67.     m_pConnection=NULL;  
  68. }  
該段代碼演示瞭如何讀取數據庫表內的數據。其原理是如果沒有遇到表結束標誌adoEOF,則用GetCollect(字段名)來獲取當前記錄指針所指的字段值,然後再用MoveNext()方法移動到下一條記錄位置。

雙擊IDC_BTN_CHANGE按鈕,並編輯OnBtnChange()函數如下:

[cpp] view plain copy
  1. void CRecordsetPtrDlg::OnBtnChange()  
  2. {  
  3. <span style="white-space:pre">  </span>...  
  4.     try  
  5.     {  
  6.         m_pRecordset.CreateInstance("ADODB.Recordset");  
  7.         m_pRecordset->Open("SELECT EmployeeID,FirstName,LastName FROM Employees WHERE (City='London') AND (EmployeeID=6)",  
  8.         _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText);  
  9.     }  
  10.     catch(_com_error &e)  
  11.     {  
  12.         AfxMessageBox(e.Description());  
  13.     }  
  14.     try  
  15.     {  
  16.         while(!m_pRecordset->adoEOF)  
  17.         {  
  18.             //更改記錄值  
  19.             m_pRecordset->PutCollect("LastName",_variant_t("Jackson"));  
  20.             m_pRecordset->MoveNext();  
  21.         }  
  22.       
  23.         //刷新到硬盤中  
  24.         m_pRecordset->Update();  
  25.     }  
  26.     catch(_com_error* e)  
  27.     {  
  28.         AfxMessageBox(e->ErrorMessage());  
  29.     }  
  30. <span style="white-space:pre">  </span>...  
  31. }  
該段代碼演示瞭如何修改記錄中的字段值:

將記錄指針移動到要修改記錄的位置處,直接用PutCollect(字段名,值)將新值寫入,並Update()更新到數據庫即可。

雙擊IDC_BTN_NEW按鈕,並編輯OnBtnNew()函數如下:

[cpp] view plain copy
  1. void CRecordsetPtrDlg::OnBtnNew()  
  2. {  
  3. <span style="white-space:pre">  </span>...  
  4.     try  
  5.     {  
  6.         m_pRecordset.CreateInstance("ADODB.Recordset");  
  7.         m_pRecordset->Open("SELECT * FROM Employees", _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText);  
  8.     }  
  9.     catch(_com_error &e)  
  10.     {  
  11.         AfxMessageBox(e.Description());  
  12.     }  
  13.     try  
  14.     {  
  15.         m_pRecordset->MoveLast();  
  16.           
  17.         //插入记录  
  18.         m_pRecordset->AddNew();  
  19.         //填充数据  
  20.         m_pRecordset->PutCollect("EmployeeID",_variant_t((long)10));  
  21.         m_pRecordset->PutCollect("FirstName",_variant_t("Mary"));  
  22.         m_pRecordset->PutCollect("LastName",_variant_t("Williams"));  
  23.     }  
  24.     catch(_com_error *e)  
  25.     {  
  26.         AfxMessageBox(e->ErrorMessage());  
  27.     }  
  28.       
  29.     //更新到外存  
  30.     m_pRecordset->Update();  
  31.     ...  
  32. }  
该段代码演示如何插入记录:

先用AddNew()方法新增一个空记录,再用PutCollect(字段名,值)输入每个字段的值,最后用Update()更新到数据库即可。

双击IDC_BTN_DELETE按钮,并编辑OnBtnDelete()函数如下:

[cpp] view plain copy
  1. void CRecordsetPtrDlg::OnBtnDelete()  
  2. {  
  3.     ...  
  4.     try  
  5.     {  
  6.         m_pRecordset.CreateInstance("ADODB.Recordset");  
  7.         m_pRecordset->Open("SELECT * FROM Employees", _variant_t((IDispatch*)m_pConnection,true), adOpenStatic, adLockOptimistic, adCmdText);  
  8.     }  
  9.     catch(_com_error &e)  
  10.     {  
  11.         AfxMessageBox(e.Description());  
  12.     }  
  13.     try  
  14.     {  
  15.         //假设删除第10条记录  
  16.         m_pRecordset->MoveFirst();  
  17.         m_pRecordset->Move(9);  
  18.         //参数adAffectCurrent为删除当前记录  
  19.         m_pRecordset->Delete(<span style="background-color: rgb(204, 204, 204);">adAffectCurrent</span>);  
  20.   
  21.         //更新到数据库中  
  22.         m_pRecordset->Update();  
  23.     }  
  24.     catch(_com_error *e)  
  25.     {  
  26.         AfxMessageBox(e->ErrorMessage());  
  27.     }  
  28.     ...  
  29. }  
该段代码演示了如何删除记录:

先将记录指针移动到要删除的记录的位置,直接用Delete()方法删除它,并用Update()来更新数据库即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章