ADO数据库编程

ADO数据库编程

中大型的数据库管理信息系统(MIS)的开发,一般很少用VC来完成(因为开发效率低,不过运行效率很高),而是使用VB, C#,Java等开发效率较高的语言。但小型MIS系统完全可以用VC来实现。下面讲解VC中访问数据库的基本技术。

一、四种数据库访问技术

  1. ODBCOpen Database Connectivity

开放式数据库连接,是一种用来在数据库管理系统(DBMS)中存取数据的标准应用程序接口。有ODBC API和MFC ODBC两种开发技术。

  1. DAO(Data Access Object )

即数据访问对象集,是Microsoft提供的基于一个数据库对象集合的访问技术。和ODBC一样,他们都是Windows API的一部分,可以独立于(DBMS)进行数据库的访问。

DAO跟ODBC的区别是:

访问机制不同!ODBC工作依赖于数据库制造商(MS SQL Server, Oracle,Sybase等)提供的驱动程序。使用ODBC API的时候,Windows的ODBC管理程序,把对数据库的访问请求传递给正确的驱动程序,驱动程序再使用SQL语句指示DBMS完成数据库访问工作。DAO则绕开中间环节,直接使用数据库引擎(Microsoft Jet Database Engine)提供的各种对象进行工作。速度比ODBC快。

  1. OLE DBObject Link and Embedding Database

非常底层,基于COM接口技术;功能强大灵活,但编程非常非常非常麻烦,使用ADO只需要3-5行代码的事情,用OLEDB却需要将近200-300行代码才能完成。WinCE目前不支持ADO,但支持OLEDB。推荐阅读文章:VC++实战OLEDB编程(一)至(九)

http://gamebabyrocksunblog.163.com/blog/static/571534632008101083957499/

  1. ADO(ActiveX Data Object)

是建立在OLE DB之上的高层数据库访问技术,是对OLEDB的封装, 微软为我们提供了丰富的COM组件(包括ActiveX)来访问各种关系型/非关系型数据库。特点是简单、易用,这也是为什么大多数数据库应用软件开发者选择ADO的重要原因。

       下面重点讲解使用ADO连接数据库的方法。

二、ADO对象

ADO是一个面向对象的COM组件库,用ADO访问数据库,其实就是利用ADO对象来操作数据库中的数据,所以我们首先要撑握ADO的对象。ADO对象有:

  1. 连接对象(connection):

连接对象用于与数据库建立连接,执行查询及进行事务处理。在连接时必须指定使用何种数据库的OLEDB供应者。

  1. 命令对象(Command):

可以执行数据库操作命令(如查询,修改,增加和删除)。用命令对象执行一个查询字串,可以返回一个记录集合。

  1. 记录集对象(Recordset):

用于表示查询返回的结果集,它可以在结果集中增加,删除,修改和移动记录。当建立一个记录集时,一个游标就自动建立了,查询所产生的记录就放在本地的游标中,游标有四种类型:仅能向前移动的游标,静态游标,键集游标和动态游标。记录集对象是对数据库进行查询和修改的主要对象。

  1. 字段对象(Fields字段集合对象,Field字段对象):

字段对象用于表示数据库或记录集中的信息,包括列值等信息。一个记录集或一个数据库中的表包括了多行记录,若将其当做二维网格,字段将是网格中的列,每个字段分别有名称,数据类型和值等属性,字段中包括了来自数据库中的真实数据。要修改其中的数据可在记录集中修改Filed字段对象,也可以通过在记录集中访问Fields字段集合对象,再定位要修改的Filed字段对象。对记录集的修改将最终被传送给数据库。

  1. 参数对象(Parameter):

是和命令对象联合使用的一个对象。当命令对象执行的查询是一个有参数的查询时,就要用参数对象来为命令对象提供参数信息和数据。

下面我们先看一个简单的通过ADO控件访问数据库的例子,然后再学习如何通过上述ADO对象访问数据库。

三、通过ADO控件访问数据库示例

下面以Microsoft Office Access数据库为例,讲解通过ADO控件访问数据库的方法。这种方法基本不用编写代码,就可以完成对数据库的访问,非常方便。

