VC++ 实战OLEDB编程
OLEDB作为目前最全面,最强大的Windows平台下的数据库编程接口,其资料在网上却少之又少,这着实有些让人纳罕。
现在很多的应用软件系统都要和数据库打交道,没有一个好的强大的数据库编程接口作为支撑,这些系统的功能,性能,安全性等等都将是不可想象的事情。当然我们还可以选择OLEDB之上的ADO接口来作为我们的编程接口,由于ADO是基于OLEDB的上层封装,ADO比之OLEDB最大的优势就在于方便。使用ADO只需要3-5行代码的事情,用OLEDB却需要将近200-300行代码才能完成,这也是很多系统目前使用ADO作为数据库编程接口的主要原因。当然这并不表示OLEDB在功能上比ADO有什么逊之处,相反,OLEDB接口不但功能强大,而且由于处于底层的原因,它在灵活性上有更明显的优势。甚至我鼓励VC++程序员在大型项目中使用OLEDB而不是ADO来作为数据库编程的接口,因为OLEDB的很多东西都是由你完全控制的,比如数据存放的位置,存放的方式等等。
另外OLEDB还可以作为数据提供者编程接口,比如你可以自己实现一个ORACLE或MySQL的O LEDB提供程序。
数据库实例名是什么意思好了,废话就不多说了,下面就开始我们正式的OLEDB之旅,注意本文以及以后一系列文章中所有的关于OLEDB的介绍都以OLEDB2.6以上版本为准,你可以在微软的网站上免费下载到完整的OLEDB2. 6SDK包,
其中有关于OLEDB,ADO等的详细帮助以及例子代码。
首先让我们来看看OLEDB中两个最基本的概念:数据提供者和数据消费者。在OLEDB中,不但要考虑使用数据的一方,还要考虑提供数据的一方,比如各种数据库系统几乎都提供了自己的OLEDB接口。从本质上说,OLEDB其实就是一个标准的数据库与应用系统间的数据标准交换接口,它的好处就是高效,通用和灵活。
如果是数据提供的一方,在OLEDB中就称之为数据提供者,如果是使用数据的一方,那么就称之为数据消费者。在此系列文章中将主要的介绍一下数据消费者接口。
OLEDB顾名思义,它肯定是一组COM接口,因此要用好OLEDB,一个必不可少的先决条件就是必须熟悉COM原理,当然这对现在的VC++程序员来说是必须掌握的技能之一,本文中不对COM的基本内容做任何介绍,需要的请自己查阅相关资料。
要完成一个数据库访问任务,第一件要做的事情就是打开一个连接,在OLEDB2.0以前的版本中,要做到这点只需要像下面这样调用一段代码就可以创建一个数据库连接:
#define COM_NO_WINDOWS_H    //如果已经包含了Windows.h或不使用其他Windows
//库函数时
#define DBINITCONSTANTS
#define INITGUID
#define OLEDBVER 0x0250
#include <oledb.h>
#include <oledberr.h>
IDBInitialize *pIDBInitialize = NULL;
CoCreateInstance(CLSID_MSDASQL, NULL, CLSCTX_INPROC_SERVER,
IID_IDBInitialize,(void**)&pIDBInitialize);
当然如果你使用的SQL Server 2005以上的数据库,那么还可以像下面这样来创建一个连接对象:
#include <sqlncli.h>
CoCreateInstance( CLSID_SQLNCLI10,NULL,CLSCTX_INPROC_SERVER,
IID_IDBInitialize,(void **) &pIDBInitialize);
这样调用的前提是你已经安装了SQL Server Native Client支持组件,当然这还需要你包含SQLN CLI.h这个头文件,这个在Windows SDK组件中到它。
当然这只是创建了一个数据库连接的COM接口,而且要特别注意的是这是OLEDB2.0以前推荐的方法,现在不应该再这样使用了,介绍它的目的就是方便你看懂一些例子代码。
同时这个地方要特别注意的是,这种方法初始化出来的IDBInitialize接口,在后续的调用中是无法使用一些高级接口的,比如IRowsetFind、IRowsetIdentity等等,同时这将导致你后续创建的IRowset接口无法直接和ADO混用(ADO和OLEDB混用这个话题将在后续的文章中讨论),在2.0以后的OLEDB 接口中,替代的是两个接口:IDataInitialize和IDBPromptInitialize。其中IDBPromptInitialize将打开那个Windows系统标准的数据库连接创建对话框,像下图这样:
而IDataInitialize则纯粹的是以代码的方式创建一个数据库连接对象。它们分别用于不同的编程目的。调用这两个接口例子如下:
1、使用IDataInitialize接口:
IDataInitialize* pIDataInitialize = NULL;
CoCreateInstance(CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER,
IID_IDataInitialize,(void**)&pIDataInitialize);
IDBInitialize *pIDBInitialize = NULL;
pIDataInitialize->CreateDBInstance(CLSID_MSDASQL, NULL,
CLSCTX_INPROC_SERVER, NULL, IID_IDBInitialize,
(IUnknown**)&pIDBInitialize);
2、使用IDBPromptInitialize接口:
IDBPromptInitialize* pIDBPromptInitialize = NULL;
CoCreateInstance(CLSID_DataLinks, NULL, CLSCTX_INPROC_SERVER,
IID_IDBPromptInitialize, (void **)&pIDBPromptInitialize);
IDBInitialize *pIDBInitialize = NULL;
//下面这句将弹出前面所说的对话框
pIDBPromptInitialize->PromptDataSource(NULL, hWndParent,
DBPROMPTOPTIONS_PROPERTYSHEET, 0, NULL, NULL, IID_IDBInitialize,
(IUnknown **)&pIDBInitialize);
pIDBInitialize->Initialize();//根据对话框采集的参数连接到指定的数据库
上面两种方法中实际最后还是创建了IDBInitialize接口,表面上看这没什么区别,其实不然,在这个地方要特别注意的是,一定要使用后面这两种方法创建的IDBInitialize的接口,虽然很多例子中都像文中前面提到的那样直接创建了IDBInitialize接口,但是在正式的项目代码中一定要使用后面这两种方法之一来创建IDBInitialize接口,否则你就会遇到很多奇怪的问题,最重要的就是后面这两种方法打开了所有的数据源OLEDB功能支持,而直接创建的IDBInitialize只打开了基本OLEDB功能支持,这在项目中会导致很多问题,因为很多的接口以及属性都将无法使用。而后两种方法保证你后续所有的OLEDB接口和功能都能使用。
在创建了IDBInitialize接口之后(pIDBPromptInitialize->PromptDataSource这种方式创建的除外),我们就需要详细的指定连接数据库的各种参数,在OLEDB中这些参数都叫做属性,并且被加以分组,每个分组都叫做一个属性集合。典型的我们需要指定数据库实例名,数据库名,连接数据库的用户名以及密码等等属性。在SQL Server中有一种特殊的方式就是集成安全模式,它的属性相对简单些,下面的例子演示了如何使用集成安全性连接到SQL Server数据库: