我的ATL/ADO编程的曲折经历

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
   我在用VC6的ATL作一个组件,它内部通过ADO访问Access数据库。因为ADO本身也是一系列组件,因此,ATL项目要引入ADO类型库,我是用以下语句引入的(假设Windows安装在C盘):#import "C:/Program Files/Common Files/System/ADO/msado15.dll" no_namespace named_guids rename("EOF","adoEOF")

    这是在微软的官方教材(1015 Mastering COM Development using Visual C++ 6.0)上讲的引用ADO的标准方法,教材上说,这样可以使你能使用最新的ADO版本。请注意,这是第一个麻烦所在。

    Access数据库是在Access97上建立的,所以我用了Jet 3.51的OLE DB Provider,也就是说Connection串是:“Provider=Microsoft.Jet.OLEDB.3.51;……”

    这是第二个造成麻烦所在。

    我的开发环境是Win2K,这是第三个麻烦所在。下面请听我慢慢道来。

    好了,在 Win2K上调试一切正常。我一直很信任2K,因为在2K上调程序系统很稳定,另外速度好象比在98上快,最重要的是很多在98上用Debug跟踪不到的错误,在2K上都能跟踪到!我信心百倍地交给用户了。用户机器是Win98SE,另外装了Access2000.但是用户机器上报错:“Create ADODB.Recordset failed”!当然98没有这么智能,这个错误信息是我留了个心眼儿,在程序中让它报的:_RecordsetPtr pRs=NULL;if (pRs.CreateInstance(CComBSTR("ADODB.Recordset"))!=S_OK)

    { Error("Create ADODB.Recordset failed");return E_FAIL;} 98不会不支持ADO呀!我首先想到会不会是Access2000的问题?但是也不应该,虽然在Access2000执行界面不能修改Access97的数据库结构,但是因为Access2000是Jet4.0驱动,它应该向下兼容地呀!通过ADO是可以修改结构的,何况我并没有修改结构,我甚至连数据都没有修改!

    翻箱倒柜地一通查,在MDAC 2.5的帮助文件中我找到了:从ADO2.1开始提供的JET4.0 OLE DB Provider将禁用某些JET3.5x的文件,该死的微软!我不得不把连接串改成了:“Provider=Microsoft.Jet.OLEDB.4.0;……”

    毕竟现在用户机器都升级到Office2000了,用Access97的人不多了。但是仍然报那个错!换到另一台装了WinMe的机器上安装运行,运行正常!这是怎么回事?我差点怀疑那个装98的机器系统有问题。于是我查它的注册表,HKEY_CLASSES_ROOT/CLSID下是有ADODB.Recordset的。在几乎绝望之际,我发现了这个:#import msado15.dll生成的文件msado15.tlh里,_Recordset的IID是"00000556-0000-0010-8000-00aa006d2ea4"而那个倒霉98机器的注册表的HKEY_CLASSES_ROOT/Interface下没有这个IID!我赶紧用OLE View查看了98上的msado15.dll,却在里面看到了_Recordset接口,所有Interface,coclass应有尽有。有意思有意思!编了这么多年程序,让我长了记性:永远不要怀疑系统有问题、编译器有问题,永远要坚信是自已的程序的问题。幸亏我还算有点观察力,我发现这个98机器上的msado15.dll的_Recordset接口的IID是:"00000555-0000-0010-8000-00aa006d2ea4"看见没有,一个是556,一个是555,它们不是一个接口!

    好,仔细看看OLE View为我揭示的msado15.dll:_Recordset派生于Recordset20,Recordset20派生于Recordset15,Recordset15就差不多到根上了(怪不得文件名是msado15而不是msado20或别的),它们每个的IID都不一样。我又看了看2K上的msado15.dll, _Recordset派生于Recordset21,Recordset21派生于Recordset20,下面的派生树与98上的就一样了。我又注意到,2K的msado15.dll的library节的version属性是2.5,也就是说typelib版本是2.5,而98上的是2.1.我终于明白了,原来我开发用的ADO版本与用户机器上的用户版本不一样,开发用的是ADO2.5,而用户机器上的是ADO2.1.ADO 2.1版的Recordset命名为Recordset21,2.0版的Recordset命名为Recordset20,依此类推,而ADO总是把最新版的Recordset接口命名为_Recordset.所以在用VC的#import时,生成的_RecordsetPtr是msado15.dll支持的最高版的Recordset.那么,我怎么能知道用户机器安装了哪个ADO版本呢?

    在MSDN中没有直接的方式查找这方面的信息,或者说我无从下手。我只好用“搜索”功能。搜索“MDAC”查到的主题数大大超出我的想象―有500页之多!幸亏没查“ADO”,那样会更多。在看了三五个主题后,我有些头大了,微软的数据库存取技术的版本控制太混乱了!在咬牙坚持看完了不下十个主题后,终于理出了一些头绪。

    首先,M$ Bless Me! 这个主题在搜索结果中比较靠前,使我及时了解了一些基本概念,能坚持看完后面的主题:INFO: What are MDAC, DA SDK, ODBC, OLE DB, ADO, RDS, and ADO/MD?

    ID: Q190463 MDAC是ODBC, OLE DB, ADO, RDS四类数据库存取技术的总称。比较象样的MDAC包是从版本1.5开始的。它包括ODBC 3.5, OLE DB 1.5, ADO 1.5, RDS 1.5.2.0的MDAC曾一度被命名为Data Access SDK 2.0,它包括ODBC 3.51, OLE DB 2.0, ADO 2.0, RDS 2.0.以后的ADO版本基本上和MDAC的版本一致。除了大版本外,还有象1.5b,1.5(PDC)等小版本,但是大版本的功能是差不多一样的。

    好了,我关心的是怎样确定用户机器的ADO版本,然后才能知道要发布哪些文件。到用户机器上手工查看msado15.dll的Typelib版本总不是个办法。这个主题好象有点用:HOWTO: Determine the Version of MDAC ID: Q269490不过这要下载一个Component Checker的软件,或者依靠一个并不可靠的注册表项。我更想知道:给定一个用户机器的软件配置,能确定它支持的ADO最小版本。

    M$ Bless Me Again! 下面的主题又比较靠前:INFO: Microsoft Data Access Components (MDAC) Release History ID: Q231943请看OLE DB/ADO的曲折发展进程和混乱的版本发布:MDAC 1.5在以下产品中安装了Beta版:NT Options Pack(IIS 4)/IE4/Win98,正式发布是在08/01/1997的IE4,也就是说,Win98或是Win95+IE4可以保证ADO1.5的存在。而在NT内核的操作系统中,NT4/OP/IIS4也最少可以用1.5.在07/01/1998的NT4的SP4中,包含了MDAC 2.0.这回NT内核超过了98内核。

    在3/15/1999的IE5中,包含了MDAC 2.1,我们知道Win98SE是与IE5绑定的。这回98内核领先了。

    4/1/1999,NT上的BackOffice 4.5赶了上来,支持MDAC 2.1了。

    2/17/2000, Windows 2000来了个大一统,干脆绑定了MDAC 2.5.呵呵,我用的是MSDN January 2001,后面的事情就查无出处了。我看过WinMe的缺省安装,是支持MDAC 2.5的,98内核与NT内核走到一起了。

    后来发布的还有MDAC 2.6,我估计它是独立发布的。我有一台装XP的机器已经装上VS.net了,VS.net要求安装MDAC 2.7.我已分不清楚2.6和2.7哪个是与XP绑定的了。不过后面你将看到,对主要用ADO.Recordset对象的编程者来说,MDAC 2.5与2.6/2.7差别不大。

    下面让我们看看ADO各版本中的Recordset对象都有哪些变化。

    Recordset15没有完善的Clone和Resync方法,另外很可能不支持异步方法调用(asynchronous method)。这些都在Recordset20里实现了,Recordset20的Cancel方法支持终止异步方法调用。ADO 2.0还实现了Recordset的Persistance,不过只支持ADO专用的ADTG(Microsoft Advanced Data TableGram)格式。

    Recordset21增加了Seek方法和Index属性。另外在Persistance方面还支持部分的XML格式。

    从ADO 2.5起,Persistance得到了很大的完善。Recordset对象完全支持Persistance到XML格式,但是这依赖于Microst XML Parser,也就是msxml.dll,它从IE5开始提供。Recordset对象还可以Persistance到任何实现了IStream接口的对象,并且ADO 2.5还提供了Stream对象。因此,ADO 2.5的Recordset可以直接Persistance到IIS5(Windows 2000绑定)的ASP Response/Request对象,为ASP的数据存取编程提供了极大的方便。

    ADO 2.5以后的2.6,2.7版本对Recordset的接口没有再做改动,所增强的是其他ADO对象,例如ADO 2.7中支持Command 2.7对象。对于主要使用Recordset对象的开发者来说,2.5与2.6,2.7区别不大。

    好了,我班门弄斧地总结了ADO的发展历程和各版本的功能,下面该讨论一下如何发布ADO应用程序了。

    需要说明的是,MDAC包不仅随操作系统和IE发布,它也经常做为一个单独的包发布,例如在PDC(Professional Developer‘s Conference)上。它还随一些应用系统发布,如BackOffice,SQL Server等,尤其是它也随Visual Studio发布。VS6中包含MDAC 2.0,而VS6的SP3包含MDAC 2.1.不过这些不是我们开发者考虑的主要问题。我想如果你在你的软件安装需求中写上“本软件要求您安装了MDAC X.X”会使大多数用户看不懂,包括许多MCSE(BTW:我是MCSD,因为D在E之前,所以我有优越感)。“本软件要求您安装了VS6或者SQL Server”也经常会使用户感到手足无措,而“要求Win98SE/WinNT+IE5/Win2K”比较清晰明了。用户对自已用的操作系统和IE的版本是比较清楚的,这两样也是必装的,所以在确定用户机器的MDAC环境时,我觉得还是主要依赖于对这两样的判断为好。

    MDAC包有一个安装程序mdac_typ.exe,可以把它加到你的应用程序的安装工程中去,当用户机器的ADO版本比你的要求低时用它安装高版本的MDAC.在VS6的安装盘中你可以找到这个程序。MSDN的这个主题可以提供帮助:Redistributing MDAC但是这要在安装工程中做很多文章,而且安装包将会变得很大,另外你还可能和M$惑上官司,如果你是用D版的话。所以我更愿意把我的程序对系统的要求降到最低,换句话说,我想让我的程序使用的ADO版本尽量低。怎么办呢?

    首先我沮丧地想到要找一个Win98或Win95+IE4的机器,把它的msado15.dll复制过来#import,或者干脆在这上面开发。但是现在要找一个Win98第一版或Win95的机器已经很难了,而且在上面运行VS6是太别扭了。复制一个msado15.dll又很容易与开发机器上的搞混。忽然我想到VC6有一个头文件叫adoint.h,我猜它是ADO Interfaces的意思。在这里有ADO各对象、接口的定义!我打开了adoint.h,发现它的_Recordset的IID是:"0000054F-0000-0010-8000-00AA006D2EA4"再一查msado15.dll,这是Recordset20的IID,也就是说,VC6的adoint.h提供的是ADO 2.0的对象和接口。这很好理解,VS6自带的MDAC2.0.再看看支持ADO 2.0的最低操作系统:Win98SE/NT+SP4/2K/XP,这对大多数用户来说都满足的,所以按这个adoint.h的定义使用ADO很理想。

    如果你还想用Smart Pointer(_com_ptr_t)的话,如_RecordsetPtr,那么就要把#import "C:/Program Files/Common Files/System/ADO/msado15.dll" no_namespace named_guids rename("EOF","adoEOF")

    换成:#include <adoint.h> #include <icrsint.h>

    #include <comdef.h> _COM_SMARTPTR_TYPEDEF(_Connection, __uuidof(_Connection));_COM_SMARTPTR_TYPEDEF(_Recordset, __uuidof(_Recordset));_COM_SMARTPTR_TYPEDEF(Fields, __uuidof(Fields));_COM_SMARTPTR_TYPEDEF(Field, __uuidof(Field));其中#include <icrsint.h>是可选的,它使你能用ADO内部的VC支持接口IADORecordBinding来处理记录数据,避开在VC中今人生烦的对VARIANT的处理,我比较喜欢用这个接口。

    #include <comdef.h>是必须的。没有它,你会碰到一大堆编译错误,主要是“抽象类(abstract)的成员函数没有实现”之类的信息。

    后面的_COM_SMARTPTR_TYPEDEF为你需要的接口指针定义Smart Pointer类型(_com_ptr_t的模板实现类XxxxPtr)。我列出的是最常用的接口。

    有一点要注意:如果你用的是VS6的SP3,那么Adoint.h有可能是ADO 2.1的定义(我没有VS6 SP3,不能肯定)。

    这里还有一点小麻烦,用这种方法生成的smart pointer只支持接口的原生方法和属性,例如你只能用put_CursorLocation/get_CursorLocation而不能用#import为你实现的PutCursorLocation/GetCursorLocation,#import实现的对方法的BSTR和VARIANT参数的包装(用_bstr_t和_variant_t类)也不能用了,你必须自已处理BSTR和VARIANT,这包括对SysAllocString/SysFreeString/VariantInit/VariantClear/VariantChangeType等的小心使用。不过如果你是用ATL开发的话,ATL的CComBSTR和CComVariant类可以起到_bstr_t和_variant_t同样的作用。

    最后来看一下现在的大红人Visual Studio.net,如果你安装时选择了安装Platform SDK(缺省是不安装的),VC.net的adoint.h在VS.net安装目录的vc7/PlatformSDK/include下。看一下这个文件,_Recordset是2.5的,只有_Command是派生于Command25,也就是说,VC.net的adoint.h是支持ADO 2.7的(ADO 2.7的大多数接口与2.5相同,只有Command接口是新的)。因此,虽然VC.net是VS.net中唯一能开发Windows专有平台应用的工具,但是用它开发ADO应用要小心,它用的是ADO 2.7,如果用到了Command对象,那么你的应用只能在XP上用了!

    可能有人会有这样的想法,不管开发时引用的是哪个版本的ADO,代码里不用_RecordsetPtr不就行了吗?比如用Recordset20Ptr,事实是这样也不行,因为#import生成的Recordset20Ptr代码中引用了_RecordsetPtr,不信你可以试试。

 