1、在Access中建立数据库student.mdb,并添加表stu_info,如下图:

这里的字段名使用了中文,只是为了教学方便,建议在实际工作中使用英文字段名。

2、建立一个MFC对话框工程AdoCtrl

3、在对话框界面编辑器中增加如下的2个ADO控件:

ADO Data控件,用于建立数据库连接。

ADO DataGrid控件,用于表示一个结果记录集。

在对话框编辑器中-->右键菜单-->选择Insert ActiveX Control-->在出现的对话框中选择Microsoft ADO Data Control,Version 6.0-->点OK,这样ADO Data控件IDC_ADODC1就加入到对话框中了;

同样方法,选择Microsoft DataGrid Control,Version 6.0加入到对话框中。这样DataGrid控件IDC_DATAGRID1就加入到对话框中了。

4、设置对话框中连接控件的属性

设置ADO Data控件的属性:在属性对话框中选择Control页面,选择Use Connection String选项,点Build按钮,在出现的对话框中选择Microsoft Jet 4.0 OLEDB Provider提供者。点下一步,选择刚建立的Access数据库文件名称student.mdb。点测试连接,应能连接数据库通过。再次打开ADO Data控件的属性设置,选择RecordeSource页面,在Command Type中选择2-adCmdTable,在Table Or StoredProcedure Name中选择stu_info表。

设置DataGrid控件的属性:在属性对话框中选择Control页面,选中Allow AddNewAllow Delete复选框,再选择All页面,设置DataSource参数为连接控件的IDIDC_ADODC1

5、运行该程序

将可以在对话框中连接数据库,并取出表中的数据显示在Grid控件中。如下图:

四、预备知识:数据类型_bstr_t和_variant_t

       VC可以连接各种数据库,而不同数据库对数据类型的定义各有不同,为了在VC中对数据库中的各种类型进行统一的表达,我们需要用到如下知识:

4.1 数据类型BSTR

BSTR是BASIC中字符串类型数据的表示方式,是一个指向 UNICODE 字符串的指针。有关 BSTR 的处理函数,参见下表。string

API 函数

说明

SysAllocString()

申请一个 BSTR 指针,并初始化为一个字符串

SysFreeString()

释放 BSTR 内存

SysAllocStringLen()

申请一个指定字符长度的 BSTR 指针,并初始化为一个字符串

SysAllocStringByteLen()

申请一个指定字节长度的 BSTR 指针,并初始化为一个字符串

SysReAllocStringLen()

重新申请 BSTR 指针

CString类

说明

AllocSysString()

从 CString 得到 BSTR

SetSysString()

重新申请 BSTR 指针,并复制到 CString 中

CComBSTR是BSTR 的封装类。在 atlbase.h 中定义

Append ()、AppendBSTR()、AppendBytes()、ArrayToBSTR()、BSTRToArray()、AssignBSTR()、 Attach()、Detach()、Copy()、CopyTo()、Empty()、Length()、ByteLength()、 ReadFromStream()、WriteToStream()、LoadString()、ToLower()、ToUpper()
运算符重载:!,!=,==,<,>,&,+=,+,=,BSTR

太多了。详细资料,查看MSDN 吧。CComBSTR类简化了对BSTR类型的使用

4.2 数据类型VARIANT

C++、BASIC、Java、Pascal、Script......计算机语言多种多样,而它们各自又都有自己的数据类型,COM 产生目的,其中之一就是要跨语言。而 VARIANT 数据类型就具有跨语言的特性,同时它可以表示(存储)任意类型的数据。

另外,使用CComVariant类可简化VARIANT,如:VARIANT v = CComVariant(任意C++类型);

4.3 _bstr_t类封装数据类型BSTR

_bstr_t是一个对BSTR完整封装类,实际上它隐藏了底层的BSTR。它提供各种构造函数和操作符来访问底层的C语言风格的字符串。然而,_bstr_t却没有访问BSTR本身的操作符,所以一个_bstr_t类型的字符串不能被作为输出参数传给一个COM方法。如果你需要一个BSTR*参数,使用类CComBSTR是比较容易的方式。

