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