複製鏈接
請複製以下鏈接發送給好友

ActiveX Data Objects

鎖定
一種程序對象,用於表示用户數據庫中的數據結構和所包含的數據。在Microsoft Visual Basic編輯器中,可以使用ADO對象以及ADO的附加組件(稱為Microsoft ADO Extensions for DLL and Security(ADOX))來創建或修改表和查詢、檢驗數據庫、或者訪問外部數據源。還可在代碼中使用ADO來操作數據庫中的數據。
中文名
ActiveX Data Objects
性    質
一種程序對象
含    義
用户數據庫中的數據結構和所包含
作    用
實現訪問關係

ActiveX Data Objects簡介

ADO (ActiveX Data Objects,ActiveX數據對象)是Microsoft提出的應用程序接口API)用以實現訪問關係或非關係數據庫中的數據。例如,如果您希望編寫應用程序從DB2Oracle數據庫中向網頁提供數據,可以將ADO程序包括在作為活動服務器頁(ASP)的HTML文件中。當用户從網站請求網頁時,返回的網頁也包括了數據中的相應數據,這些是由於使用了ADO代碼的結果。
像Microsoft的其它系統接口一樣,ADO是面向對象的。它是Microsoft全局數據訪問(UDA)的一部分,Microsoft認為與其自己創建一個數據,不如利用UDA訪問已有的數據庫。為達到這一目的,Microsoft和其它數據庫公司在它們的數據庫和Microsoft的OLE數據庫之間提供了一個“橋”程序,OLE數據庫已經在使用ADO技術。ADO的一個特徵(稱為遠程數據服務)支持網頁中的數據相關的ActiveX控件和有效的客户端緩衝。作為ActiveX的一部分,ADO也是Microsoft的組件對象模式(COM)的一部分,它的面向組件的框架用以將程序組裝在一起。
ADO從原來的Microsoft數據接口遠程數據對象RDO)而來。RDO與ODBC一起工作訪問關係數據庫,但不能訪問如ISAM和VSAM的非關係數據庫。
ADO 是對當前微軟所支持的數據庫進行操作的最有效和最簡單直接的方法,它是一種功能強大的數據訪問編程模式,從而使得大部分數據源可編程的屬性得以直接擴展到你的Active Server 頁面上。可以使用ADO 去編寫緊湊簡明的腳本以便連接到 Open Database Connectivity (ODBC) 兼容的數據庫和 OLE DB 兼容的數據源,這樣 ASP 程序員就可以訪問任何與 ODBC 兼容的數據庫,包括 MS SQL SERVER、Access、 Oracle等等。
比如,如果網站開發人員需要讓用户通過訪問網頁來獲得存在於IBM DB2或者Oracle數據庫中的數據,那麼就可以在ASP頁面中包含ADO程序,用來連接數據庫。於是,當用户在網站上瀏覽網頁時,返回的網頁將會包含從數據庫中獲取的數據。而這些數據都是由ADO代碼做到的。
ADO是一種面向對象編程接口,微軟介紹説,與其同IBM和Oracle提倡的那樣,創建一個統一數據庫,不如提供一個能夠訪問不同數據庫的統一接口,這樣會更加實用一些。為實現這一目標,微軟在數據庫和微軟的OLE DB中提供了一種“橋”程序,這種程序能夠提供對數據庫的連接。 開發人員在使用ADO時,其實就是在使用OLE DB,不過OLE DB更加接近底層。ADO的一項屬性-遠程數據服務,支持“數據倉庫”ActiveX 組件以及高效的客户端緩存。作為ActiveX的一部分,ADO也是COM組件的一部分。ADO是由早期的微軟數據接口——遠程數據對象RDO演化而來的。RDO同微軟的ODBC一同連接關係數據庫,不過不能連接非關係數據庫。
ADO向我們提供了一個熟悉的,高層的對OLE DB的Automation封裝接口。對那些熟悉RDO的程序員來説,你可以把OLE DB比作是ODBC驅動程序。如同RDO對象是ODBC驅動程序接口一樣,ADO對象是OLE DB的接口;如同不同的數據庫系統需要它們自己的ODBC驅動程序一樣,不同的數據源要求它們自己的OLE DB提供者(OLE DB provider)。但微軟正積極推廣該技術,並打算用OLE DB取代ODBC。
ADO向VB程序員提供了很多好處。包括易於使用,熟悉的界面,高速度以及較低的內存佔用(已實現ADO2.0的Msado15.dll需要佔用342K內存,比RDO的Msrdo20.dll的368K略小,大約是DAO3.5的Dao350.dll所佔內存的60%)。同傳統的數據對象層次(DAO和RDO)不同,ADO可以獨立創建。因此你可以只創建一個"Connection"對象,但是可以有多個,獨立的"Recordset"對象來使用它。ADO針對客户/服務器以及WEB應用程序作了優化。