一个_bstr_t字符串能够传给一个接收参数类型为BSTR的函数,只是因为下列3个条件同时满足。首先,_bstr_t有一个向wchar_t*转换的转换函数;其次,对编译器而言,因为BSTR的定义,wchar_t*和BSTR有同样的含义;第三,_bstr_t内部含有的wchar_t*指向一片按BSTR的形式存储数据的内存。所以,即使没有文档说明,_bstr_t可以转换成BSTR,这种转换仍然可以正常进行。

注意_bstr_t也提供char*和wchar_t*之间的转换操作符。但不提倡使用,因为即使它们是非常量字符串指针,你也一定不能使用这些指针去修改它们指向的缓冲区的内容,因为那将破坏内部的BSTR结构。

一个用在自动化接口中的变量类型是VARIANT。它被用来在无类型(typeless)语言,如Jscript和VBScript,来传递数据。一个VARIANT可能含有很多不同类型的数据,例如long和IDispatch*。当一个VARIANT包含一个字符串,字符串被存成一个BSTR。

4.4 _variant_t类封装数据类型VARIANT

_variant_t是一个对VARIANT完整封装类,它提供很多构造函数和转换函数来操作一个VARIANT可能包含的大量的数据类型。这里,介绍与字符串有关的操作。

没有从一个_variant_t变量到一个MBCS字符串的直接转换。你需要创建一个临时的_bstr_t变量,使用提供Unicode到MBCS转换的另一个字符串类或者使用一个ATL转换宏。

不像_bstr_t,一个_variant_t变量可以被直接作为参数传递给一个COM方法。_variant_t继承自VARIANT类型,所以传递一个_variant_t来代替VARIANT变量是C++语言所允许的。

五、通过ADO对象编程访问数据库

通过ADO对象进行数据库开发的基本流程如下:

    1. 初始化COM库CoInitialize(NULL)
    2. 引入ADO库定义文件msado15.dll
    3. 用Connection对象连接数据库
    4. 利用建立好的连接,通过Connection、Command对象执行SQL命令,或利用Recordset对象取得结果记录集进行查询、处理。
    5. 使用完毕后关闭连接释放对象。

1、COM库的初始化和释放

我们可以使用CoInitialize(NULL)或者AfxOleInit()来初始化COM库,这项工作通常在CWinApp::InitInstance()的重载函数中完成:

       ::CoInitialize(NULL);

    /*if(!AfxOleInit())

       {

              AfxMessageBox("COM Error!");

              return FALSE;

       }*/

退出程序前,可以在CWinApp::ExitInstance()中使用CoUninitialize()释放COM。

2、用#import指令引入ADO类型库

在stdafx.h中加入如下语句:

#prgama warning (disable : 4146)

#include "icrsint.h"

#import "C:\Program Files\Common Files\System\ado\msado15.dll" \

 no_namespace rename("EOF""EndOfFile") rename("BOF""FirstOfFile")

这个#import语句的作用同我们熟悉的#include类似,编译时系统会为我们自动生成msado15.tlhmsado15.tli,这两个文件分别相当于.h和.cpp文件,是ADO COM组件相关的文件。头文件icrsint.h文件包含了VC++对COM扩展的一些预处理指令、宏等的定义。

注意1:你的环境中msado15.dll不一定在这个目录下,请按实际情况修改;

注意2:如果去掉#prgama warning (disable : 4146)则在编译的时候可能会出现如下警告,对此微软在MSDN中作了说明,并建议我们不要理会这个警告:

msado15.tlh(405) : warning C4146: unary minus operator applied to unsigned type, result still unsigned

3、创建Connection对象并连接数据库

首先添加一个指向Connection对象的指针:

_ConnectionPtr      m_pConnection;

下面的代码演示了如何创建Connection对象实例及如何连接数据库并进行异常捕捉。

BOOL CADOTest1Dlg::OnInitDialog()