转载: http://www.linuxmine.com/48435.html

 

C++通过ATL访问Excel时 使用COleSafeArray批量读写数据及公式 c++开发中在使用ATL对Excel进行操作时,使用COleSafeArray对Excel的内容进行批量读写,包括数据的批量读写及公式的批量写入。 阅读详情

相关推荐

oledb 例子,数据库例子

rowsetviewer例子 详细列表 ├─ado │ ├─adosql2k │ ├─adovcgen │ ├─inventoryapp │ ├─isapi │ ├─performance │ ├─semistru │ ├─shape │ ├─shapexsl │ └─simpledb ├─odbc │ ├─odbcsql │ └─quiktest ├─oledb │ ├─omniprov │ ├─prsample │ ├─rowsetviewer │ ├─sampclnt │ ├─sampprov │ └─tablecopy ├─osp └─rds ├─addrbook ├─handler └─rdstest

VC中利用ATL OLE DB类开发Access数据库的技巧

Microsoft公司提供的最新数据开发技术OLE DB,是建立在COM接口上。由于OLE DB开发数据库十分方便,并且对数据库访问速度很快,所以成为很多商业软件首选技术。作为一个程序员,我有幸参加成都天下视讯网络有限责任公司互动电视节目的开发。在开发“股票点播”系统中,我们选用了由ATL封装的OLE DB类来开发股票数据库,由于股票数据库往往上100MB,并且程序不断往数据库追加