ActiveX Data Objects定義

  • ADO 是一項微軟的技術 [1] 
  • ADO 指 ActiveX 數據對象(ActiveX Data Objects)
  • ADO 是一個微軟的 Active-X 組件
  • ADO 會隨微軟的 IIS 被自動安裝
  • ADO 是一個訪問數據庫中數據的編程接口

ActiveX Data Objects訪問方法

從一個 ASP 頁面內部訪問數據庫的通常的方法是: [1] 
  1. 創建一個到數據庫的 ADO 連接
  2. 打開數據庫連接
  3. 創建 ADO 記錄集
  4. 從記錄集提取您需要的數據
  5. 關閉記錄集
  6. 關閉連接

ActiveX Data Objects對象總結

對象
説明
Command
Command 對象定義了將對數據源執行的指定命令。
Connection
代表打開的、與數據源的連接。
DataControl (RDS)
綁定Recordset到一個或多個控件上,以便在 Web 頁上顯示數據。
DataFactory (RDS Server)
實現對客户端應用程序的指定數據源進行讀/寫數據訪問的方法。
DataSpace (RDS)
創建客户端代理以便自定義位於中間層業務對象
Error
包含與單個操作(涉及提供者)有關的數據訪問錯誤的詳細信息。
Field
代表使用普通數據類型的數據的列。
Parameter
參數化查詢或存儲過程的 Command 對象相關聯的參數或自變量。
Property
代表由提供者定義的 ADO 對象的動態特性。
RecordSet
代表來自基本表或命令執行結果的記錄的全集。

ActiveX Data Objects接口簡介

ADO庫包含三個基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口。
1、_ConnectionPtr接口
返回一個記錄集或一個空指針。通常使用它來創建一個數據連接或執行一條不返回任何結果的SQL語句,如一個存儲過程。
2、_CommandPtr接口
返回一個記錄集。它提供了一種簡單的方法來執行返回記錄集的存儲過程和SQL語句。
3、_RecordsetPtr接口
是一個記錄集對象。與以上兩種對象相比,它對記錄集提供了更多的控制功能,如記錄鎖定,遊標控制等。
4、接口間的區別與聯繫
使用_ConnectionPtr接口返回一個記錄集不是一個好的使用方法。對於要返回記錄的操作通常用_RecordsetPtr來實現。而用_ConnectionPtr操作時要想得到記錄條數得遍歷所有記錄,而用_RecordsetPtr時不需要。
在使用_CommandPtr接口時,你可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口裏直接使用連接串。如果你只執行一次或幾次數據訪問操作,後者是比較好的選擇。但如果你要頻繁訪問數據庫,並要返回很多記錄集,那麼,你應該使用全局_ConnectionPtr接口創建一個數據連接,然後使用_CommandPtr接口執行存儲過程和SQL語句。
同_CommandPtr接口一樣,_RecordsetPtr接口不一定要使用一個已經創建的數據連接,可以用一個連接串代替連接指針賦給_RecordsetPtr的connection成員變量,讓它自己創建數據連接。如果你要使用多個記錄集,最好的方法是同Command對象一樣使用已經創建了數據連接的全局_ConnectionPtr接口,然後使用_RecordsetPtr執行存儲過程和SQL語句。

ActiveX Data ObjectsADO 事件

ActiveX 數據對象 (ADO) 是添加到 Microsoft Active Server Pages (ASP) 的一套高級別接口,有利於服務器端與數據庫的連接。ADO 與低級別接口 (OLE DB) 一起使用則有利於 Microsoft Universal Data Access 策略。ADO 2.0 版可生成 Visual Studio Analyzer 事件。可使用這些事件跟蹤分佈式應用程序中的 ADO 交互。
ADO 生成的 Visual Studio Analyzer 事件
事件 事件描述 事件數據 [2] 
事件
事件描述
事件數據
ConnectionClose
指示 ADO 要與 OLE DB 數據源斷開連接。
無。
ConnectionOpen
指示 ADO 正在連接到 OLE DB 數據源。
如果客户端提供,則為連接到數據源所用的連接字符串。
Find
指示 ADO 客户端已調用 ADO Recordset.Find 函數。
“查找”操作的判據;根據該判據匹配記錄。
GetRows
指示 ADO 客户端已調用 ADO Recordset.GetRows 函數。
提取的行數。
QueryResult
指示數據庫已返回響應查詢的結果集。
無。
QuerySend
指示 ADO 正在執行命令。該事件可由下列函數觸發:
Connection.Execute
Command.Execute
Connection.
Recordset.Open
構成查詢的 SQL 語句。
RecordsetOpen
指示 ADO 正在打開遠程服務器上的記錄集。僅適用於三層方案。
打開記錄集的源(通常為行返回的命令文本)。
Sort
指示 ADO 準備篩選或對數據排序。
排序或篩選應用於記錄集數據的判據。
Transaction Rollback
指示 ADO 要中止當前本地事務。
返回真或假。如果為真,則保持中止,即該事務中止後緊跟着開始另一事務。如果為假,則不保持中止。
TransactionCommit
指示 ADO 正在提交 OLE DB 提供程序上的本地事務。
返回真或假。如果為真,則保留提交,即該事務提交後緊跟着開始另一事務。如果為假,則不保留提交。
TransactionStart
指示 ADO 正在開始 OLE DB 提供程序上的本地事務。
ADO 開始事務所基於的隔離級別。隔離級別指示可看到其他事務所做更改的哪一級別。
UpdateBatch
指示 ADO 正在向提供程序發送更新批處理。僅適用於三層方案。
如果有,為 ADO 將更新發送到的遠程服務器名。

ActiveX Data Objects組織形式

以前的對象模型,如DAO和RDO是層次型的。也就是説一個較低的數據對象如Recordset是幾個較高層次的對象,如Environment和QueryDef,的子對象。在創建一個QueryDef對象的實例之前,你不能創建DAO Recordset對象的實例。但ADO卻不同,它定義了一組平面型頂級對象.。
最重要的三個ADO對象是Connection, Recordset和Command. 本文將主要介紹Connection和Recordset這兩個對象。每個Connection的屬性定義了與數據源的連接。Recordset對象接收來自數據源的數據。Recordset可以與Connection一起起使用,先建立一個連接,然後獲取數據。儘管如此,Recordset也可以被單獨創建,其Connection參數可以在Open屬性定義。

ActiveX Data ObjectsADO 2.0特點

對於ADO1.5以前包括1.5的版本來説,從功着你可以通過這兩種方法解決同樣的問題;它不是指存在重命名的或者優化的功能相同的對象.因此,移植到ADO不是一個簡單的事情.從另一方面來説,一旦你熟練掌握了RDO或DAO技術的話,學習ADO是件相當容易的事情.
ADO 2.0的新特性包括事件處理,記錄集的延續,分層目錄結構指針和數據成形,分佈式事務處理,多維數據,遠程數據服務(RDS),以及對C++和Java的支持的增強.在鑽研一些Visual Basic代碼的時候將會見到所有的這些特性.當使用Visual J++時,我將舉例説明新的Windows Foundation Classes(WFC)是如何支持ADO的.ADO的最讓人激動的是在Visual Studio 6.0中的任何開發工具中你都可以找到對它的充分的支持.

ActiveX Data Objects編程模型

連接數據源 (Connection),可選擇開始事務。
可選擇創建表示 SQL 命令的對象 (Command)。
可選擇指定列、表以及 SQL 命令中的值作為變量參數 (Parameter)。
執行命令(Command、Connection 或 Recordset)。
如果命令以行返回,將行存儲在存儲對象中 (Recordset)。
可選擇創建存儲對象的視圖以便進行排序、篩選和定位數據 (Recordset)。
編輯數據。可以添加、刪除或更改行、列 (Recordset)。
在適當情況下,可以使用存儲對象中的變更對數據源進行更新 (Recordset)。
在使用事務之後,可以接受或拒絕在事務中所做的更改。結束事務 (Connection)。

ActiveX Data Objects使用方法

安裝ADO,在VB的工程->引用對話框中選擇 "ActiveX Data Objects 1.5 Library" (ADODB).在其下的 "ADO Recordset 1.5 Library"是一個客户端的版本(ADOR),它定義了有聚的數據訪問對象。ADOR 對於客户端的數據訪問來説是足夠的了,因為你不需要Connection對象來建立與遠程數據源的聯繫。
如果你想要訪問更多的外部數據源,你需要安裝這些外部數據源自己的OLE DB Provider,就象你需要為新的數據庫系統安裝新的ODBC驅動程序一樣。如果該外部數據源沒有自己的OLE DB Provider,你就得使用OLE DB SDK來自己為這個外部數據源創建一個OLE DB Provider了。這已不是本文討論的範圍了。

