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> 创建记录集对象
- _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;
- }
该段代码演示了如何读取数据库表内的数据。其原理是如果没有遇到表结束标志adoEOF,则用GetCollect(字段名)来获取当前记录指针所指的字段值,然后再用MoveNext()方法移动到下一条记录位置。
双击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>...
- }
该段代码演示了如何修改记录中的字段值:
将记录指针移动到要修改记录的位置处,直接
- {
- <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()来更新数据库即可。
ADO接口之_RecordsetPtr的更多相关文章
- ADO接口简介
源地址:http://blog.csdn.net/xiaobai1593/article/details/7449151 参考: 1. 百度文库:http://wenku.baidu.com/view ...
- ADO接口
转自百度文库 ADO中最重要的对象有三个:Connection.Recordset和Command,分别表示连接对象.记录集对象和命令对象. 三个对象对应的智能指针分别是:_ConnectionPtr ...
- 第三次上机,ADO接口的使用
<html> <head> <title>Reg</title> </head> <body><center> &l ...
- VC++ ADO相关
<VC对ADO的操作> ADO概述: ADO是Microsoft为最新和最强大的数据访问范例 OLE DB 而设计的,是一个便于使用的应用程序层接口. ADO 使您能够编写应用程序以通过 ...
- 智能指针 ADO数据库连接
ADO库包含三个基本接口:_ConnectionPtr接口._CommandPtr接口和_RecordsetPtr接口._ConnectionPtr接口返回一个记录集或一个空指针.通常使用它来创建一个 ...
- 读书笔记——数据库的ADO开发总结
基本上是对 ADO+开发指南.pdf 的摘抄和总结,以及个人心得. 文章末尾有<ADO+开发指南.pdf>的资源下载,附带个人批注. --------------------------- ...
- VC操作ADO的基本策略
一.ADO概述 ADO是Microsoft为最新和最强大的数据访问范例 OLE DB 而设计的,是一个便于使用的应用程序层接口.ADO 使您能够编写应用程序以通过 OLE. DB 提供者访问和操作数据 ...
- ADO数据库链接
一.数据库操作准备 // --------------------------------------------------------------------------------------- ...
- MFC中使用ADO方式连接数据库
文章转自:http://blog.sina.com.cn/s/blog_a43aba5601014z8h.html 一.数据库操作准备 1.导入ADO动态链接库 在工程的stdafx.h中加入如下语句 ...
随机推荐
- Android Studio中 ADB WIFI插件进行无线调试实践
首先要确保电脑和手机在同一个局域网中.具体步骤如下 1.Android Studio中安装ADB WIFI插件.安装成功后重启Android Studio.(没有安装过插件的同仁,请自己搜索) 2.手 ...
- 32位汇编基础_cpu 寄存器
32位通用寄存器 EAX EBX ECX EDX EBP ESP ESI EDI 八个寄存器都可以作为普通的数据寄存器使用.但有的有特殊的用途: EAX 为累加器, ECX 为计数器, E ...
- [转]Java IDE 之 IntelliJ IDEA 2017
参考链接1:http://blog.csdn.net/u012364631/article/details/47682011 IDEA Community(社区版) 使用Maven创建Web工程 并部 ...
- sqoop导出到mysql中文乱码问题总结、utf8、gbk
sqoop导出到mysql中文乱码问题总结.utf8.gbk 今天使用sqoop1.4.5版本的(hadoop使用cdh5.4)因为乱码问题很是头痛半天.下面进行一一总结 命令: [root@sdzn ...
- Spring cloud Hystrix使用@HystrixCommand使用Hystrix组件及@EnableCircuitBreaker原理介绍
通过@HystrixCommand注解实现在Spring Cloud使用Hystrix组件相关的工程 cloud-registration-center:注册中心 cloud-service-hyst ...
- MVC中@Html.Action的用法
MVC项目中如果有公共部分的代码就可以单独拿出来作为控件来用(比如头部和底部代码).跟ASP.NET中的ASCX实现的效果一样,但MVC比它方便的多. 想要实现该效果,需要知道@Html.Action ...
- 2.spring整合ehcache 注解实现查询缓存,并实现实时缓存更新或删除
转自:http://www.importnew.com/23358.html 写在前面:上一篇博客写了spring cache和ehcache的基本介绍,个人建议先把这些最基本的知识了解了才能对今天主 ...
- 34.TokenInterceptor防止表单重复提交
转自:https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html 由于某些原因,用户在进行类似表单提交的操作后,以为表单未被提交,会进行多次的 ...
- div高度自适应的问题
对象height:100%并不能直接产生效果,是因为跟其父对象有关. #center{height:100%;} 上面的css样式是无效的,不会产生任何效果. 需要改写: html,body{ m ...
- 实用 Linux 命令行使用技巧集锦
最近在Quora上看到一个问答题目,关于在高效率Linux用户节省时间Tips.将该题目的回答进行学习总结,加上自己的一些经验,记录如下,方便自己和大家参考. 下面介绍的都是一些命令行工具,这些工具在 ...