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

_RecordsetPtr智能指针,它是专门为通过记录集操作数据库而设立的指针,通过该接口可以对数据库的表内的记录、字段等进行各种操作。

要搞清楚:数据库和ADO的记录集是两个不同的概念,是存在于不同物理位置的两个存储空间。

                   记录集相当于是实际数据的一份拷贝。 正因为记录集是相对脱离数据库而存在的, 所以才存在后面将要介绍的Open方法中涉及的光标类型和锁定类型这两个问题。

_RecordsetPtr接口的使用方法

1> 创建记录集对象

  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锁定类型,它可以是以下值之一,请看如下枚举结构

  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表的记录集的语句如下:

  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()函数如下:

  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()函数如下:

  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. }  

该段代码演示了如何修改记录中的字段值:

将记录指针移动到要修改记录的位置处,直接

  • {  
  • <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()函数如下:

  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()来更新数据库即可。