使用OLEDB編寫資料庫應用程式
OLE DB的存在為使用者提供了一種統一的方法來訪問所有不同種類的資料來源。OLE DB可以在不同的資料來源中進行轉換。利用OLE DB,客戶端的開發人員在進行資料訪問時只需把精力集中在很少的一些細節上,而不必弄懂大量不同資料庫 的訪問協議。
OLE DB是一套通過COM介面訪問資料的ActiveX介面。這個OLE DB介面相當通用,足以提供一種訪問資料的統一手段,而不管儲存資料所使用的方法如何。同時,OLE DB還允許開發人員繼續利用基礎資料庫技術的優點,而不必為了利用這些優點而把資料移出來。
使用ATL使用OLE DB資料使用程式
由於直接使用OLE DB的物件和介面設計資料庫應用程式需要書寫大量的程式碼。為了簡化程式設計,Visual C++提供了ATL模板用於設計OLE DB資料應用程式和資料提供程式。
利用ATL模板可以很容易地將OLE DB與MFC結合起來,使資料庫的引數查詢等複雜的程式設計 得到簡化。MFC提供的資料庫類使OLE DB的程式設計更具有面向物件的特性。Viual C++所提供用於OLE DB的ATL模板可分為資料提供程式的模板和資料使用程式的模板。
使用ATL模板建立資料應用程式一般有以下幾步驟:
1、 建立應用框架
2、 加入ATL產生的模板類
3、 在應用中使用產生的資料訪問物件
5.3 不用ATL使用OLE DB資料使用程式
利用ATL模板產生資料使用程式較為簡單,但適用性不廣,不能動態適應資料庫的變化。下面我們介紹直接使用MFC OLE DB類來生成資料使用程式。
模板的使用
OLE DB資料使用者模板是由一些模板組成的,包括如下一些模板,下面對一些常用類作一些介紹。
1、 會話類
CDataSource類
CDataSource類與OLE DB的資料來源物件相對應。這個類代表了OLE DB資料提供程式和資料來源之間的連線。只有當資料來源的連線被建立之後,才能產生會話物件,可以呼叫Open來開啟資料來源的連線。
CSession類
CSession所建立的物件代表了一個單獨的資料庫訪問的會話。一個用CDataSource類產生的資料來源物件可以建立一個或者多個會話,要在資料來源物件上產生一個會話物件,需要呼叫函式Open()來開啟。同時,會話物件還可用於建立事務操作。
CEnumeratorAccessor類
CEnumeratorAccessor類是用來訪問列舉器查詢後所產生的行集中可用資料提供程式的資訊的訪問器,可提供當前可用的資料提供程式和可見的訪問器。
2、 訪問器類
CAcessor類
CAccessor類代表與訪問器的型別。當用戶知道資料庫的型別和結構時,可以使用此類。它支援對一個行集採用多個訪問器,並且,存放資料的緩衝區是由使用者分配的。
CDynamicAccessor類
CDynamicAccessor類用來在程式執行時動態的建立訪問器。當系統 執行時,可以動態地從行集中獲得列的資訊,可根據此資訊動態地建立訪問器。
CManualAccessor類
CManualAccessor類中以在程式執行時將列與變數繫結或者是將引數與變數捆定。
3、 行集類
CRowSet類
CRowSet類封裝了行集物件和相應的介面,並且提供了一些方法用於查詢、設定資料等。可以用Move()等函式進行記錄移動,用GetData()函式讀取資料,用Insert()、Delete()、SetData()來更新資料。
CBulkRowset類
CBulkRowset類用於在一次呼叫中取回多個行控制代碼或者對多個行進行操作。
CArrayRowset類
CArrayRowset類提供用陣列下標進行資料訪問。
4、 命令類
CTable類
CTable類用於對資料庫的簡單訪問,用資料來源的名稱得到行集,從而得到資料。
CCommand類
CCommand類用於支援命令的資料來源。可以用Open()函式來執行SQL命令,也可以Prepare()函式先對命令進行準備,對於支援命令的資料來源,可以提高程式的靈活性和健壯性。
在stdafx.h標頭檔案裡,加入如下程式碼。
#include <atlbase.h> extern CComModule _Module; #include <atlcom.h> #include <atldbcli.h> #include <atldbsch.h> // if you are using schema templates
在stdafx.cpp檔案裡,加入如下程式碼。
#include <atlimpl.cpp> CComModule _Module;
決定使用何種型別的存取程式和行集。
獲取資料
在開啟資料來源,會話,行集物件後就可以獲取資料了。所獲取的資料型別取決於所用的存取程式,可能需要繫結列。按以下步驟。
1、 用正確的命令開啟行集物件。
2、 如果使用CManualAccessor,在使用之前與相應列進行繫結。要繫結列,可以用函式GetColumnInfo,如下所示:
// Get the column information ULONG ulColumns = 0; DBCOLUMNINFO* pColumnInfo = NULL; LPOLESTR pStrings = NULL; if (rs.GetColumnInfo(&ulColumns, &pColumnInfo, &pStrings) != S_OK) AfxThrowOLEDBException(rs.m_pRowset, IID_IColumnsInfo); struct MYBIND* pBind = new MYBIND[ulColumns]; rs.CreateAccessor(ulColumns, &pBind[0], sizeof(MYBIND)*ulColumns); for (ULONG l=0; l3、 用while迴圈來取資料。在迴圈中,呼叫MoveNext來測試游標的返回值是否為S_OK,如下所示:
while (rs.MoveNext() == S_OK) { // Add code to fetch data here // If you are not using an auto accessor, call rs.GetData() }4、 在while迴圈內,可以通過不同的存取程式獲取資料。
1) 如果使用的是CAccessor類,可以通過使用它們的資料成員進行直接訪問。如下所示:
2) 如果使用的是CDynamicAccessor 或CDynamicParameterAccessor 類,可以通過GetValue或GetColumn函式來獲取資料。可以用GetType來獲取所用資料型別。如下所示:
while (rs.MoveNext() == S_OK) { // Use the dynamic accessor functions to retrieve your // data ULONG ulColumns = rs.GetColumnCount(); for (ULONG i=0; i3) 如果使用的是CManualAccessor,可以指定自己的資料成員,繫結它們。就可以直接存取。如下所示:
while (rs.MoveNext() == S_OK) { // Use the data members you specified in the calls to // AddBindEntry. wsprintf("%s", szFoo); }決定行集的資料型別
在執行時決定資料型別,要用動態或手工的存取程式。如果用的是手工存取程式,可以用GetColumnInfo函式得到行集的列資訊。從這裡可以得到資料型別。
總結
由於現在有多種資料來源,,想要對這些資料進行訪問管理的唯一途徑就是通過一些同類機制來實現,如OLE DB。高階OLE DB結構分成兩部分:客戶和提供者。客戶使用由提供者生成的資料。
就像其它基於COM的多數結構一樣,OLE DB的開發人員需要實現很多的介面,其中大部分是模板檔案。
當生成一個客戶物件時,可以通過ATL物件嚮導指向一個數據源而建立一個簡單的客戶。ATL物件嚮導將會檢查資料來源並建立資料庫的客戶端代理。從那裡,可以通過OLE DB客戶模板使用標準的瀏覽函式。
當生成一個提供者時,嚮導提供了一個很好的開端,它們僅僅是生成了一個簡單的提供者來列舉某一目錄下的檔案。然後,提供者模板包含了OLE DB支援的完全補充內容。在這種支援下,使用者可以建立OLE DB提供者,來實現行集定位策略、資料的讀寫以及建立書籤。