VC++ADO开发实践4

  在VC中使用ADO开发数据库应用程序
  
  
  1.引入ADO库文件
  使用ADO前必须在工程的stdafx.h文件里用直接引入符号#import引入ADO库文件,
  以使编译器能正确编译。代码如下所示:
  #import “c:program filescommon filessystemadomsado15.dll”
  no—namespaces rename(“EOF” adoEOF”)
  这行语句声明在工程中使用ADO,但不使用ADO的名字空间,并且为了避免冲突,将EOF改
  名为adoEOF。
  
  2.初始化OLE/COM库环境
  必须注意的是,ADO库是一组COM动态库,这意味应用程序在调用ADO前,必须初始
  化OLE/COM库环境。在MFC应用程序里,一个比较好的方法是在应用程序主类的
  InitInstance成员函数里初始化OLE/COM库环境。
  
    //初始化OLE/COM库环境
  
    BOOL CADOApp::InitInstance()
    {
  if(!AfxOleInit())
  {
  AfxMessageBox(“OLE初始化出错!”);
  return FALSE;
  }
  ……
  }
  
  函数AfxOleInit在每次应用程序启动时初始化OLE/COM库环境。
  
  3.ADO接口简介
  ADO库包含三个基本接口:
  __ConnectionPtr接口、
  __CommandPtr接口和、
  __RecordsetPtr接口,
  
  __ConnectionPtr接口返回一个记录集或一个空指针。通常使用它来创建一个数据连接或
  执行一条不返回任何结果的SQL语句,如一个存储过程。用__ConnectionPtr接口返回一
  个记录集不是一个好的使用方法。通常同CDatabase一样,使用它创建一个数据连接,然
  后使用其它对象执行数据输入输出操作。
  
  __CommandPtr接口返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储
  过程和SQL语句。在使用__CommandPtr接口时,可以利用全局__ConnectionPtr接口,也
  可以在__CommandPtr接口里直接使用连接串。如果只执行一次或几次数据访问操作,后
  者是比较好的选择。但如果要频繁访问数据库,并要返回很多记录集,那么,应该使用
  全局__ConnectionPtr接口创建一个数据连接,然后使用__CommandPtr接口执行存储过程
  和SQL语句。
  
  __RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多
  的控制功能,如记录锁定,游标控制等。同__CommandPtr接口一样,它不一定要使用一
  个已经创建的数据连接,可以用一个连接串代替连接指针赋给__RecordsetPtr的
  connection成员变量,让它自己创建数据连接。如果要使用多个记录集,最好的方法是
  同Command对象一样使用已经创建了数据连接的全局—ConnectionPtr接口,然后使用
  __RecordsetPtr执行存储过程和SQL语句。
  
  4.使用__ConnectionPtr接口
  
  __ConnectionPtr是一个连接接口,它类似于CDatabase和CDaoDatabase。首先创建一个
  __ConnectionPtr接口实例,接着指向并打开一个ODBC数据源或OLE DB数据提供者
  (Provider)。以下代码分别创建一个基于DSN和非DSN的数据连接。
  
    //使用__ConnectionPtr(基于DSN)
  
    __ConnectionPtr MyDb;
  
    MyDb.CreateInstance(__uuidof(Connection));
  
    MyDb-〉Open(“DSN=samp;UID=admin;PWD=admin”,””,””,-1);
  
    //使用—ConnectionPtr (基于非DSN)
  
    __ConnectionPtr MyDb;
  
    MyDb.CreateInstance(__uuidof(Connection));
  
    MyDb-〉Open(“Provider=SQLOLEDB;SERVER=server;DATABASE=samp;UID=admin;
  
    PWD=admin”,””,””,-1);
  
  
  5.使用__RecordsetPtr接口
  __RecordsetPtr接口的使用方法和CDaoDatabase类似,通过以下代码的比较,你会发现
  使用—RecordsetPtr接口非常简单(以下代码使用上面已经创建的数据连接):
  
    //使用CDaoDatabase执行SQL语句
  
    CDaoRecordset MySet = new CDaoRecordset(MyDb);
  
    MySet-〉Open(AFX__DAO__USE__DEFAULT__TYPE,”SELECT  FROM t__samp”);
  
    Now using ADO:
  
    //使用__RecordsetPtr执行SQL语句
  
    __RecordsetPtr MySet;
  
    MySet.CreateInstance(__uuidof(Recordset));
  
    MySet-〉Open(“SELECT  FROM some__table”,
  
    MyDb.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
  
    现在我们已经有了一个数据连接和一个记录集,接下来就可以使用数据了。从以下
  代码可以看到,使用ADO的__RecordsetPtr接口,就不需要像DAO那样频繁地使用大而复
  杂的数据结构VARIANT,并强制转换各种数据类型了,这也是ADO的优点之一。假定程序
  有一个名称为m__List的ListBox控件,下面代码我们用__RecordsetPtr接口获取记录集
  数据并填充这个ListBox控件:
  
    //使用ADO访问数据
  
    __variant__t Holder
  
    try{while(!MySet-〉adoEOF)
  
    { Holder = MySet-〉GetCollect(“FIELD__1”);
  
    if(Holder.vt!=VT__NULL)
  
    m__List.AddString((char)__bstr__t(Holder));
  
    MySet-〉MoveNext();} }
  
    catch(__com__error  e)
  
    { CString Error = e-〉ErrorMessage();
  
     AfxMessageBox(e-〉ErrorMessage());
  
    } catch(…)
  
    { MessageBox(“ADO发生错误!”);}
  
    必须始终在代码中用try和catch来捕获ADO错误,否则ADO错误会使你的应用程序崩
  溃。当ADO发生运行错误时(如数据库不存在),OLE DB数据提供者将自动创建一个
  __com__error对象,并将有关错误信息填充到这个对象的成员变量。
  
  6.使用__CommandPtr接口
  __CommandPtr接口返回一个Recordset对象,并且提供了更多的记录集控制功能,以下代
  码示例使用__CommandPtr接口的方法:
  
    //使用__CommandPtr接口获取数据
  
    __CommandPtr pCommand;
  
    __RecordsetPtr MySet;
  
    pCommand.CreateInstance(__uuidof(Command));
  
    pCommand-〉ActiveConnection=MyDb;
  
    pCommand-〉CommandText=”select  from some—table”;
  
    pCommand-〉CommandType=adCmdText;
  
    pCommand-〉Parameters-〉“refresh”();
  
    MySet=pCommand-〉Execute(NULL,NULL,adCmdUnknown);
  
    __variant__t TheValue = MySet-〉GetCollect(“FIELD__1”);
  
    CString sValue=(char)__bstr__t(TheValue);
  
  7.关于数据类型转换
    由于COM对象是跨平台的,它使用了一种通用的方法来处理各种类型的数据,因此
  CString 类和COM对象是不兼容的,我们需要一组API来转换COM对象和C++类型的数
  据。__vatiant__t和__bstr__t就是这样两种对象。它们提供了通用的方法转换
COM对象
  和C++类型的数据。
  
  
  

VC++ADO开发实践6

  在Visual C++中用ADO进行数据库编程
  作者:蒋东宇
  
  
  
    ActiveX数据对象(ADO)是OLE DB上面的高层数据库API。我们在C++程序中也可以调用ADO。本文将在VC 6.0环境下做一个小小的例子解释如何使用ADO。
  
    1. 生成应用程序框架并初始化OLE/COM库环境
  
    创建一个标准的MFC AppWizard(exe)应用程序,然后在应用程序类的InitInstance函数中初始化OLE/COM库(因为ADO库是一个COM DLL库)。
  
    BOOL CADOTestApp::InitInstance()
  
    { //初始化OLE/COM库环境
  
  AfxOleInit();}
  
    2. 引入ADO库文件
  
    使用ADO前必须在工程的stdafx.h文件里用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下:
  
     #include 〈comdef.h〉
  
     #import “c:program filescommon filessystemadomsado15.dll”
  
     no_namespace
  
     rename (“EOF”,”adoEOF”)
  
    头文件comdef.h使我们的应用程序能够使用Visual C++中的一些特殊COM支持类,这些类使得处理OLE自治更为容易一些,OLE自治是ADO使用的数据类型。后三行使用#import指令在我们的应用程序中输入ADO类库定义。
  
    ADO类的定义是作为一种资源存储在ADO DLL(msado15.dll)中,在其内部称为类型库。类型库描述了自治接口,以及C++使用的COM vtable接口。当使用#import指令时,在运行时Visual C++需要从ADO DLL中读取这个类型库,并以此创建一组C++头文件。这些头文件具有.tli 和.tlh扩展名,读者可以在项目的目录下找到这两个文件。在C++程序代码中调用的ADO类要在这些文件中定义。
  
    程序的第三行指示ADO对象不使用名称空间。在有些应用程序中,由于应用程序中的对象与ADO中的对象之间可能会出现命名冲突,所以有必要使用名称空间。如果要使用名称空间,则可把第三行程序修改为: rename_namespace(“AdoNS”)。第四行代码将ADO中的EOF(文件结束)更名为adoEOF,以避免与定义了自己的EOF的其他库冲突。
  
    3.利用智能指针进行数据库操作
  
    在CaboutDlg头文件中定义两个ADO智能指针类实例,并在对话框中加入一个ListCtrl。
  
  _ConnectionPtr m_pConnection;
  
  _RecordsetPtr m_pRecordset;
  
    ClistCtrl m_List;
  
    ADO库包含三个智能指针:_ConnectionPtr、_CommandPtr和_RecordsetPtr。
  
  _ConnectionPtr通常被用来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。
  
  _CommandPtr返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。
  
  _RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定、游标控制等。
  
    在OnInitDialog()中加入以下代码:
  
    BOOL CAboutDlg::OnInitDialog()
  
    {
  
  CDialog::OnInitDialog();
  
  _variant_t TheValue;
  
  m_List.ResetContent();
  
    m_pConnection.CreateInstance(_uuidof(Connection));
  
    m_pRecordset.CreateInstance(_uuidof(Recordset));
  
    try{
  
  m_pConnection->Open(“DSN=ADOTest”,””,””,0); //连接叫作ADOTest的ODBC数据源
  
  m_pRecordset->Open(“SELECT * FROM BlockDefine”,(IDispatch*)m_pConnection,
  adOpenDynamic,
  adLockOptimistic,
  adCmdText);
  
    //执行SQL语句得到一个记录集
  
     while(!m_pRecordset->adoEOF)
  
    //遍历所有记录
  
     {
  
     TheValue = m_pRecordset->GetCollect(“BlockIndex”);
  
    //得到字段BlockIndex的值
  
     if(TheValue.vt!=VT_NULL)
  
     m_List.AddString((char*)_bstr_t(TheValue)); //将该值加入到列表控件中
  
     m_pRecordset->MoveNext();
  
    }
  
     m_pRecordset->Close();
  
  m_pConnection->Close();
  
     }
  
     catch(_com_error e) //异常处理
  
     {
  
  AfxMessageBox(e->ErrorMessage());
  
    }
  
    m_pRecordset = NULL;
  
  m_pConnection = NULL;
  
    return TRUE; // return TRUE unless you set the focus to a control
  
    }
  
    程序中通过_variant_t和_bstr_t转换COM对象和C++类型的数据, _variant_t类封装了OLE自治VARIANT数据类型。在C++中使用_variant_t类要比直接使用VARIANT数据类型容易得多。
  
    好,编译后该程序就能运行了,但记住运行前要创建一个叫ADOTest的ODBC数据源。该程序将把表BlockDefine中的BlockIndex字段值显示在列表控件中。
  
  
  

VC++ADO开发实践7

  一致的数据访问技术ADO/OLE DB
  
   Microsoft新近推出的UDA(Universal Data Access,一致数据访
  问技术)为关系型或非关系型数据访问提供了一致的访问接口,为企业
  级Intranet应用多层软件结构提供了数据接口标准。一致数据访问包
  括两层软件接口,分别为ADO(Active Data Object)和OLED B,对应于
  不同层次的应用开发,ADO提供了高层软件接口,可在各种脚本语言(Sc
  ript)或一些宏语言中直接使用;OLE DB提供了底层软件接口,可在C/C
  ++语言中直接使用。ADO以OL E DB为基础,它对OLE DB进行了封装。
  一致数据访问技术建立在Microsoft的COM(组件对象模型)基础上,它
  包括一组COM组件程序,组件与组件之间或者组件与客户程序之间通过
  标准的COM接口进行通讯。
   由于ADO建立在自动化(Automation)基础上,所以ADO的应用场合
  非常广泛,不仅可在Visual Basic这样的高级语言开发环境中使用,还
  可以在一些脚本语言中使用,这对于开发Web应用,在ASP(Active Serv
  er Page)的脚本代码访问数据库中提供了操作应用的捷径。本文将首
  先介绍ADO和OLE DB的结构模型,以便读者了解ADO与OLE DB之间的关
  系,然后介绍ADO的对象模型和ADO的一些特性,同时我们也将通过一些
  例子代码向读者展示ADO的用法。
   一、一致数据访问介绍
   随着网络技术和数据库技术的不断发展,现在的应用系统对数据
  集成的要求越来越高,这些数据有可能分布在不同的地方,并且使用不
  同的格式,例如关系型数据库和操作系统中的文件、电子表格、电子
  邮件、多媒体数据以及目录服务信息等等。传统的解决方案是使用大
  型的数据库系统,把所有这些数据都移到数据库系统中,然后按照操作
  数据库的办法对这些数据进行访问,这样做虽然能够按统一的方式对
  数据进行各种操作,但这种间接访问方式带来了很多问题,比如数据更
  新不及时、空间资源的冗余和访问效率低等等。
   Microsoft公司推出的一致数据访问技术则较好地解决了这些问
  题,它使得应用通过一致的接口来访问各种各样的数据,而不管数据驻
  留在何处,也不需要进行数据转移或复制、转换,在实现分布式的同时
  也带来了高效率。并且UDA技术在统一数据访问接口的同时,它的多层
  结构使数据使用方有了更多的选择机会,而它强大的扩展能力也给数
  据提供方留下了更多的扩展余地,这种开放型的软件结构使它具有极
  强的生命力,所以,这种技术从一推出便获得了广泛的欢迎,可以说,UD
  A技术是继ODBC之后的又一数据访问技术的飞跃。
   UDA技术包括OLE DB和ADO两层标准接口,OLE DB是系统级的编程
  接口,它定义了一组COM接口,这组接口封装了各种数据系统的访问操
  作,这组接口为数据使用方和数据提供方建立了标准,OLE DB还提供了
  一组标准的服务组件,用于提供查询、缓存、数据更新、事务处理等
  操作,因此,数据提供方只需实现一些简单的数据操作,在使用方就可
  以获得全部的数据控制能力。
   ADO是应用层的编程接口,它通过OLE DB提供的COM接口访问数据,
  它适合于各种客户机/服务器应用系统和基于Web的应用,尤其在一些
  脚本语言中访问数据库操作是ADO的主要优势。ADO是一套用自动化技
  术建立起来的对象层次结构,它比其他的一些对象模型如DAO(Data Ac
  cess Object)、RDO(Remote Data Object)等具有更好的灵活性,使用
  更为方便,并且访问数据的效率更高。
   图1显示了统一数据访问的软件层次模型。
  图1 UDA的层次结构图
   从图中我们可以看出,应用程序既可以通过ADO访问数据也可以直
  接通过OLE DB访问数据,而ADO则通过OLE DB访问底层数据。而且,OLE
   DB分成两部分,一部分由数据提供者实现,包括一些基本功能,如获取
  数据、修改数据、添加数据项等;另一部分由系统提供, 包括一些高
  级服务,如游标功能、分布式查询等等。这样的层次结构既为数据使
  用者即应用程序提供了多种选择方案,又为数据提供方简化了服务功
  能的实现手段,它只需按OLED B规范编写一个COM组件程序即可,使得
  第三方发布数据更为简便,而在应用程序方可以得到全面的功能服务,
  这充分体现了OLE DB两层结构的优势。
   由于OLE DB和ADO都以COM组件的形式实现,所以COM组件的各种特
  性也使得构建数据应用更为灵活,而不仅仅局限于一般的客户机/服务
  器或Web应用模型,它既适合于以数据为中心的应用,也适合于多层结
  构的分布式软件系统。通过对COM组件的配置,我们可以建立各种复杂
  的应用系统。利用从COM到DCOM的位置透明技术,我们可以很方便地建
  立分布式应用系统;利用MTS(Microsoft Transaction Server)运行环
  境,我们也可以在数据访问一层增加安全性控制,并利用MTS的对象管
  理使数据访问效率更高。所有这些功能都无需数据提供方编写代码实
  现,只需在DCOM或MTS环境中进行常规的配置即可。
   可以说一致的数据访问技术的核心是OLE DB,OLE DB建立了数据
  访问的标准接口,它把所有的数据源经过抽象形成行集(rowset)的概
  念。OLE DB模型主要包括以下一些COM对象:
   (1)数据源(Data Source)对象 数据源对象对应于一个数据提供
  者,它负责管理用户权限、建立与数据源的连接等初始操作。
   (2)会话(Session)对象 在数据源连接的基础上建立会话对象,会
  话对象提供了事务控制机制。
   (3)命令(Command)对象 数据使用者利用命令对象执行各种数据
  操作,如查询命令、修改命令等。
   (4)行集(Rowset)对象 提供了数据的抽象表示,它可以是命令执
  行的结果,也可以直接由会话对象产生,它是应用程序主要的操作对象
  。
   OLE DB的对象模型非常简单,这种简单性也带来了灵活性,从上面
  的几个COM对象也可以看出这一点。下面我们将从应用层角度出发,通
  过建立在OLE DB基础上的ADO对象模型结构的分析和使用以帮助读者
  进一步理解一致数据访问技术。
   二、ADO对象模型
   ADO对象模型定义了一组可编程的自动化对象,可用于Visual Bas
  ic、Visual C++、Java以及其他各种支持自动化特性的脚本语言。AD
  O最早被用于Microsoft Internet In formation Server中访问数据
  库的接口,与一般的数据库接口相比,ADO可更好地用于网络环境,通过
  优化技术,它尽可能地降低网络流量;ADO的另一个特性是使用简单,不
  仅因为它是一个面向高级用户的数据库接口,更因为它使用了一组简
  化的接口用以处理各种数据源。这两个特性使得ADO必将取代RDO和DA
  O,成为最终的应用层数据接口标准。
   从图1我们也看到了ADO实际上是OLE D
B的应用层接口,这种结构
  也为一致的数据访问接口提供了很好的扩展性,而不再局限于特定的
  数据源,因此,ADO可以处理各种OLE DB支持的数据源。
   图2是ADO的对象模型图。
  图2 ADO对象模型
   在ADO模型中,主体对象只有3个:Connection、Command和Records
  et,其他4个集合对象Errors、Properties、Parameters和Fields分别
  对应Error、Property、Parameter和Field对象,整个ADO对象模型由
  这些对象组成。
   一个典型的ADO应用使用Connection对象建立与数据源的连接,然
  后用一个Command对象给出对数据库操作的命令,比如查询或者更新数
  据等,而Recordset用于对结果集数据进行维护或者浏览等操作。Comm
  and命令所使用的命令语言与底层所对应的OLE DB数据源有关,不同的
  数据源可以使用不同的命令语言,对于关系型数据库,通常使用SQL作
  为命令语言。
   在Connection、Command和Recordset 3个对象中,Command对象是
  个可选对象,它是否有效取决于OLE DB数据提供者是否实现了IComman
  d接口。由于OLE DB可提供关系型数据源也可以提供非关系型数据源,
  所以在非关系型数据源上使用传统的SQL命令查询数据有可能无效,甚
  至Command命令对象也不能使用。
   从结构上看,ADO模型非常简单,但使用上又非常灵活,下面我们先
  从单个对象的角度进行讨论:
   (1) Connection对象 Connection对象代表与数据源之间的一个
  连接,ADO的Connec tion对象封装了OLE DB的数据源对象和会话对象
  。根据OLE DB提供者的不同性能,Conne ction对象的特性也有所不同
  ,所以Connection对象的方法和属性不一定都可以使用。利用Connect
  ion对象,我们可以完成以下一些基本设置操作。
   a.通过ConnectionString、ConnectionTimeOut和Mode属性设置
  连接串、超时信息、访问模式。
   b.还可以设置CursorLocation属性以便指定使用客户端游标,以
  便在客户程序中使用批处理修改方式。
   c.设置连接的缺省数据库属性DefaultDatabase。
   d.设置OLE DB提供者的属性Provider。
   e.通过Open和Close控制Connection对象与物理数据源的连接。
   f.通过Execute方法执行命令。
   g.提供事务机制,通过BeginTrans、CommitTrans和RollbackTran
  s方法实现事务控制。
   h.通过Errors集合属性检查数据源的错误信息。
   i.通过OpenSchema方法获取数据库的表信息。
   Connection对象是ADO的基本对象之一,它独立于所有其他的对象
  。如果我们要对数据库进行查询操作,既可以使用Execute方法,也可
  以使用Command对象。使用Execute方法