ADO客户数据库编程
ADO,即ActiveX Data Objects,是一种特殊的OLE DB客户程序,它允许访问程序在Visual C++、Visual Basic、VBscript、Java等编程语言中访问。虽然ADO的巨大优势在于Visual Basic和VBscript的使用,但是在某些特殊的情况下,ADO在Visual C++中的访问是无法避免的。正是由于ADO本身是一种OLE DB客户程序,所以在数据库应用程序里使用ADO变得更加容易。ADO同OLE DB、数据库应用以及数据源之间的关系可以用图9-1表示:
图9-1 ADO同OLE DB、数据库应用以及数据源之间的关系
本章详细介绍ADO的基本原理和数据库访问技术。
9.1 ADO原理
9.1.1 ADO与OLE DB
ADO是微软最新的对象层次上的数据操作技术,它为操作OLE DB数据源提供了一套高层次自动化接口。尽管OLE DB 已经是一个强大的数据操作接口,然而大多数数据库应用开发者并不需要OLE DB提供的操作数据的底层控制接口。大多数开发者对于管理内存资源、手工聚合组件以及其它的底层操作接口并不是很感兴趣。另外,开发者经常使用高层的、不支持指针和C++函数调用规范的开发语言,OLE DB为这种需要提供了方便。
从功能上来说,ADO也是一种OLE DB客户程序,不过它不依赖于特定的OLE DB服务器,相反,它支持所有的OLE DB服务提供者。通过这些OLE DB服务提供者,ADO支持客户/服务器模式和基于Web的数据库应用。
ADO支持客户/服务器模式和基于Web的数据操作,ADO尤其支持通过客户/服务器模式或者基于Web模式访问微软的SQL Server数据库服务器。
9.1.2 ADO的优越性
对于数据库编程人员来说,ADO具有如下优越性:
· 便于使用。
· 支持多种编程语言,包括Visual Basic、Java、C++、VBScript和JavaScript。
· 支持任何的OLE DB服务器,ADO可以操作任何的OLE DB数据源。
· 不损失任何OLE DB的功能,ADO支持C++编程人员操作底层的OLE DB接口。
· 可扩展性,ADO能够通过提供者属性集合动态地表示指定的数据提供者,还能够支持COM的扩展数据类型。
9.1.3 ADO对象模型
ADO对象模型包括以下关键对象:
· Connection对象
在数据库应用里操作数据源都必须通过该对象,这是数据交换的环境。Connection对象代表了同数据源的一个会话,在客户/服务器模型里,这个会话相当于同服务器的一次网络连接。不同的数据提供者提供的该对象的集合、方法和属性不同。
借助于Connection对象的集合、方法和属性,可以使用Open和Close方法建立和释放一个数据源连接。使用Execute方法可以执行一个数据操作命令,使用BeginTrans、CommitTrans和RollbackTrans方法可以启动、提交和回滚一个处理事务。通过操作the Errors 集合可以获取和处理错误信息,操作CommandTimeout属性可以设置连接的溢出时间,操作ConnectionString属性可以设置连接的字符串,操作Mode属性可以设置连接的模式,操作Provider属性可以指定OLE DB提供者。
· Command对象
Command对象是一个对数据源执行命令的定义,使用该对象可以查询数据库并返回一个Recordset对象,可以执行一个批量的数据操作,可以操作数据库的结构。不同的数据提供者提供的该对象的集合、方法和属性不同。
借助于Command对象的集合、方法和属性,可以使用Parameters集合制定命令的参数,可以使用Execute方法执行一个查询并将查询结果返回到一个Recordset对象里,操作CommandText属性可以为该对象指定一个命令的文本,操作CommandType属性可以指定命令的类型,操作Prepared可以得知数据提供者是否准备好命令的执行,操作CommandTimeout属性可以设置命令执行的溢出时间。
· Parameter对象
Parameter对象在Command对象中用于指定参数化查询或者存储过程的参数。大多数数据提供者支持参数化命令,这些命令往往是已经定义好了的,只是在执行过程中调整参数的内容。
借助于Parameter对象的集合、方法和属性,可以通过设置Name属性指定参数的名称,通过设置Value属性可以指定参数的值,通过设置Attributes和Direction、Precision、NumericScale、Size与Type 属性可以指定参数的信息,通过执行AppendChunk方法可以将数据传递到参数里。
· Recordset对象
如果执行的命令是一个查询并返回存放在表中的结果集,这些结果集将被保存在本地的存储区里,Recordset对象是执行这种存储的ADO对象。通过Recordset对象可以操纵来自数据提供者的数据,包括修改和更新行、插入和删除行。
ADO定义了如表9-1所示的光标类型。
表9-1 ADO的光标类型
光标类型
|
描述
|
adOpenDynamic
|
允许添加、修改和删除记录,支持所有方式的光标移动,其他用户的修改可以在联机以后仍然可见
|
adOpenKeyset
|
类似于adOpenDynamic光标,它支持所有类型的光标移动,但是建立连接以后其他用户对记录的添加不可见,其他用户对记录的删除和对数据的修改是可见的。支持书签操作
|
adOpenStatic
|
支持各种方式的光标移动,但是建立连接以后其他用户的行添加、行删除和数据修改都不可见,支持书签操作
|
adOpenForwardOnly
|
只允许向前存取,而且在建立连接以后,其他用户的行添加、行删除和数据修改都不可见,支持书签操作
|
ADO定义了如表9-2所示的锁定类型。
表9-2 ADO的锁定类型
锁定类型
|
描述
|
adLockReadOnly
|
(缺省)数据只读
|
adLockPessimistic
|
锁定操作的所有行,也称为消极锁定
|
adLockOptimistic
|
只在调用Update方法时锁定操作的行,也称为积极锁定
|
adLockBatchOptimistic
|
在批量更新时使用该锁定,也称为积极批量锁定
|
ADO定义了如表9-3所示的光标服务位置。
表9-3 ADO的锁定类型
光标服务位置
|
描述
|
adUseNone
|
不使用光标服务位置
|
adUseClient
|
使用客户端光标
|
adUseServer
|
(缺省)使用数据服务端或者驱动提供端光标
|
借助于Recordset对象的集合、方法和属性,可以通过设置CursorType属性设置记录集的光标类型,通过设置CursorLocation属性可以指定光标位置,通过读取BOF 和EOF属性的值,获知当前光标在记录集里的位置是在最前或者最后,通过执行MoveFirst、MoveLast、MoveNext和MovePrevious 方法移动记录集里的光标,通过执行Update方法可以更新数据修改,通过执行AddNew方法可以执行行插入操作,通过执行Delete方法可以删除行。
· Field对象
Recordset对象的一个行由一个或者多个Fields对象组成,如果把一个Recordset对象看成一个二维网格表,那么Fields对象就是这些列。这些列里保存了列的名称、数据类型和值,这些值是来自数据源的真正数据。为了修改数据源里的数据,必须首先修改Recordset对象各个行里Field对象里的值,最后Recordset对象将这些修改提交到数据源。
借助于Field对象的集合、方法和属性,可以通过读取Name属性,获知列的名称。通过操作Value属性可以改变列的值,通过读取Type、Precision和NumericScale 属性,可获知列的数据类型、精度和小数位的个数,通过执行AppendChunk 和GetChunk 方法可以操作列的值。
· Error对象
Error对象包含了ADO数据操作时发生错误的详细描述,ADO的任何对象都可以产生一个或者多个数据提供者错误,当错误发生时,这些错误对象被添加到Connection 对象的Errors集合里。当另外一个ADO对象产生一个错误时,Errors集合里的Error对象被清除,新的Error对象将被添加到Errors集合里。
借助于Errosr对象的集合、方法和属性,可以通过读取Number和Description属性,获得ADO错误号码和对错误的描述,通过读取Source属性得知错误发生的源。
· Property对象
Property对象代表了一个由提供者定义的ADO对象的动态特征。ADO对象有两种类型的Property对象:内置的和动态的。内置的Property对象是指那些在ADO里实现的在对象创建时立即可见的属性,可以通过域作用符直接操作这些属性。动态的Property对象是指由数据提供者定义的底层的属性,这些属性出现在ADO对象的Properties集合里,例如,如果一个Recordset 对象支持事务和更新,这些属性将作为Property对象出现在Recordset对象的Properties集合里。动态属性必须通过集合进行引用,比如使用下面的语法:
MyObject.Properties(0)
或者
MyObject.Properties("Name")
不能删除任何类型的属性对象。借助于Property对象的集合、方法和属性,可以通过读取Name属性获得属性的名称,通过读取Type属性获取属性的数据类型,通过读取Value属性获取属性的值,
ADO对象模型如图9-2所示。
图9-2 ADO对象模型
每个Connection,Command,Recordset和Field对象都有一个Properties集合,如图9-3所示。
图9-3 ADO的Properties集合和Property对象
9.1.4 ADO编程
通常情况下,一个基于ADO的数据库应用使用如下过程操作数据源里的数据:
(1) 创建一个Connection 对象。定义用于连接的字符串信息,包括数据源名称、用户ID、口令、连接超时、缺省数据库以及光标的位置。一个Connection 对象代表了同数据源的一次会话。可以通过Connection 对象控制事务,即执行BeginTrans、CommitTrans和RollbackTrans方法。
(2) 打开数据源,建立同数据源的连接。
(3) 执行一个SQL命令。一旦连接成功,就可以运行查询了。可以以异步方式运行查询,也可以异步地处理查询结果,ADO会通知提供者后台提供数据。这样可以让应用程序继续处理其它事情而不必等待。
(4) 使用结果集。完成了查询以后,结果集就可以被应用程序使用了。在不同的光标类型下,可以在客户端或者服务器端浏览和修改行数据。
(5) 终止连接。当完成了所有数据操作后,可以销毁这个同数据源的连接。
9.2 ADO的数据库访问规范
Visual C++6.0为ADO操作提供了库支持,一般情况下,每个Windows操作系统的Program Files\Common Files\System\ado\目录下都有一个msado*.dll文件,根据Windows版本的不同,该文件可以是msado1.dll、msado15.dll和msado2.dll。目前ADO的最高版本是2.0。在利用Visual C++6.0进行ADO编程时,可以借助Visual C++6.0的import宏,将该库文件引用到工程里,从而使msado*.dll库里的数据和函数声明被应用的代码所使用。
通过引用,msado*.dll库在工程里产生了所有ADO对象的描述和声明,这些声明同前面介绍的对象名称基本相似,但有所不同,下面将最常用的操作对象介绍如下:
· _ConnectionPtr:指向ADO的Connect对象的指针。
· _RecordsetPtr:指向ADO的Recordset对象的指针。
· _CommandPtr:指向ADO的Command对象的指针。
· _ParameterPtr:指向ADO的Parameter对象的指针。
· FieldPtr:指向ADO的Field对象的指针。
· ErrorPtr:指向ADO的Error对象的指针。
· PropertyPtr:指向ADO的Property对象的指针。
利用上述指针,可以使用9.1.3节里介绍的所有属性和方法进行数据库应用开发。图9-4是一个最典型的ADO对象使用流程描述。
图9-4 ADO的对象使用流程描述