程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> ATL COM和ADO

ATL COM和ADO

編輯:關於VC++

最近我在NIIT.Bangalore做一個在線銀行工程。這個工程幾乎是用VB編寫,僅有一小部分涉及ATL組件,僅僅能教會我們編寫分布式應用程序。我編寫的一個中間層組件用到了ATL和ADO來查詢後端(SQL Server),部分代碼展示在這裡。

我假設讀者懂(至少了解)ATL 的 COM 編程和 VB 的 ADO 編程

什麼是ADO?

ADO是 ActiveX數據對象(ActiveX Data Object)的縮寫。ADO使用OLEDB數據支持提供了一個面向對象的訪問數據源的接口,它是DAO and RDO 對象模型的集大成者,集合了DAO 和 RDO 的優點。

C++編寫OLEDB程序很容易。但是,那些沒有提供指針和其他C++特性的語言(如Visual Basic)實現OLEDB就很難了。

這就是ADO真正露臉的原因。ADO是基於COM接口技術的OLEDB的高級接口,所以,任何支持COM的應用程序都可以實現ADO。

ADO的特性

允許訪問所有的數據類型

提供自由線程

提供異步查詢

提供客戶端和服務器端指針

提供分離的記錄集

ADO的體系結構

在ADO模型中,我們將使用三種主要的對象類型:

Connection

Command

Recordset

Connection 對象用來建立與數據源的連接,首先,數據源名稱,所在位置,用戶ID,密碼等都存儲在ConnectionString對象中,用來傳遞給Connection對象來連接數據源。

Command 對象用來執行SQL命令,查詢和存儲過程

當一個查詢被執行了,它返回一組由Recordset對象存儲的結果集,Recordset中的數據可以被修改並更新到數據庫中。

使用ADO

首先,我們將創建一個ATL DLL組件。這個組件由一個方法,該方法有一個輸入參數(該工程的用戶ID)並返回相應的Recordset結果引用給VB 的客戶機,然後客戶機在一個窗體中顯示數據。

為了創建DLL ,我們使用ATL COM AppWizard產生一個應用程序框架,給工程命名為FindCust,選擇服務器類型為 Dynamic Link Library ,並選擇support MFC library.選項。

向工程插入一個新的ATL對象(New ATL Object ),選擇Simple Object 在 ATL Object Wizard Properties窗口的Short Name文本框中輸入 Search 並點擊OK,添加了對象。

在類視圖(CLASSVIEW)中,右擊接口名稱並添加一個方法,給該方法起名為SearchCust,並把下面的文字輸入到Parameters文本框中:

[in] BSTR bstrcustid,[out,retval] _Recordset **ptr

點擊OK按鈕添加這個方法。由於SearchCust 方法返回一個Recordset 對象的引用,所以我們需要導入(import)ADO庫,打開StdAfx.h 文件並添加下列代碼:

#import "C:\Program Files\Common Files\System\ADO\MSADO15.DLL"
rename_namespace("ADOCust") rename("EOF","EndOfFile")
using namespace ADOCust;

這一步是為了讓VC++編譯器明白在對象類型庫 MSADO15.DLL 中定義的ADO對象。rename_namespace 函數改變了一個名字空間的名稱,DLL文件就是被導入到該名字空間中的。rename選項把EOF關鍵字改成 EndOfFile,這是因為EOF已經被定義到標准頭文件中了。

.idl文件中也包含了SearchCust 方法,改方法返回Recordset 對象的引用,為了讓MIDL編譯器也明白ADO對象,用importlib語句在.idl文件 的library 段中導入類型庫( 在importlib "stdole2.tlb"之後)如:

importlib("C:\Program Files\Common Files\System\ADO\MSADO15.DLL");

把接口的定義移動到.idl 文件新添加的imporlib語句的後邊,也是為了讓MIDL編譯器明白ADO對象做完後,我的接口塊定義如下:

[
object,
uuid(EB78D558-E071-4D25-80DD-41FD3519934E),
dual,
helpstring("ISearch Interface"),
pointer_default(unique)
]
interface ISearch : IDispatch
{
   [id(1), helpstring("method SearchCust")]
     HRESULT SearchCust([in] BSTR rcustid,
     [out,retval] _Recordset **ptr);
};

構建ATL組件

現在我們已經准備好編寫SearchCust方法的代碼來獲得相應的訊息,我們需要做如下這些事情:

初始化COM庫

連接到數據源

執行SQL命令

返回Recordset對象

反初始化COM庫

初始化COM庫:

CoInitialize(NULL);

為了連接數據源,首先要聲明一個Connection對象指針傳遞組件類的ID:

_ConnectionPtr conptr(__uuidof(Connection));

現在調用Open函數來家裡與數據源的連接:

conptr->Open(_T("Provider=SQLOLEDB.1;
        Data Source=SQLServer;
        Initial Catalog=Customer"),
        _T("user1"),
        _T(""),
        adOpenUnspecified);

Open函數由四個參數。第一個參數是連接字符串,包含提供者的名字和要連接的SQL Server的名字。 第二個參數和第三個參數是用來建立連接的用戶名和密碼。 第四個參數是使用的指針的類型 _T宏確保了字符串的UNICODE的兼容性。

為了執行SQL命令,通過傳遞一個Command對象的CLSID來建立一個Command對象指針:_CommandPtr cmd(__uuidof(Command));

設置Command對象的ActiveConnection 屬性為打開的Connection對象的指針:

cmd->ActiveConnection=conptr;

把要執行的SQL語句存儲到Command對象的CommandText屬性中:

cmd->CommandText="<Your SQL statement goes here>"

創建Recordset 對象並指明作為記錄源的Command對象:

_RecordsetPtr rst(__uuidof(Recordset));
rst->PutRefSource(cmd);

現在打開Recordset,使用Open方法,如下:

_variant_v vNull;
rst->Open(vNull,
     vNull,
     adOpenDynamic,
     adLockOptimistic,
     adCmdText);
Open方法有個參數

 

第一個和第二個參數是數據源的名稱和各自的活動連接由於數據源在Connection對象中已經被ActiveConnection 屬性指定了,而且在Command 對象中也被指定了,所以第一個和第二個參數使用了NULL的變體值。第三個參數指明了指針類型,第四個參數指明了鎖定參數,第五個參數指明了在命令被發送時數據庫應該怎樣評估命令。現在創建的Recordset對象指針將會引用由SQL語句返回的記錄集,我們應該把這個Recordset返回給客戶機,使用如下代碼:

rst->QueryInterface(__uuidof(_Recordset), (void **) ptr);

QueryInterface函數使用了Recordset對象的IID 並返回由SQL語句返回的記錄集的引用,當客戶機調用SearchCust 方法時,這個指針會返回給客戶機。

反初始化 COM庫:

::CoUninitialize();

現在構建(build)組件,這將會把DLL注冊到注冊表中。

創建客戶機

打開 VB 並創建一個新的標准EXE工程(Standard EXE project)。很簡單,這裡就不詳細描述了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved