VC++学习笔记(7)——在Visual C++中使用ADO(续)

来源:互联网 发布:golang 引用c 编辑:程序博客网 时间:2024/06/06 00:36

 

VC中实现对ADO操作通常有三种方法: #import方法;利用MFC OLE的ClassWizard;通过Windows API中COM相关的函数。

在这三种方法中,#import是最方便的方法,它允许产生一个类似VB的类结构,使程序开发变得很方便。

下面分别介绍这三种方法。

1.#import方法

在#import方法中,需要提供所要包含的类型库的路径和名称,VC能够自动产生一个对GUIDs的定义,以及自动生成对ADO对象的封装。对任何引用的类型库,VC会在编译的时候自动生成两个文件:

头文件(.tlh):包含了所列举的类型和对类型库中对象的定义;

实现文件(.tli):对类型库对象模型中的方法产生封装。

例如,在stdafx.h文件中增加对msado15.dd的#import之后,VC会产生msado15.tlh和msado15.tli两个文件。

#import能够使用一个新的类_com_ptr_t,它也被称为智能指针。智能指针能够自动执行QuyerInterface、AddRef和Release函数。

下面的代码演示了如何使用#import在应用中实现对ADO的操作:

#import "c:/program files/common files/system/ado/msado15.dll" /no_namespace   rename ( "EOF", "adoEOF" )

重命名EOF是必要的,因为典型的VC应用都已经定义了EOF作为常数-1。

通常来说,操作一个自动化对象需要定义和初始化一个用来操作的变量。可以通过使用智能指针(_com_ptr_t)的构造函数传递一个有效的CLSID或者是PROGID,也可以通过_com_ptr_t::CreateInstance()方法来定义对象。具体代码如下所示:

  _ConnectionPtr Conn1( _uuidof( Connection ) );

也可以采用下面的代码实现同样的功能:

_ConnectionPtr Conn1 = NULL; //定义对象

HRESULT hr = S_OK;   //创建实例

hr =Conn1.CreateInstance( _uuidof( Connection ) );

推荐采用第二种方式,因为用第一种方式不能返回一个失败的HRESULT,所以也就不能判断ADO连接对象是成功还是失败,以及失败的原因。注意这里的_uuidof( Connection)中的Connection是在.tlh文件中定义的。通过把它传递给方法CreateInstance,就可以创建一个有效的 ADOConnection对象。

需要注意的是#import的no_namespace属性,它告诉编译器该类在不在一个单独的名字空间中。使用no_namespace意味着不需要在初始化变量时引用名字空间。当然如果在应用中需要导入多个类型库时,最好不要使用 no_namespace,以免引起名字冲突。

下面是一个简单的采用了#import方法的基于ADO应用的示例代码:

#include

#import rename("EOF", "adoEOF")

void main()

{

HRESULT hr = S_OK;   //因为没有在#import中指定no_namespace,所以必须采用ADODB::这样的形式来定义变量类型

ADODB::_RecordsetPtr Rs1 = NULL;

//通过ODBC建立ADO连接

_bstr_t Connect( "DSN=AdoDemo;UID=sa;PWD=;" );

_bstr_t Source ( "SELECT * FROM Authors" );

CoInitialize();   //初始化Rs1对象

hr = Rs1.CreateInstance( _uuidof( ADODB::Recordset ) ); //省略对返回值hr的判断  Rs1->Open( Source, Aonnect, ADODB::adOpenForwardOnly,   ADODB::adLockReadOnly,-1 );   //此处可以添加对记录集Rs1进行操作的代码  Rs1->Close();

Rs1 = NULL;

::MessageBox( NULL,"Success!","",MB_OK );

CoUninitialize();

}

 用MFC OLE创建ADO应用

MFC OLE同样能够封装(wrapper)一个类型库,但是与#import不同,它不能从类型库中产生枚举类型。MFC类CString和 COleVariant隐藏了BSTRS和Variants的细节。由MFC OLE产生的类都继承了类ColeDispatchDriver,由ADO产生的失败的HRESULTS被封装在类 ColeDispatchException中。

用MFC OLE ClassWizard创建ADO应用的步骤如下:

从Tools菜单中,选择Options选项中的Directories tab条目,在Show Directories中的Library Files中增加路径C:/program files/common files/system/ado,设置包含ADO类型库的路径。

从View菜单中,激活ClassWizard,点击Add Class按钮并选择"From A Type Library..."选项,然后在Type Library dialog box对话框中,从C:/program files/common files/system/ado中选择文件msado15.dll,在Confirm Classes对话框中,选择所有列出的类并按OK按钮退出ClassWizard。这样,ClassWizard便生成了两个文件msado15.h和 msado15.cpp。

下面是实现ADO应用的示例代码:

//初始化COM对象

AfxOleInit();

...

//定义数据集对象

_Recordset Rs1;

COleException e;

COleVariant Connect( "DSN=AdoDemo;UID=sa;PWD=;" );

COleVariant Source ( "SELECT * FROM Authors" );   //创建数据集对象  Rs1.CreateDispatch("ADODB.Recordset.2.0",&e );

Rs1.Open( (VARIANT) Source,(VARIANT) Connect,0, 1, -1 );   //此处可以添加对结果集Rs1进行处理的代码

Rs1.Close();

Rs1.ReleaseDispatch();

AfxMessageBox("Success!");

 用COM API创建ADO工程

#import和MFC OLE都围绕着一个给定的自动化对象产生了一个封装类,它们分别继承自_com_ptr_t和ColeDispatchDriver。其实也可以通过使用 Windows API函数直接初始化ADO对象。为了直接使用ADO和COM对象,需要添加两个头文件adoid.h和adoint.h,这两个头文件定义了 CLSIDs、接口定义和操作ADO类型库所需要的枚举类型。此外,还需要增加头文件INITGUID.H。

为了能够编译用COM API创建的ADO工程文件,还需要在机器中安装OLE DB SDK或者是MSDASDK工具。下面是利用API创建ADO的简单的示例代码:

#include "adoid.h" // ADO的GUID's

#include "adoint.h" // ADO的类、枚举等等

void main()

{

HRESULT hr = S_OK;   // ADORecordset 是在adoint.h中定义的  ADORecordset *Rs1 = NULL;

VARIANT Source;

VARIANT Connect;

VariantInit( &Source );

VariantInit( &Connect );

Source.vt = VT_BSTR;Connect.bstrVal = ::SysAllocString( L"DSN=AdoDemo;UID=sa;PWD=;" );

hr = CoCreateInstance( CLSID_CADORecordset, NULL, CLSCTX_INPROC_SERVER, IID_IADORecordset, (LPVOID *) &Rs1 );

if( SUCCEEDED( hr ) ) hr = Rs1->Open(Source,Connect,adOpenForwardOnly, adLockReadOnly, -1 );   //对记录集Rs1进行处理

if( SUCCEEDED( hr ) ) hr = Rs1->Close();

if( SUCCEEDED( hr ) )

{ Rs1->Release(); Rs1 = NULL; }

if( SUCCEEDED( hr ) )

::MessageBox( NULL, "Success!", "", MB_OK );

}

 

C++ Extensions

如果用C++进行ADO应用程序开发,应该使用ADO C++ Extensions。我们知道,用VB或者VBScript来操作ADO是非常方便的,但是如果使用C++或者是Java,就必须要处理类似 Variants这样的数据结构以实现和C++数据结构的转换,而这种处理无疑是所有C++开发人员都很头疼的事情。但如果使用C++ Extensions的话,ADO就不需要从数据提供者处得到列信息,而是在设计时刻使用开发人员提供的列信息。以下是一个简单的示例:

//创建和具体记录相对应的类

class CAuthor : public CADORecordBinding

{

BEGIN_ADO_BINDING(CCustomRs1)

ADO_VARIABLE_LENGTH_ENTRY4(1,adVarChar, m_szau_id, sizeof(m_szau_id), FALSE)

ADO_VARIABLE_LENGTH_ENTRY4(2, adVarChar,m_szau_fname,sizeof(m_szau_fname), FALSE)

ADO_VARIABLE_LENGTH_ENTRY4(3,adVarChar,m_szau_lname,sizeof(m_szau_lname), FALSE)

END_ADO_BINDING()

protected:

char m_szau_id[12];

char m_szau_fname[21];

char m_szau_lname[41];

};

void FetchAuthorData()

{

  CAuthor author;   //记录集对象

  _RecordsetPtr pRs;

   IADORecordBinding *piAdoRecordBinding;   //获取COM对象接口指针

      pRs.CreateInstance(_uuidof(Recordset));   //得到需要的记录集

  pRs->Open("select au_id,au_fname,au_lname from Employees","Provider=SQLOLEDB;Data Source=sureshk1;Database=pubs;User Id=sa;Password=;", adOpenForwardOnly, adLockReadOnly,adCmdText); //查询接口IADORecordBinding

   pRs->QueryInterface(_uuidof(IADORecordBinding),(LPVOID*)&piAdoRecordBinding);   //绑定对象

  piAdoRecordBinding->BindToRecordset(&author);   //得到记录中的相关内容  while (VARIANT_FALSE == pRs->EOF)

{

   printf("%s %s %s", author.m_szau_id,

   author.m_szau_fname, author.m_szau_lname);

   pRs->MoveNext();

}   //释放对象

 

原创粉丝点击