日期:2012-03-03  浏览次数:20845 次


     服务器组件一般用于实现三层应用程序的业务规则,因此需要与数据库交互。C++访问数据有两种方式: ADO和OLE DB消费者模板。第1 2章我们已经讨论了通用数据访问(UDA)、ADO和OLE DB的作用。
    从C++ ADO与从ASP或Visual Basic访问ADO非常相似。使用完全一样的ADO COM对象(如ADODB.Recordset),只是用不同的语言创建和使用ADO COM对象。但使用ADO时没有Visual C++向导,必须编写所有的实现代码。这不仅须手工编写,而且还容易引入代码错误,因此应认真仔细。但是可从C++中得到完全可用的ADO对象模型。
    OLE DB消费者使用OLE DB提供者的服务访问数据。ADO是OLE DB消费者的一个例子。使用C++可创建OLE DB消费者,完全跳过ADO层。Visual C++向导可用于创建和使用OLEDB消费者。可以使用向导指向想要访问的数据库和表格,自动生成所需的代码。但是,因为消费者代码直接指向指定的数据库,所以不如使用ADO灵活。
18.3.1 通过C++使用ADO
    通过C++使用ADO需要两种技能:理解ADO对象模型和在C++中使用COM对象。我们对ADO对象模型已非常熟悉,但现在没有C++类库或模板库支持ADO。因为ADO在COM上构造,使用ADO与使用其他COM对象相同。下面介绍一下使用步骤。
    1. 设置使用ADO
    C++中使用COM组件最简单的方法是用# import关键字导入组件的类型库。# import 指令围绕ADO类型库产生瘦C++类,可以用接近于VBScript和Visual Basic的语句操作ADO对象和接口。大部分ADO例子用VBScript编写,用#import指令能很容易地将它们转换为C++,比在没有包装类(wrapper class)的情况下使用ADO容易。
    使用#import时,可以使用no_namespace属性,这样ADO类型库内容就没有范围限制。但是,这会引起名称与EOF的冲突,而rename属性可解决这个问题。在TableStorage2.cpp增加下列内容可导入ADO类型库。

    上述代码生成一个msADO15.tlh文件和一个msADO15.tli文件。msADO15.tlh文件包含前向引用、smart指针声明和typeinfo声明。msADO15.tli文件包含编译器产生的几个成员函数的实现。这两个文件用于观察和显示类型库中的可用内容。例如,下面是msADO15.tlh文件对ADO记录集的smart指针的声明:
    _COM_SMARTPTR_TYPEDEF(_Recordset,_uuideof(_Recordset));
    后面的例子将说明如何在代码中使用smart指针。在msADO15.tlh中还有一些枚举量的声明,使得使用ADO更为方便。下面是光标位置的枚举量声明:

    如上所述,#import使得ADO的使用更为轻松,因为这个指令可自动创建包装类和来自类型库的类型信息。但对C++程序员来说,将ADO返回的VA R I A N T数据类型转变为C/C++数据类型还是比较麻烦。ADO 2.0和Visual C++ 6.0用附加的ADO VC++扩展解决了这个问题。这一章不讨论ADO VC++扩展,有关内容可参考Visual C++文献。
    还增加了一个宏,这个宏可使程序容易理解,减少了嵌套代码的数量:

    通过导入类型库,已可使用所有ADO对象。下面介绍如何在C++中使用ADO进行读写。我们将以图1 8 - 1 0所示的数据库为例。

    假设对这个数据库已建立了一个称为MusicianDSN的ODBC连接。
    2. 读数据库
    首先在ITableStorage2中增加Read方法。这个方法从数据库读记录,并将这些记录插入STL数据结构中,它的参数是DSN名称、用户名和口令。在对话框中,参数在Implementation文本框中出现,如图1 8 - 11所示。

    下面看一下这个方法的实现:

    首先声明方法中使用的变量,注意如何使用ATL smart指针的创建ADO Connection和Recordset对象。为在代码中跟踪错误,我们采用了异常处理,因此开启一个try块。任何ADO调用都用前面声明的SAFE_CALL宏包装,如果任一方法调用返回一个表明失败的值,就抛出一个异常:

    首先打开到数据库的连接,这个连接用于Recordset对象的Open方法。

    如果成功,可对数据库的记录进行遍历。首先必须确保内存中当前无数据: