zoukankan      html  css  js  c++  java
  • 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> 创建记录集对象

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

  • 相关阅读:
    常见S1信令交互流程
    pthread_cond_wait避免线程空转
    sqlite:多线程操作数据库“database is locked”解决方法(二)
    sqlite:多线程操作数据库“database is locked”解决方法
    大端 小端
    关于天气分类的贝叶斯预测
    n 支队伍比赛,分别编号为 0,1,2。。。。n-1,已知它们之间的实力对比关系, 存储在一个二维数组 w[n][n]中,w[i][j] 的值代表编号为 i,j 的队伍中更强的一支。
    AC自动机 多模式匹配
    浮点数转换成二进制
    在一个缓冲去内实现三个栈,使用自有链表记录空闲块
  • 原文地址:https://www.cnblogs.com/zhaoxinshanwei/p/3857346.html
Copyright © 2011-2022 走看看