天道酬勤 2296

The ATL OLE DB Provider templates only seem to support read-

The ATL OLE DB Provider templates only seem to support read-only rowsets and making them support updating of data isn’t as easy as you’d expect!只读数据库模板

使用OLEDB编写数据库应用程序

使用OLE DB5.1    概述OLE DB的存在为用户提供了一种统一的方法来访问所有不同种类的数据源。OLE DB可以在不同的数据源中进行转换。利用OLE DB,客户端的开发人员在进行数据访问时只需把精力集中在很少的一些细节上,而不必弄懂大量不同数据库的访问协议。OLE DB是一套通过COM接口访问数据的ActiveX接口。这个OLE DB接口相当通用,足以提供一种访问数据的统一手段,而不管存

zzh的专栏 1915

ATL模板库中的OLEDB与ADO

上次将OLEDB的所有内容基本上都说完了,从之前的示例上来看OLEDB中有许多变量的定义,什么结果集对象、session对象、命令对象,还有各种缓冲等等,总体上来说直接使用OLEDB写程序很麻烦,用很大的代码量带来的仅仅只是简单的功能。还要考虑各种缓冲的释放,各种对象的关闭,程序员的大量精力都浪费在无用的事情上,针对这些情况微软在OLEDB上提供了两种封装方式,一种是将其封装在ATL模板库中,一种...