{

       CDialog::OnInitDialog();

       HRESULT hr;

CString sConnectStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db1.mdb";

       try

{

              hr = m_pConnection.CreateInstance("ADODB.Connection");//创建Connection对象

              if (SUCCEEDED(hr))

                     hr = m_pConnection->Open(sConnectStr, "", "", adModeUnknown);//连数据库

       }

       catch(_com_error e)      //捕捉异常

       {

              CString sErr;

              sErr.Format("连接数据库失败!\r\n错误信息:%s", e.ErrorMessage());

              AfxMessageBox(sErr);   //显示错误信息

       }

}

这里,我们是通过Connection对象的Open方法来连接数据库的,该方法的原型如下:

HRESULT Connection15::Open (

_bstr_t           ConnectionString,  //连接数据库的字符串

_bstr_t           UserID,                 //数据库用户名

_bstr_t           Password,              //数据库密码

long               Options                 //连接选项

);

其中ConnectionString为连接字串,UserID是用户名, Password是登陆密码,Options是连接选项,用于指定Connection对象对数据的更新许可权,Options可以是如下几个常量:

    1. adModeUnknown:缺省。当前的许可权未设置。
    2. adModeRead:只读
    3. adModeWrite:只写
    4. adModeReadWrite:可以读写
    5. adModeShareDenyRead:阻止其它Connection对象以读权限打开连接
    6. adModeShareDenyWrite:阻止其它Connection对象以写权限打开连接
    7. adModeShareExclusive:阻止其它Connection对象打开连接
    8. adModeShareDenyNone:允许其它程序或对象以任何权限建立连接。

我们给出一些常用数据库的连接方式供大家参考:

  1. 通过JET数据库引擎对Access 2000数据库的连接

m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\test.mdb"

""""adModeUnknown);

  1. 通过DSN数据源对任何支持ODBC的数据库进行连接:

m_pConnection->Open("Data Source=adotest;UID=sa;PWD=;"""""adModeUnknown);

  1. 不通过DSN对SQL SERVER数据库进行连接:

m_pConnection->Open("driver={SQLServer};Server=127.0.0.1;DATABASE=vckbase;

UID=sa;PWD=139"""""adModeUnknown);

其中Server是SQL服务器的名称或者IP地址,DATABASE是库的名称。

Connection对象除Open方法外还有许多方法,我们先介绍Connection对象中两个有用的属性:ConnectionTimeOut与State ConnectionTimeOut,用来设置连接的超时时间,需要在Open之前调用,例如:

m_pConnection->ConnectionTimeout = 5;   //设置超时时间为5

m_pConnection->Open("Data Source=adotest;"""""adModeUnknown);

State属性指明当前Connection对象的状态,0表示关闭,1表示已经打开,我们可以通过读取这个属性来作相应的处理,例如:

if (m_pConnection->State)

m_pConnection->Close();                   //如果已经打开了连接则关闭它

4、执行SQL命令并取得结果记录集

为了取得结果记录集,我们定义一个指向Recordset对象的指针,并为其创建Recordset对象的实例:

_RecordsetPtr        m_pRecordset;

m_pRecordset.CreateInstance("ADODB.Recordset");

SQL命令的执行可以采用多种形式,下面我们一一进行阐述。

(1)、利用Connection对象的Execute方法执行SQL命令,原型如下:

_RecordsetPtr Connection15::Execute (

_bstr_t               CommandText,

VARIANT        *RecordsAffected,

long                  Options

);

其中CommandText通常是SQL命令字符串。RecordsAffected是操作完成后所影响的行数, Options表示CommandText中内容的类型,Options可以取如下值之一:

    1. adCmdText:表明CommandText是SQL文本命令
    2. adCmdTable:表明CommandText是一个表名
    3. adCmdProc:表明CommandText是一个存储过程
    4. adCmdUnknown:未知

Execute执行完后返回一个指向记录集的指针,下面我们给出示例代码并作说明:

//执行SQL命令:CREATE TABLE创建表格usersusers包含四个字段:

//整形ID,字符串username,整形age,日期型birthday

_variant_t RecordsAffected;

m_pConnection->Execute("CREATE TABLE users(ID INTEGER, username TEXT,

age INTEGER, birthday DATETIME)"&RecordsAffectedadCmdText);

//往表格里面添加记录