ActiveX Data Objects示例

下面的示例代碼以Northwinds數據庫作為遠程數據源,然後用ADO來訪問它。首先在控制面板中打開“32位數據源”,單擊“添加”按鈕。在彈出的對話框中選擇 "Microsoft Access Driver (*.mdb)" 作為數據源驅動程序
然後在對話框中填寫下面的內容
選擇數據庫Northwinds所在路徑。單擊完成,退出ODBC設備管理器
啓動一個新的VB工程,在窗體的Load事件中輸入下面的代碼:
Private Sub Form_Load()
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
'Set Connection properties
cn.ConnectionString = "DSN=RDC Nwind;UID=;PWD=;"
cn.ConnectionTimeout = 30
cn.Open
If cn.State = adStateOpen Then _
MsgBox "Connection to NorthWind Successful!"
cn.Close
End Sub
按F5運行程序,看看,一個消息框彈出來告訴你連接成功了。請注意,這裏我特別註明了是ADODB.Connection,而不是ADOR.Connection,這樣做是為了將二者區分開(如果你引用了ADODB和ADOR的話,這樣做很有必要)。連接字符串看上去同RDO的連接字符串差不多。事實上,二者確實差不多。
如果我們要訪問一個SQL server數據庫,你的Connection代碼看上去應象下面所示:
'設置連接屬性cn.Provider = "MSDASQL"
cn.ConnectionString = "driver={SQL Server};" & "server=prod1;uid=bg;pwd=;database=main"
cn.Open
"Provider"屬性指向SQL Server的OLE DB Provider.
回到我們的示例程序,讓我們創建一個Recordset對象來訪問“Orders”表,並從該表的"ShipCountry"字段中產生頭十個不重複的國家名。修改窗體Load事件中的代碼,讓它看上去象下面這樣。
Private Sub Form_Load()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sSQL As String
Dim sOut As String
Dim Count As Integer
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
' Set properties of the Connection.
cn.ConnectionString = "DSN=RDC Nwind;UID=;PWD=;"
cn.ConnectionTimeout = 30
cn.Open
If cn.State = adStateOpen Then _
MsgBox "Connection to NorthWind Successful!"
sSQL = "SELECT DISTINCT Orders.ShipCountry FROM Orders"
Set rs = cn.Execute(sSQL)
'Enumerate the recordset
sOut = ""
For Count = 1 To 10
sOut = sOut & rs("ShipCountry") & vbCrLf
rs.MoveNext
Next Count
MsgBox sOut, vbExclamation, "ADO Results"
cn.Close
End Sub
運行程序後,需要創建一個獨立的Recordset對象,該對象擁有自己的Connection屬性,就象下面的代碼所示:
Private Sub Form_Load()
Dim rs As ADODB.Recordset
Dim sSQL As String
Dim sOut As String
Dim Count As Integer
Set rs = New ADODB.Recordset
sSQL = "SELECT DISTINCT Orders.ShipCountry FROM Orders"
rs.Open sSQL, "DSN=RDC Nwind;UID=;PWD=;", adOpenDynamic
'Report Recordset Connection information
MsgBox rs.ActiveConnection, , "Connection Info"
'Enumerate the recordset
sOut = ""
For Count = 1 To 10
sOut = sOut & rs("ShipCountry") & vbCrLf
rs.MoveNext
Next Count
MsgBox sOut, vbExclamation, "ADO Results"
rs.Close
End Sub
上面代碼返回的結果同前例一樣,但是本代碼中的Recordset是獨立的。這一點是DAO和RDO做不到的。Recordset對象的Open方法打開一個代表從SQL查詢返回的記錄的遊標。雖然你可以用Connection對象同遠程數據源建立連接,但請記住,在這種情況下,Connection對象和Recordset對象是平行的關係。

ActiveX Data Objects總結

本文僅向你介紹了ADO強大的功能的冰山一角。微軟承諾,在將來ADO將會取代DAO和RDO。所以現在你應該考慮將你的數據訪問代碼投向ADO的懷抱。因為ADO的語法同現有的語法差不多。也許微軟或第三方會在將來開發出轉換向導來簡化這一轉換過程。從現在起,你就開發純ADO代碼的程序。你也可以繼續使用DAO或RDO代碼來開發你的程序,但落伍的感覺總是不好的。