Masimaro的专栏 764

VC++ 自定义向导(如何生成,修改,调试自定义向导)

这是一篇关于C++中自定义向导非常好的文档。 取自:http://msdn.microsoft.com/en-us/library/aa730846(v=vs.80).aspx Inside Visual C++ Wizards Shankar Vaidyanathan, Gabriel Esparza-Romero, Andras Tantos, Boris

huangxy10的专栏 4334

MFC OLEDB数据库

class CLinkInfo : public CCommand > { public: ///////////////////////////////////////////////// //构造函数 CLinkInfo () { //Allow 1 k for SQL WHERE clause memset(m_strFilter, 0, 50); // strcpy (m_s

autumn20080101的专栏 1797

一些实用链接

miscSmartPhone上与IMEI号相关联的软件破解 上海服务器100M=2000元/月 上海服务器100M独享=2.5万 上海服务器托管100M独享=16000元/年 共用一个IP地址 10台机器共享上网就这样配 基于 Windows Mobile 的 Pocket PC 和 Smartphone 的开发工具简介 宽带共享常见经典问题 广告商信誉大家评 彩屏智能手机 VC++相关我的ATL

梦的归宿 1027

MFC和ATL下通用的ADO模块

Ansi字符集和Unicode字符集下均编译通过。

批量获取DataGrid控件模板列中的数据

 

zgh2002007的专栏 1465

浅析ATL中类厂的创建及其IUnkown接口的获取

先贴2个很重要的数据结构:对象映射表和接口映射表 struct _ATL_OBJMAP_ENTRY  {      const CLSID* pclsid;      HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);      _ATL_CREATORFUNC* pfnGetClassObject;  //创建类厂的函数指针  

dahaiI0的专栏 2442

C++ Standard Library/std/STL/ATL/WTL的区别与联系

0. Standard Library C++标准库,C++ Standard Library,是类库和函数的集合,其使用核心语言写成,由c++标准委员会制定,并不断维护更新。 简单的来说除了支持文件之外C++   标准库主要包含了三个部分:C   标准库的   C++   版本;C++   IO   库;C++   STL     C++标准库的内容基本可以分以下为10类。

Invoker's Tower 3261

Ado编译错误解决办法

@2018-02-26 问题描述,今天将控件由win7向winserver进行编译的时候,出现了ado相关的问题。 Error 25 error C2039: '_Recordset_DeprecatedPtr' : is not a member of 'ADODB 等报错。 解决办法 将msado15和msjro两个dll换成当前系统里program files(大概)下的。即可...

hao931126的博客 892

数据访问技术的演变(转载)

数据访问技术的演变发布日期: 4/1/2004 | 更新日期: 4/1/2004Wei-Meng Lee在数据库出现的早期,开发人员只需要了解正在使用的数据库产品的详尽知识。但数据库产品和技术发展很快。从关系数据库到非关系数据存储区(如电子邮件和文件系统),数据访问技术必须始终追随技术的飞速变化。并且,随着客户端/服务器及多层应用程序结构的出现,现在开发人员必须了解多种数据访问技术。大多数开发人员

梦的归宿 1515
上一篇: 字节长度,字节对齐以及类,对象的长度
下一篇: loadrunner监视linux服务器的安装与操作
vinchwang
博客等级 码龄20年 2粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值