m_pConnection->Execute("INSERT INTO users(IDusernameagebirthday)

VALUES (1 'Washington'25'1970/1/1')"&RecordsAffectedadCmdText);

m_pConnection->Execute("INSERT INTO users(IDusernameagebirthday)

VALUES (2 'Aobama27'1970/1/1')"&RecordsAffectedadCmdText);

m_pConnection->Execute("INSERT INTO users(IDusernameagebirthday)

VALUES (3 Klten29'1970/1/1')"&RecordsAffectedadCmdText);

//将所有记录的age字段的值加一

m_pConnection->Execute("UPDATE users SET age = age+1"&RecordsAffectedadCmdText);

//执行SQL统计命令得到包含记录条数的记录集

m_pRecordset = m_pConnection->Execute("SELECT COUNT(*) FROM users",

&RecordsAffected, adCmdText);

_variant_t vIndex = (long)0;

_variant_t vCount = m_pRecordset->GetCollect(vIndex);//取得第一个字段的值放入vCount变量

m_pRecordset->Close();               //关闭记录集

CString message;

message.Format("共有%d条记录"vCount.lVal);

AfxMessageBox(message);           //显示当前记录条数

(2)、利用Command对象来执行SQL命令

_CommandPtr        m_pCommand;

m_pCommand.CreateInstance("ADODB.Command");

_variant_t       vNULL;

vNULL.vt = VT_ERROR;

vNULL.scode = DISP_E_PARAMNOTFOUND;        //定义为无参数

m_pCommand->ActiveConnection = m_pConnection;        //非常关键,将建立的连接赋值给它

m_pCommand->CommandText = "SELECT * FROM users";    //SQL命令字符串

m_pRecordset = m_pCommand->Execute(&vNULL&vNULLadCmdText);

//执行命令,取得记录集

在这段代码中我们只是用Command对象来执行了SELECT查询语句,Command对象在对存储过程的调用中能真正体现它的作用。

(3)、直接用Recordset对象进行查询取得记录集

m_pRecordset->Open("SELECT * FROM users"

_variant_t((IDispatch *)m_pConnectiontrue)

adOpenStaticadLockOptimisticadCmdText);

Open方法的原型如下:

HRESULT Recordset15::Open (

const _variant_t             &Source,

const _variant_t             &ActiveConnection,

enum CursorTypeEnum  CursorType,

enum LockTypeEnum    LockType,

long                             Options

);

其中:

    Source是数据查询字符串

    ActiveConnection是已经建立好的连接(我们需要用Connection对象指针来构造一个_variant_t对象)

    CursorType光标类型,它可以是以下值之一,请看这个枚举结构:

              enum CursorTypeEnum

              {

                     adOpenUnspecified = -1,    //不作特别指定

                     adOpenForwardOnly = 0,   //前滚静态光标。这种光标只能向前浏览记录集,

                                                               //比如用MoveNext向前滚动,这种方式可以提高

                                                               //浏览速度。但诸如BookMark,RecordCount,

                                                               //AbsolutePosition,AbsolutePage都不能使用

adOpenKeyset = 1,             //采用这种光标的记录集看不到其它用户的新增、

                                          //删除操作,但对于更新原有记录的操作对你是可

                                          //见的。

                     adOpenDynamic = 2,         //动态光标。所有数据库的操作都会立即在各用户

                                                               //记录集上反应出来。

                     adOpenStatic = 3                  //静态光标。它为你的记录集产生一个静态备份,

//但其它用户的新增、删除、更新操作对你的记录//集来说是不可见的。

              };

    LockType锁定类型,它可以是以下值之一,请看如下枚举结构:

              enum LockTypeEnum

              {

                     adLockUnspecified = -1,     //未指定

                     adLockReadOnly = 1,         //只读记录集

                     adLockPessimistic = 2,       //悲观锁定方式。数据在更新时锁定其它所有动

                                                               //作,这是最安全的锁定机制

                     adLockOptimistc = 3,         //乐观锁定方式。只有在你调用Update方法时才锁

                                                               //定记录。在此之前仍然可以做数据的更新、插入、

                                                               //删除等动作

                     adLockBatchOptimistic = 4,//乐观分批更新。编辑时记录不会锁定,更改、插

                                                               //入及删除是在批处理模式下完成。

              };

Options请参考本文中对Connection对象的Execute方法的介绍

5、记录集的遍历、更新

根据我们刚才通过执行SQL命令建立好的users表,它包含四个字段:ID,username,age,birthday

       以下的代码实现:打开记录集,遍历所有记录,删除第一条记录,添加三条记录,移动光标到第二条记录,更改其年龄,保存到数据库。

_variant_t       vUsernamevBirthdayvIDvAge;

_RecordsetPtr m_pRecordset;

m_pRecordset.CreateInstance("ADODB.Recordset");

m_pRecordset->Open("SELECT * FROM users"

_variant_t((IDispatch*)m_pConnectiontrue)

adOpenStaticadLockOptimisticadCmdText);

while (!m_pRecordset->adoEOF)

//这里为什么是adoEOF而不是EOF?还记得rename("EOF""adoEOF")这一句吗?

{

vID = m_pRecordset->GetCollect(_variant_t((long)0));

//取得第1列的值,从0开始计数,你也可以直接给出列的名称,如下一行

vUsername = m_pRecordset->GetCollect("username");

//取得username字段的值

vAge = m_pRecordset->GetCollect("age");

vBirthday = m_pRecordset->GetCollect("birthday");

//DEBUG方式下的OUTPUT窗口输出记录集中的记录

if     (vID.vt != VT_NULL && vUsername.vt != VT_NULL &&

 vOld.vt != VT_NULL && vBirthday.vt != VT_NULL)

       {

TRACE("id:%d,姓名:%s,年龄:%d,生日:%sr",

vID.lVal,(LPCTSTR)(_bstr_t)vUsername,

vOld.lVal(LPCTSTR)(_bstr_t)vBirthday) ;

       }

m_pRecordset->MoveNext();        //移到下一条记录

}

m_pRecordset->MoveFirst();               //移到首条记录

m_pRecordset->Delete(adAffectCurrent);    //删除当前记录

//添加三条新记录并赋值

for(int i=0;i<3;i++)

{

       m_pRecordset->AddNew();                 //添加新记录

       m_pRecordset->PutCollect("ID", _variant_t((long)(i+10)));

       m_pRecordset->PutCollect("username", _variant_t("奥巴马"));

       m_pRecordset->PutCollect("age", _variant_t((long)71));

       m_pRecordset->PutCollect("birthday", _variant_t("1930-3-15"));

}

//从第一条记录往下移动一条记录,即移动到第二条记录处

m_pRecordset->Move(1, _variant_t((long)adBookmarkFirst));

m_pRecordset->PutCollect(_variant_t("age"), _variant_t((long)55));  //修改其年龄

m_pRecordset->Update();     //保存到数据库中

6、关闭记录集与连接

记录集或连接都可以用Close方法来关闭

m_pRecordset->Close();        //关闭记录集

m_pConnection->Close();     //关闭连接

至此,我们已经熟悉了ADO操作数据库的大致流程

六、使用ADO对象进行数据库开发实例

  1. 创建一个MFC对话框工程AdoObject,并设计如下对话框界面。

2、关联变量:

3、在stdafx.h引入ADO库定义文件,包含头文件。

#prgama warning (disable : 4146)

#include "icrsint.h"

#import "C:\Program Files\Common Files\System\ado\msado15.dll" \

 no_namespace rename("EOF""EndOfFile") rename("BOF""FirstOfFile")

4、在AdoObject.cpp中,初始化COM库

BOOL AdoObjectApp::InitInstance()

{

       ::CoInitialize(NULL);

    /*if(!AfxOleInit())

       {

              AfxMessageBox("COM Error!");

              return FALSE;

       }*/

       AfxEnableControlContainer();

//......

}

5、为对话框类添加成员:

       _ConnectionPtr  m_pConnection;       //数据库连接指针(对象)

       _RecordsetPtr   m_pRecordSet;         //记录集指针(对象)

       _variant_t      vFieldValue;              //字段对应的记录值

       CString        strFieldValue;            //字段对应的记录值

void                DisplayFields();         //显示记录到绑定的对话框控件上

6、在对话框类的OnInitDialog中添加如下代码,实现数据库连接:

       // 数据库连接

       m_pConnection.CreateInstance(_uuidof(Connection));

       m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source = student.mdb;"""""-1);

       // 打开数据库记录

       m_pRecordSet.CreateInstance(_uuidof(Recordset));

       m_pRecordSet->Open("select * from stu_info"m_pConnection.GetInterfacePtr()

                     adOpenDynamic adLockOptimistic adCmdText);

       // 移动游标到打开的第一条数据库记录

       m_pRecordSet->MoveFirst();

       DisplayFields();     //显示表中的记录信息

7、添加对话框成员函数DisplayFields:负责显示对应表中的记录信息。

void CAdoObjectDlg::DisplayFields()

{

       vFieldValue= m_pRecordSet->GetCollect("学号");

       strFieldValue = (char*)_bstr_t(vFieldValue);

       m_sNo = strFieldValue;

       vFieldValue.Clear();

       vFieldValue= m_pRecordSet->GetCollect("姓名");

       strFieldValue=(char*)_bstr_t(vFieldValue);

       m_sName = strFieldValue;

       vFieldValue.Clear();

       vFieldValue= m_pRecordSet->GetCollect("出生日期");

       strFieldValue=(char*)_bstr_t(vFieldValue);

       m_sBirthday = strFieldValue;

       vFieldValue.Clear();

       vFieldValue= m_pRecordSet->GetCollect("地址");

       strFieldValue=(char*)_bstr_t(vFieldValue);

       m_sAddress = strFieldValue;

       vFieldValue.Clear();

       vFieldValue= m_pRecordSet->GetCollect("四级成绩");

       strFieldValue=(char*)_bstr_t(vFieldValue);

       m_sEnglish = strFieldValue;

       vFieldValue.Clear();

       vFieldValue= m_pRecordSet->GetCollect("VC成绩");

       strFieldValue=(char*)_bstr_t(vFieldValue);

       m_sVC = strFieldValue;

       vFieldValue.Clear();

       UpdateData(FALSE);

}

8、按钮响应函数

void CAdoTestDlg::OnButton1() // 向后

{

       // TODO: Add your control notification handler code here

       m_pRecordSet->MoveNext();

       if(m_pRecordSet->EndOfFile==VARIANT_FALSE)

              DisplayFields();

       else

       {

              m_pRecordSet->MovePrevious();

              AfxMessageBox("已经到最后一条记录!");

       }

}

void CAdoTestDlg::OnButton2() // 向前

{

       m_pRecordSet->MovePrevious();

       if(m_pRecordSet->FirstOfFile==VARIANT_FALSE)

              DisplayFields();

       else

       {

              m_pRecordSet->MoveNext();

              AfxMessageBox("已经到第一条记录!");

       }    

}

void CAdoTestDlg::OnButton3() //添加

{

       // TODO: Add your control notification handler code here

       UpdateData(TRUE);

       m_pRecordSet->AddNew();

       m_pRecordSet->PutCollect("学号"_variant_t(m_Sno));

       m_pRecordSet->PutCollect("姓名"_variant_t(m_Name));

       m_pRecordSet->PutCollect("出生日期"_variant_t(m_birthday));

       m_pRecordSet->PutCollect("四级成绩"_variant_t(m_EnglishGrade));

       m_pRecordSet->PutCollect("VC成绩"_variant_t(m_ComputerGrade));

       m_pRecordSet->Update();     //存入数据库

       m_sNo = " ";

       m_sName= " ";

       m_sBirthday = " ";

       m_sEnglish = " ";

       m_sVC = " ";

       UpdateData(FALSE);

}

void CAdoTestDlg::OnButton4()

{

       // TODO: Add your control notification handler code here.;

       m_pRecordSet->Delete(adAffectCurrent);

       m_Sno = " ";

       m_Name= " ";

       m_birthday = " ";

       m_EnglishGrade = " ";

       m_ComputerGrade = " ";

       UpdateData(FALSE);

}

9、程序运行结果如下:

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mark-puls

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值