ActiveX Data Objects編程應用

ADO(ActiveX Data Objects)是基於組件的數據庫編程接口,它是一個和編程語言無關的COM組件系統。本文主要介紹用ADO編程所需要注意的技巧和在VC下進行ADO編程的模式,並對C++Extensions進行了簡單的討論,希望對ADO開發人員有一定的幫助作用。因為ADO是一個和編程語言無關的COM組件系統,所以這裏討論的要點適用於所有的編程語言和編程環境,比如:VB、VBScript、VC、Java等等。
編程技巧
1.顯式定義對象類型
實際上,這條準則不僅適用於ADO編程,也適用於其他的與COM對象相關的編程。因為如果一開始就定義變量類型,則編譯器在編譯的時候就可以知道變量的類型,此時編譯器實際上是採用vtable偏移的方式來得到具體的COM對象包含的方法的地址(這一點和C++中虛函數的地址獲取方式類似);但如果一開始不指定變量類型的話,比如簡單地採用如下的語句:
DIM myCon as Object
或者是:
DIM myCon
這樣,編譯器在編譯的時候就不能得到變量的類型,而只能在運行的時候動態地得到方法的信息(通過使用接口IDispatch的Invoke方法來實現),如此為了得到方法的地址和相關的變量情況就需要在內部進行兩次調用,無疑會降低程序的運行速度。
2.綁定列到字段對象
在程序開始時就建立對字段對象的引用,可以避免在每次得到記錄後,再在Recordset::Fields中進行查找而增加系統的開銷。
例如,可以採用如下所示的代碼:
Private Sub TblBrowse_Click()
Dim fld1 As ADODB.Field
Dim fld2 As ADODB.Field
Dim rs As ADODB.Recordset
set rs=g_cn.execute(...)
'g_cn為全局對象adodb.connection
Set fld1 = rs.Fields(“id”) '數據表的字段
Set fld2 = rs.Fields(“name”) ’數據表的字段
If rs.BOF = False Then
While rs.BOF = False
Debug.Print fld1.Value
Debug.Print fld2.Value
rs.MoveNext
Wend
End If
rs.Close
End Sub
3.好的數據更新方式
儘管採用Recordset對象來更新數據是非常方便的,但是它的開銷也大,通過數據源對象返回的查詢集不僅包含了數據,而且也包含了元數據(metadata),在有些時候元數據可能比數據本身還要大,所以最好採用SQL語句來更新數據。還有要使用存儲過程而不是單一的SQL語句來獲取信息。因為存儲過程是在服務器端執行的,只把結果返回到客户端,這樣一方面可以降低網絡進行數據交互的開銷,另一方面使系統更加容易維護,並且能保持數據的一致性。
4.操作單條SELECT語句
在使用遊標時,最好使用集合的方法對單條的SELECT語句進行操作。Recordset::get_Collect方法和Recordset::put_Collect方法是Recordset 對象的快捷方式,可以快速地得到一個字段的值而不需要獲得關於一個字段的引用。例如,可以採用如下代碼:
Sub Collect()
Dim rs As New Recordset
rs.ActiveConnection = “...”
rs.Source=“一條SQL查詢語句”
rs.Open
Debug.Print rs.Collect(0),rs.Collect(1),rs.Collect(2)
Debug.Print rs!au_id, rs!au_fname, rs!au_lname
End Sub
5.查詢所需要的數據
儘管很多開發人員都習慣採用“SELECT * FROM TBL”的模式進行查詢,但是為了提高系統的效率,如果只需要其中某幾個字段的值,最好把這幾個字段直接寫出來,同時需要限定返回記錄集的範圍(通過WHERE子句進行限定)。
6.正確選擇遊標參數
如果只需要按順序讀取記錄並且不需要滾動和更新記錄,最好使用服務器端遊標(adUseServer)、僅向前遊標(adOpenForwardOnly)和讀加鎖(adLockReadOnly),這樣可以獲得最好的性能。如果需要滾動記錄,採用客户端遊標(adUseServer)會比採用服務器端遊標所得到的性能要好,因為ADO系統默認是採用服務器端遊標類型。當然如果數據集合相當大,採用服務器端遊標的性能會好一些。同時需要注意:如果採用客户端遊標,最好只採用讀加鎖(adLockReadOnly)的鎖類型,因為如果需要更新數據,客户端遊標引擎需要得到額外的信息(元數據),而獲取這個信息的代價是非常昂貴的。
7.調整CacheSize屬性
ADO使用記錄集對象的CacheSize屬性來決定提取和緩存的記錄的數目,當在緩存的範圍內瀏覽數據時,ADO就只從緩存中提取數據。當要瀏覽的數據超出緩存範圍的時候,ADO就釋放當前緩存,提取下一些記錄(提取的數目為CacheSize所指定的大小),所以必須根據具體的應用程序的情況,來設定CacheSize的大小,保證得到最佳的性能。
8.定義Command參數
在許多數據源中,得到參數信息和執行命令的代價幾乎是一樣的,所以最好自己在程序中定義好Command參數(也就是説要定義好參數的名稱、類型和方向信息),避免一些從數據提供者(Provider)那裏獲取信息的操作。
9.使用原始的提供者
MDAC對許多數據源提供了原始的數據提供者,比如SQL Server、Oracle和Access數據庫,這樣就不需要再通過ODBC來獲取數據(也就是説不需要再通過ODBC驅動這一層),這樣的好處是能更快地得到數據,並且能降低磁盤和內存的開銷。
10.斷開相關對象連接
如果使用客户端遊標,就要斷開Connection連接。ADO有一個特徵是當使用客户端遊標操作Recordset記錄集的時候,不需要和服務器保持聯繫。所以可以充分利用這個特性降低服務器端的開銷(服務器就不需要維護這些連接了)。當操作完記錄集需要更新時,可以重新和數據庫進行連接來更新數據。為了創建一個可以斷開連接的記錄集,同時需要使用靜態遊標(adOpenStatic)和批處理的加鎖模式(adLockBatchOptimistic)。下面是有關處理的VC代碼:
pRs.CreateInstance(__uuid(Recordset));
pRs->CursorLoction=adUseClient;
pRs->Open(strCmdText,strConnection,adOpenStatic,adLockBatchOptimistic,adCmdText);
pRs->PutRefActiveConnection(NULL);
//對記錄集對象pRs進行操作
//重新和數據庫建立連接
pRs->PutRefActiveConnectio(pCon);
//批量更新數據
pRs->UpdateBatch(adAffectAll);
需要注意的是:當執行批量更新時,必須自己處理數據衝突問題,因為更新數據時,其他用户也可能同時正在對該數據進行操作。
11.不返回記錄的選項
如果不需要返回記錄,要使用adExecuteNoRecords選項。ADO 2.0包括一個新的執行選項稱為adExecuteNoRecords。當使用該選項的時候,ADO就不會創建記錄集對象,不設置任何遊標屬性。數據提供者因為不需要認證集合的屬性而使性能得到優化。具體的例子如下:
con.Execute “insert into tbl values(fv1, fv2) ”, , adExecuteNoRecords
對僅有一條的執行語句採用Connection::Execute方法比使用Recordset::Open方法或者是Command::Execute方法的效果要好,因為ADO不保留任何命令狀態的信息,因此執行性能就有所改進。
12.使用正確的緩衝池
因為數據庫的打開和關閉非常消耗系統資源,因此,使用連接池對基於多層的應用的性能會有很大的提高。當使用MDAC的時候,開發人員本身並不需要考慮對數據庫連接的緩存,MDAC會自動處理它。連接池在兩個層次上提供支持:OLE DB sessions和ODBC連接。如果使用ADO,數據庫連接會自動被OLE DB session緩衝池所緩存;如果使用ODBC,可以利用在ODBC數據源管理中新的連接緩衝池選項對ODBC緩衝進行設置。

ActiveX Data Objects實現方法

我們知道,在VB下進行基於ADO的編程相對比較簡單,只要通過reference加載了適當的類型庫後,就可以正常地調用ADO對象。但是對於VC下的基於ADO的數據庫開發就稍微複雜一些。VC中實現對ADO操作通常有三種方法:
#import方法;
利用MFC OLE的ClassWizard;
通過Windows API中COM相關的函數。
在這三種方法中,#import是最方便的方法,它允許產生一個類似VB的類結構,使程序開發變得很方便。下面分別介紹這三種方法。

ActiveX Data Objects1.#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();
}

ActiveX Data Objects2.用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;
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!”);

ActiveX Data Objects3.用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
#include
#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;
Source.bstrVal = ::SysAllocString( L“SELECT * FROM Authors”);
Connect.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();
}
//釋放對象
參考資料