第十二章 ADO编程技术Word文件下载.docx
《第十二章 ADO编程技术Word文件下载.docx》由会员分享,可在线阅读,更多相关《第十二章 ADO编程技术Word文件下载.docx(18页珍藏版)》请在冰豆网上搜索。
⏹字段对象(Fields字段集合对象,Field字段对象):
字段对象用于表示数据库或记录集中的信息,包括列值等信息。
一个记录集或一个数据库中的表包括了多行记录,若将其当做二维网格,字段将是网格中的列,每个字段分别有名称,数据类型和值等属性,字段中包括了来自数据库源中的真实数据。
要修改其中的数据可在集录集修改Filed字段对象,也可以通过在刻录集中访问Fields字段集合对象,再定位要修改的Filed字段对象。
对记录集的修改将最终被传送给数据库。
⏹参数对象(Parameter):
是和命令对象联用的一个对象。
当命令对象执行的查询是一个有参数的查询时,就要用参数对象来为命令对象提供参数信息和数据。
使用ADO访问数据库有两种方式:
◆通过ADO控件访问数据库
◆通过ADO对象访问数据库
下面我们将详细讲述这两种访问数据库的方法。
使用ADO控件访问数据库
Access2000是MicrosoftOffice中的一个组件,是一个小型的桌面数据系统,我们将以它为例子,讲解使用ADO控件访问数据库的方法。
⏹在Access2000建立空数据库(参见Access2000操作信息)
⏹在空数据库中建立一个名称为test的一个表(参见Access2000操作信息)
⏹建立一个VC的基于对话框的程序框架(也可以是其它向导建立手框架)
⏹在对话框界面编辑器中增加一个ADO控件。
ADO控件有多种类型:
◆ADOData连接控件,用于方便建立数据连接
◆ADOGrid控件,用于表示一个记录结果集
在对话框编辑器,右键菜单中选择InsertActiveXControl,在出现的对话框中选择MicrosoftADODataControl,Version6.0,点OK即可以将连接控件加入到对话框中,同样方法选择MicrosoftADOGridControl,Version6.0加入到对话框中。
⏹设置对话框中连接控件的属性
上述两个控件的属性设置和VC中其它控件的设置是一样的。
连接控件的属性设置:
在属性对话框中选择Control页面,选择UseConnectionString选项,点Build按钮,在出现的对话框中选择MicrosoftJet4.0OLEDBProvider提供者。
点下一步选择刚建立的Access2000数据文件名称。
点测试连接应能连接数据库通过。
再一次打开连接控件的属性设置,选择RecordeSource页面,在CommandType中选择2-adCmdTable,在TableOrStoredProcedureName中选择刚建立的test的表。
到此完成一连接控件的设置。
⏹设置对话框中Grid控件的属性
同样方法打开Grid控件的属性对话框。
选择Control页面,选中AllowAddNew和AllowDelete复选框,再选择All页面,设置DataSource参数为连接控件的ID
⏹运行该程序
将可以在对话框中连接数据库,并取出表中的数据显示在Grid控件中。
使用ADO对象访问数据库
ADO数据库开发的基本流程
⏹初始化COM库,引入ADO库定义文件
⏹用Connection对象连接数据库
⏹利用建立好的连接,通过Connection、Command对象执行SQL命令,或利用Recordset对象取得结果记录集进行查询、处理。
⏹使用完毕后关闭连接释放对象。
我们采用Access数据库,您也可以直接在我们提供的示例代码中找到这个test.mdb。
下面我们将详细介绍上述步骤并给出相关代码。
COM库的初始化
我们可以使用AfxOleInit()来初始化COM库,这项工作通常在CWinApp:
:
InitInstance()的重载函数中完成,请看如下代码:
BOOLCADOTest1App:
InitInstance(){AfxOleInit();
......
用#import指令引入ADO类型库
我们在stdafx.h中加入如下语句:
(stdafx.h这个文件哪里可以找到?
你可以在FileView中的HeaderFiles里找到)
#import"
c:
programfilescommonfilessystemadomsado15.dll"
no_namespacerename("
EOF"
"
adoEOF"
)
这一语句有何作用呢?
其最终作用同我们熟悉的#include类似,编译的时候系统会为我们生成msado15.tlh,ado15.tli两个C++头文件来定义ADO库。
几点说明:
⏹您的环境中msado15.dll不一定在这个目录下,请按实际情况修改
⏹在编译的时候肯能会出现如下警告,对此微软在MSDN中作了说明,并建议我们不要理会这个警告。
msado15.tlh(405):
warningC4146:
unaryminusoperatorappliedtounsignedtype,resultstillunsigned
创建Connection对象并连接数据库
首先我们需要添加一个指向Connection对象的指针:
_ConnectionPtrm_pConnection;
下面的代码演示了如何创建Connection对象实例及如何连接数据库并进行异常捕捉。
BOOLCADOTest1Dlg:
OnInitDialog()
{
CDialog:
OnInitDialog();
HRESULThr;
try
{
hr=m_pConnection.CreateInstance("
ADODB.Connection"
);
///创建Connection对象
if(SUCCEEDED(hr))
{
hr=m_pConnection->
Open("
Provider=Microsoft.Jet.OLEDB.4.0;
DataSource=test.mdb"
"
adModeUnknown);
///连接数据库///上面一句中连接字串中的Provider是针对ACCESS2000环境的,对于ACCESS97,需要改为:
Provider=Microsoft.Jet.OLEDB.3.51;
}
}
catch(_com_errore)///捕捉异常
CStringerrormessage;
errormessage.Format("
连接数据库失败!
r错误信息:
%s"
e.ErrorMessage());
AfxMessageBox(errormessage);
///显示错误信息
}
在这段代码中我们是通过Connection对象的Open方法来进行连接数据库的,下面是该方法的原型
HRESULTConnection:
Open(_bstr_tConnectionString,_bstr_tUserID,_bstr_tPassword,longOptions)
其中ConnectionString为连接字串,UserID是用户名,Password是登录密码,Options是连接选项,用于指定Connection对象对数据的更新许可权,Options可以是如下几个常量:
⏹adModeUnknown:
缺省。
当前的许可权未设置
⏹adModeRead:
只读
⏹adModeWrite:
只写
⏹adModeReadWrite:
可以读写
⏹adModeShareDenyRead:
阻止其它Connection对象以读权限打开连接
⏹adModeShareDenyWrite:
阻止其它Connection对象以写权限打开连接
⏹adModeShareExclusive:
阻止其它Connection对象打开连接
⏹adModeShareDenyNone:
允许其它程序或对象以任何权限建立连接。
我们给出一些常用的连接方式供大家参考:
⏹通过JET数据库引擎对ACCESS2000数据库的连接
m_pConnection->
DataSource=C:
\test.mdb"
⏹通过DSN数据源对任何支持ODBC的数据库进行连接:
DataSource=adotest;
UID=sa;
PWD=;
⏹不通过DSN对SQLSERVER数据库进行连接:
driver={SQLServer};
Server=127.0.0.1;
DATABASE=vckbase;
PWD=139"
adModeUnknown
其中Server是SQL服务器的名称,DATABASE是库的名称
Connection对象除Open方法外还有许多方法,我们先介绍Connection对象中两个有用的属性ConnectionTimeOut与StateConnectionTimeOut用来设置连接的超时时间,需要在Open之前调用,例如:
ConnectionTimeout=5;
///设置超时时间为5秒
State属性指明当前Connection对象的状态,0表示关闭,1表示已经打开,我们可以通过读取这个属性来作相应的处理,例如:
if(m_pConnection->
State)m_pConnection->
Close();
///如果已经打开了连接则关闭它
执行SQL命令并取得结果记录集
为了取得结果记录集,我们定义一个指向Recordset对象的指针:
_RecordsetPtrm_pRecordset;
并为其创建Recordset对象的实例:
m_pRecordset.CreateInstance("
ADODB.Recordset"
SQL命令的执行可以采用多种形式,下面我们一进行阐述。
1)利用Connection对象的Execute方法执行SQL命令,Execute方法的原型如下所示:
_RecordsetPtrConnection15:
Execute(_bstr_tCommandText,VARIANT*RecordsAffected,longOptions)
其中CommandText是命令字串,通常是SQL命令。
参数RecordsAffected是操作完成后所影响的行数,参数Options表示CommandText中内容的类型,Options可以取如下值之一:
⏹adCmdText:
表明CommandText是文本命令
⏹adCmdTable:
表明CommandText是一个表名
⏹adCmdProc:
表明CommandText是一个存储过程
⏹adCmdUnknown:
未知
Execute执行完后返回一个指向记录集的指针,下面我们给出具体代码并作说明。
_variant_tRecordsAffected;
//执行SQL命令:
CREATETABLE创建表格users,users包含四个字段:
整形ID,字符串username,整形old,日期型birthday
Execute("
CREATETABLEusers(IDINTEGER,usernameTEXT,oldINTEGER,birthdayDATETIME)"
&
RecordsAffected,adCmdText);
//往表格里面添加记录
INSERTINTOusers(ID,username,old,birthday)VALUES(1,'
Washington'
25,'
1970/1/1'
)"
//将所有记录old字段的值加一
UPDATEusersSETold=old+1"
//执行SQL统计命令得到包含记录条数的记录集
m_pRecordset=m_pConnection->
SELECTCOUNT(*)FROMusers"
_variant_tvIndex=(long)0;
_variant_tvCount=m_pRecordset->
GetCollect(vIndex);
//取得第一个字段的值放入vCount变量
m_pRecordset->
//关闭记录集
CStringmessage;
message.Format("
共有%d条记录"
vCount.lVal);
AfxMessageBox(message);
//显示当前记录条数
2)利用Command对象来执行SQL命令
_CommandPtrm_pCommand;
m_pCommand.CreateInstance("
ADODB.Command"
_variant_tvNULL;
vNULL.vt=VT_ERROR;
vNULL.scode=DISP_E_PARAMNOTFOUND;
///定义为无参数
m_pCommand->
ActiveConnection=m_pConnection;
///非常关键的一句,将建立的连接赋值给它
CommandText="
SELECT*FROMusers"
;
///命令字串
m_pRecordset=m_pCommand->
Execute(&
vNULL,&
vNULL,adCmdText);
///执行命令,取得记录集
在这段代码中我们只是用Command对象来执行了SELECT查询语句,Command对象在进行存储过程的调用中能真正体现它的作用。
下次我们将详细介绍。
3)直接用Recordset对象进行查询取得记录集。
例如:
_variant_t((IDispatch*)m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);
Open方法的原型是这样的:
HRESULTRecordset15:
Open(const_variant_t&
Source,const_variant_t&
ActiveConnection,enumCursorTypeEnumCursorType,enumLockTypeEnumLockType,longOptions)
其中:
◆Source是数据查询字符串
◆ActiveConnection是已经建立好的连接(我们需要用Connection对象指针来构造一个_variant_t对象)
◆CursorType光标类型,它可以是以下值之一,请看这个枚举结构:
enumCursorTypeEnum
adOpenUnspecified=-1,
///不作特别指定
adOpenForwardOnly=0,
//前滚静态光标。
这种光标只能向前浏览记录集,比如用MoveNext向前滚动,这种方式可以提高浏览速度。
但诸如BookMark,RecordCount,AbsolutePosition,AbsolutePage都不能使用
adOpenKeyset=1,
//采用这种光标的记录集看不到其它用户的新增、删除操作,但对于更新原有记录的操作对你是可见的。
adOpenDynamic=2,
///动态光标。
所有数据库的操作都会立即在各用户记录集上反应出来。
adOpenStatic=3
//静态光标。
它为你的记录集产生一个静态备份,但其它用户的新增、删除、更新操作对你的记录集来说是不可见的。
};
◆LockType锁定类型,它可以是以下值之一,请看如下枚举结构:
enumLockTypeEnum
adLockUnspecified=-1,
//未指定
adLockReadOnly=1,
//只读记录集
adLockPessimistic=2,
//悲观锁定方式。
数据在更新时锁定其它所有动作,这是最安全的锁定机制
adLockOptimistc=3,
//乐观锁定方式。
只有在你调用Update方法时才锁定记录。
在此之前仍然可以做数据的更新、插入、删除等动作
adLockBatchOptimistic=4,
//乐观分批更新。
编辑时记录不会锁定,更改、插入及删除是在批处理模式下完成。
Options请参考本文中对Connection对象的Execute方法的介绍
记录集的遍历、更新
根据我们刚才通过执行SQL命令建立好的users表,它包含四个字段:
ID,username,old,birthday
以下的代码实现:
打开记录集,遍历所有记录,删除第一条记录,添加三条记录,移动光标到第二条记录,更改其年龄,保存到数据库。
_variant_tvUsername,vBirthday,vID,vOld;
m_pRecordset.CreateInstance("
_variant_t((IDispatch*)m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);
while(!
adoEOF)
//这里为什么是adoEOF而不是EOF呢?
还记得rename("
)这一句吗?
{vID=m_pRecordset->
GetCollect(_variant_t((long)0)
);
///取得第1列的值,从0开始计数,你也可以直接给出列的名称,如下一行
vUsername=m_pRecordset->
GetCollect("
username"
//取得username字段的值
vOld=m_pRecordset->
old"
vBirthday=m_pRecordset->
birthday"
///在DEBUG方式下的OUTPUT窗口输出记录集中的记录
if(vID.vt!
=VT_NULL&
&
vUsername.vt!
vOld.vt!
vBirthday.vt!
=VT_NULL)
TRACE("
id:
%d,姓名:
%s,年龄:
%d,生日:
%sr"
vID.lVal,(LPCTSTR)(_bstr_t)vUsername,vOld.lVal,(LPCTSTR)(_bstr_t)vBirthday);
MoveNext();
//移到下一条记录}
MoveFirst();
//移到首条记录m_pRecordset->
Delete(adAffectCurrent);
//删除当前记录///添加三条新记录并赋值
for(inti=0;
i<
3;
i++)
m_pRecordset->
AddNew();
//添加新记录
PutCollect("
ID"
_variant_t((long)(i+10)));
_variant_t("
叶利钦"
));
_variant_t((long)71));
PutCollect(