OLE DB是一種非常具有發(fā)展?jié)摿Φ臄?shù)據(jù)庫訪問技術(shù),它首先基于COM技術(shù),以COM規(guī)范為基礎(chǔ)建立數(shù)據(jù)庫訪問接口,成為介于數(shù)據(jù)庫應(yīng)用和數(shù)據(jù)源之間的一種通用數(shù)據(jù)訪問標(biāo)準(zhǔn);其次,OLE DB能夠訪問的數(shù)據(jù)源不再受到限制,OLE DB通過OLE DB服務(wù)器將數(shù)據(jù)源透明化。從6.0版本開始,Visual C++提供了對OLE DB的全面支持。
8.1 OLE DB原理
8.1.1 OLE DB與ODBC
在Visual C++之前的數(shù)據(jù)庫編程,通常都采用ODBC實現(xiàn)數(shù)據(jù)庫的訪問。ODBC是訪問數(shù)據(jù)庫的一個底層標(biāo)準(zhǔn),數(shù)據(jù)庫供應(yīng)商常常需要編寫ODBC驅(qū)動程序,以支持客戶對數(shù)據(jù)庫的訪問。雖然ODBC仍然是一個不斷發(fā)展的技術(shù),但是ODBC在以下兩個方面無法達(dá)到目標(biāo):
ODBC只能訪問關(guān)系型數(shù)據(jù)源,而現(xiàn)在有許多數(shù)據(jù)源,包括E-Mail、Word文檔、文本、Internet連接與傳輸?shù)鹊龋?/span>ODBC無法訪問的。
ODBC不能用于專門訪問特定的數(shù)據(jù),因此使得ODBC不夠強(qiáng)大,為了追求標(biāo)準(zhǔn),效率受到了嚴(yán)重影響。
OLE DB成功地解決了上述兩個問題。OLE DB為用戶提供了訪問不同類型的數(shù)據(jù)源的一種通用方法,它作為數(shù)據(jù)源和應(yīng)用程序的中間層,允許應(yīng)用程序以相同的接口訪問不同類型的數(shù)據(jù)源。OLE DB由一套通過COM訪問數(shù)據(jù)源的ActiveX接口組成,它提供一種訪問數(shù)據(jù)的統(tǒng)一手段,開發(fā)人員在開發(fā)時,不必考慮數(shù)據(jù)源的類型。
8.1.2 OLE DB的結(jié)構(gòu)
OLE DB由客戶(Consumer,也稱為應(yīng)用程序)和服務(wù)器(Provider,又稱為提供者程序)組成。客戶是指任何一個使用了OLE DB接口的系統(tǒng)或者應(yīng)用程序,其中包括OLE DB本身,而服務(wù)器是指所有提供OLE DB接口的軟件組件。
OLE DB客戶是使用數(shù)據(jù)的應(yīng)用程序,它通過OLE DB接口對數(shù)據(jù)提供者的數(shù)據(jù)進(jìn)行訪問和控制。在大多數(shù)情況下,前端的數(shù)據(jù)庫應(yīng)用開發(fā)都屬于客戶程序的開發(fā)。
OLE DB服務(wù)器是提供OLE DB接口的軟件組件,根據(jù)提供的內(nèi)容可以將服務(wù)器分成數(shù)據(jù)提供程序和服務(wù)器提供程序。數(shù)據(jù)提供程序擁有數(shù)據(jù)并將這些數(shù)據(jù)以表的形式存放,例如關(guān)系型DBMS、存儲管理器、電子表格和ISAM數(shù)據(jù)庫等。服務(wù)器提供程序不擁有數(shù)據(jù),但是可以通過利用OLE DB接口建立一些提供服務(wù)的組件。從某種意義上來說,服務(wù)組件既是客戶又是服務(wù)器。
對于一個完整的數(shù)據(jù)庫應(yīng)用程序來說,客戶和數(shù)據(jù)提供程序都是必不可少的。然而服務(wù)提供程序卻是可以省略的。當(dāng)客戶需要對數(shù)據(jù)庫進(jìn)行操作時,他并非直接對數(shù)據(jù)源發(fā)出指令,而是通過OLE接口與數(shù)據(jù)源進(jìn)行交互,數(shù)據(jù)服務(wù)器從數(shù)據(jù)源取得所要查詢的數(shù)據(jù)時,以表格的形式將其提供給接口,再由客戶將數(shù)據(jù)從接口取出并使用。在這些操作中,客戶和數(shù)據(jù)服務(wù)器都不必知道對方的具體應(yīng)用,而只需要對接口進(jìn)行操作,從而簡化了程序設(shè)計。
8.1.3 OLE DB的優(yōu)越性
OLE DB是一種基于COM的全新數(shù)據(jù)庫開發(fā)技術(shù),它具有如下優(yōu)點:
廣泛的應(yīng)用領(lǐng)域
以往的數(shù)據(jù)庫訪問技術(shù),包括ODBC、DAO等,都只能訪問關(guān)系型數(shù)據(jù)庫,而OLE DB被設(shè)計成可以訪問任何格式的文件,其中當(dāng)然包括關(guān)系型和非關(guān)系型的數(shù)據(jù)源,以及用戶自定義的文件格式,用戶只需要對所使用的數(shù)據(jù)源產(chǎn)生自己的數(shù)據(jù)提供程序,OLE DB客戶程序就可以透明地訪問到它們。
簡潔的開發(fā)過程
OLE DB的對象組件和接口已經(jīng)定義了數(shù)據(jù)提供程序所需要的接口,Visual C++ 6.0也為此提供了OLE DB模板,可以很方便地產(chǎn)生一個OLE DB應(yīng)用程序框架。OLE DB為建立服務(wù)提供程序提供了一系列功能,這些功能可以大大簡化數(shù)據(jù)提供程序的設(shè)計。由于數(shù)據(jù)使用程序并不需要知道當(dāng)前數(shù)據(jù)提供程序的細(xì)節(jié),因此它只需要使用OLE DB的接口即可完成程序設(shè)計。由于接口的標(biāo)準(zhǔn)性,數(shù)據(jù)使用程序可以被用到任何提供了數(shù)據(jù)提供程序的數(shù)據(jù)源,使得OLE DB程序具有良好的移植性。
可靠的穩(wěn)定性
OLE DB應(yīng)用程序是基于COM接口的應(yīng)用程序,它繼承了COM接口的所有特性。COM模型具有良好的穩(wěn)定性,COM與COM之間只要遵循規(guī)定的接口,可以很容易地進(jìn)行通信,所有組件和接口共同工作,組成一個穩(wěn)定的應(yīng)用程序。OLE DB的各個對象都提供了錯誤對象和錯誤接口,可以由應(yīng)用程序截獲錯誤,對其進(jìn)行適當(dāng)處理,從而提高了應(yīng)用軟件的穩(wěn)定性。
高效的數(shù)據(jù)訪問
作為一個組件數(shù)據(jù)庫管理系統(tǒng),OLE DB通過將數(shù)據(jù)庫的功能劃分為客戶和服務(wù)器兩個方面,提供了比傳統(tǒng)數(shù)據(jù)庫更高的效率。由于數(shù)據(jù)使用者通常只需要數(shù)據(jù)庫管理的一部分功能,OLE DB將這些功能分離開來,減少了用戶方面的資源開銷,同時減少了服務(wù)器方面的負(fù)擔(dān)。
綜上所述,由于提供了靈活的接口和優(yōu)越的性能,OLE DB必定成為數(shù)據(jù)庫開發(fā)的方向。
8.1.4 OLE DB對象
OLE DB的每一個組件都是一個COM對象,每一個組件都輸出一系列的接口。OLE DB由下列組件組成:
枚舉器
枚舉器用于搜尋可用的數(shù)據(jù)源和其它的枚舉器。如果客戶沒有指定所使用的枚舉器,則可以使用枚舉器來尋找,一般通過搜尋注冊表來發(fā)現(xiàn)相應(yīng)的數(shù)據(jù)源。該對象包括如下接口:
CoType TEnumerator{
[mandatory] IParseDisplayName;
[mandatory] ISourceRowset;
[mandatory] IDBInitialize;
[mandatory] IDBProperties;
[mandatory] ISupportErrorInfo;
}
數(shù)據(jù)源對象
數(shù)據(jù)源對象包含與數(shù)據(jù)源(DBMS或者文件系統(tǒng))連接的方法,此對象中含有環(huán)境變量、連接信息、用戶信息、用戶口令等信息。使用數(shù)據(jù)源對象可以產(chǎn)生會話。該對象包括如下接口:
CoType TDataSource{
[mandatory] interface IDBCreateSession;
[mandatory] interface IDBInitialize;
[mandatory] interface IDBProperties;
[mandatory] interface IPersist;
[mandatory] interface IConnectionPointContainer;
[mandatory] interface IDBAsynchStatus;
[optional] interface IDBDataSourceAdmin;
[optional] interface IDBInfo;
[optional] interface IPersistFile;
[optional] interface ISupportErrorInfo;
}
會話
會話為事務(wù)處理提供了上下文環(huán)境,它可以被顯式或者隱式地執(zhí)行。一個數(shù)據(jù)源對象可以擁有多個會話,而通過會話又能夠生成事務(wù)、命令和行集。該對象的接口如下:
CoType TSession{
[mandatory] interface IGetDataSource
[mandatory] interface IOpenRowset
[mandatory] interface ISessionProperties;
[optional] interface IDBCreateCommand;
[optional] interface IDBSchemaRowset;
[optional] interface IIndexDefinition;
[optional] interface ITableDefinition;
[optional] interface ITransactionJion;
[optional] interface ITransactionLocal;
[optional] interface ITransaction;
[optional] interface ITransactionObject;
[optional] interface ISupportErrorInfo;
}
事務(wù)對象
事務(wù)對象用于管理數(shù)據(jù)庫的事務(wù),將多個操作合并為一個單一的事務(wù)處理。該對象緩存了對數(shù)據(jù)源的改變,使應(yīng)用程序有機(jī)會選擇提交或者回退以往的操作。事務(wù)能夠提高應(yīng)用訪問數(shù)據(jù)庫的性能,但是OLE DB數(shù)據(jù)服務(wù)器并不要求支持該對象。該對象包括如下接口:
CoType TTransaction{
[mandatory] interface IConnectionPointContainer;
[mandatory] interface ITransaction;
[optional] interface ISupportErrorInfo;
}
命令對象
命令對象用于對數(shù)據(jù)源發(fā)送文本命令。對于支持SQL的數(shù)據(jù)源,SQL命令同命令對象一起執(zhí)行,包括兩種數(shù)據(jù)定義語言和產(chǎn)生行集對象的查詢,對于其它不支持SQL的數(shù)據(jù)源,命令對象給數(shù)據(jù)源發(fā)送其它類型的文本命令。但是對于數(shù)據(jù)提供程序來說,不一定必須支持這個命令對象。一個單獨的會話能夠產(chǎn)生多個命令對象。該對象包括如下接口:
CoType TCommand{
[mandatory] interface IAccessor;
[mandatory] interface IColumnsInfo;
[mandatory] interface ICommand;
[mandatory] interface ICommandProperties;
[mandatory] interface ICommandText;
[mandatory] interface IConvertType;
[optional] interface IColumnsRowset;
[optional] interface ICommandPrepare;
[optional] interface ICommandWithParameters;
[optional] interface ISupportErrorInfo;
}
行集
行集以表的形式顯示數(shù)據(jù),其中索引就是一種特殊的行集。行集可以從會話或者命令對象產(chǎn)生。如果數(shù)據(jù)提供程序不支持命令對象,則行集可以由數(shù)據(jù)提供程序直接產(chǎn)生,直接產(chǎn)生行集是每一個數(shù)據(jù)提供程序的基本功能。根據(jù)數(shù)據(jù)提供程序所提供的功能,行集對象可以完成更新、插入、刪除等操作。該對象包括如下接口:
CoType TRowset{
[mandatory] interface IAccessor;
[mandatory] interface IColumnsInfo;
[mandatory] interface IConvertType;
[mandatory] interface IRowset;
[mandatory] interface IRowsetInfo;
[mandatory] interface IChapteredRowset;
[optional] interface IColumnsRowset;
[optional] interface IConnectionPointContainer;
[optional] interface IDBAsynchStatus;
[optional] interface IRowsetChange;
[optional] interface IRowsetFind;
[optional] interface IRowsetIdentity;
[optional] interface IRowsetIndex;
[optional] interface IRowsetLocate;
[optional] interface IRowsetRefresh;
[optional] interface IRowsetScroll;
[optional] interface IRowsetUpdate;
[optional] interface IRowsetView;
[optional] interface ISupportErrorInfo;
}
錯誤對象
錯誤對象中封裝了訪問數(shù)據(jù)提供程序時發(fā)生的錯誤,它可以由任何OLE DB對象的任何接口產(chǎn)生。錯誤對象中含有關(guān)于錯誤的附加信息,包括一個可選的定制錯誤對象,通過它也能夠獲得擴(kuò)展的返回碼和狀態(tài)信息。該對象包括如下接口:
CoType TError{
[mandatory] interface IErrorRecords;
}
如果用戶不能確定數(shù)據(jù)源的位置,可以先使用枚舉器尋找數(shù)據(jù)源,在找到數(shù)據(jù)源以后,就可以使用它來生成一個會話,這個會話允許用戶對數(shù)據(jù)進(jìn)行訪問,或者以行集的形式,或者以命令的形式。
圖8-1展示了OLE DB應(yīng)用程序的對象流程。
圖8-1 OLE DB應(yīng)用程序?qū)ο罅鞒?/span>
圖8-2 OLE DB的客戶模板體系結(jié)構(gòu)
8.1.5 OLE DB客戶模板結(jié)構(gòu)
OLE DB客戶模板支持OLE DB1.1版本的標(biāo)準(zhǔn),它使實現(xiàn)一個0級OLE DB代碼質(zhì)量、客戶所需要標(biāo)寫的代碼量達(dá)到最少。該模板具有如下優(yōu)點:
易于使用OLE DB所提供的功能。
易于與ATL和MFC集成。
提供了數(shù)據(jù)參數(shù)綁定和列綁定的簡單模型。
在編程時能夠使用C/C++數(shù)據(jù)類型。
OLE DB的客戶模板體系結(jié)構(gòu)如圖8-2所示。
由圖可以看出,OLE DB的客戶模板體系結(jié)構(gòu)由數(shù)據(jù)源支持類、用戶記錄類、行集和綁定類以及表和命令支持類4部分構(gòu)成。
8.1.6 OLE DB客戶模板類
為了能更好的使用OLE DB客戶模板進(jìn)行應(yīng)用程序設(shè)計,首先必須熟悉OLE DB的客戶模板類。根據(jù)功能,OLE DB的客戶模板類分成7種:會話類、存取器類、行集類、命令類、屬性類、書簽類以及錯誤類。
會話類
會話類包括CDataSource類、CEnmmerator類、CSession類和CEnmmeratorAccessor類。
1. CDataSource類
CDataSource類對應(yīng)于OLE DB的數(shù)據(jù)源對象,代表服務(wù)器與數(shù)據(jù)源的連接。在單個連接上可以擁有多個數(shù)據(jù)庫會話,其中的每一個會話都由CSession對象表示。調(diào)用CDataSource類的Open方法可以建立同數(shù)據(jù)源的連接。
2. CEnmmerator類
CEnmmerator類對應(yīng)于OLE DB的枚舉器對象,能夠檢索可用的數(shù)據(jù)源和枚舉器信息。CEnmmerator通過ISourcesRowset接口來獲得包含所有數(shù)據(jù)源和枚舉器描述的行集,用戶可以直接通過該類得到ISourcesRowset數(shù)據(jù)。
3. CSession類
CSession類對應(yīng)于OLE DB的會話對象,代表單個數(shù)據(jù)庫訪問會話。要從CDataSource對象創(chuàng)建一個新的CSession對象,需要首先調(diào)用CDataSource對象的Open方法建立同數(shù)據(jù)源的連接,創(chuàng)建CSession對象的方法也是調(diào)用CSession對象的Open方法。該類還提供了事務(wù)處理函數(shù),用戶調(diào)用StartTransaction函數(shù)開始一個事務(wù)處理操作,調(diào)用Commit或者Abort函數(shù)提交或者回退這個事務(wù)處理。
4. CEnmmeratorAccessor類
CEnmmeratorAccessor類被CEnmmerator類用來訪問來自枚舉器行集的數(shù)據(jù),這個行既包括從當(dāng)前枚舉器中可見的數(shù)據(jù)源和枚舉器。
存取器類
存取器類包括CAccessorBase類、CAccessor類、CDynamicAccessor類、CDynamicParameterAccessor類和CManualAccessor類。
1. CAccessorBase類
CAccessorBase類是所有存取器類的基類,所有存取器的OLE DB模板都是從該類中派生出來的。CAccessorBase類允許一個行集管理多個存取器,它還提供了對參數(shù)和輸出的綁定。
2. CAccessor類
CAccessor類用于靜態(tài)綁定到數(shù)據(jù)源的記錄,使用該存取器類時,必須事先知道數(shù)據(jù)源的結(jié)構(gòu)。當(dāng)一個記錄被靜態(tài)綁定到數(shù)據(jù)源時,該記錄包含一個緩沖區(qū)。該類支持單個行集上的多個存取器。當(dāng)知道數(shù)據(jù)源的結(jié)構(gòu)時可以使用該存取器。
3. CDynamicAccessor類
CDynamicAccessor類所代表的存取器可以在運行時被創(chuàng)建,它基于行集的列信息。當(dāng)不知道數(shù)據(jù)源的結(jié)構(gòu)時,可以使用CDynamicAccessor類檢索數(shù)據(jù)。該類將創(chuàng)建并管理緩沖區(qū),使用GetValue方法從緩沖區(qū)里讀取數(shù)據(jù)。
4. CDynamicParameterAccessor類
在不知道命令類型時,可以使用CDynamicParameterAccessor類進(jìn)行數(shù)據(jù)存取。如果服務(wù)器支持ICommandWithParameters接口,則該類就通過調(diào)用這個接口讀取參數(shù)信息。該類與CDynamicAccessor類類似,但是它所獲得的是參數(shù)信息。該類也能夠創(chuàng)建并管理緩沖區(qū),通過調(diào)用GetParam和GetParamType方法可以從緩沖區(qū)里讀取列的信息。
5. CManualAccessor類
CManualAccessor類具有同時處理列和命令的能力,利用這個類,能夠使用服務(wù)器可轉(zhuǎn)換的數(shù)據(jù)類型。該類代表了為將來設(shè)計而使用的存取器類型,使用該類能夠通過運行時函數(shù)調(diào)用指定參數(shù)和輸出列。
行集類
行集類包括CRowset類、CBulkRowset類、CAccessorRowset類、CArrayRowset類和CRestrictions類。
1. CRowset類
CRowset類用于處理、建立和檢索行數(shù)據(jù)。在OLE DB中,行集為應(yīng)用程序操作數(shù)據(jù)所用的對象。CRowset類封裝了OLE DB行集對象和一些相關(guān)的接口,并為操作行集數(shù)據(jù)提供了成員函數(shù)。
2. CBulkRowset類
CBulkRowset類用于批量讀取和處理行,通過單個函數(shù)調(diào)用可檢索多個行句柄。
3. CAccessorRowset類
CAccessorRowset類封裝一個行集和相關(guān)的存取器。
4. CArrayRowset類
CArrayRowset類用于以數(shù)組形式訪問行集中的元素。
5. CRestrictions類
CRestrictions類用于為綱要行集指定限制條件。
命令類
命令類包括:CCommand類、CTable類、CMultipleResults類、CNoMultipleResults類、CNoAccessor類和CNoRowset類。
1. CCommand類
CCommand類用于設(shè)置和執(zhí)行一個基于參數(shù)的OLE DB命令,如果只需要打開一個簡單的行集,則應(yīng)該使用CTable類。
2. CTable類
CTable類用于訪問一個不帶參數(shù)的簡單行集。
3. CMultipleResults類
CMultipleResults類用于將CCommand類的TMultiple參數(shù)設(shè)置為TRUE。
4. CNoMultipleResults類
CMultipleResults類用于將CCommand類的TMultiple參數(shù)設(shè)置為FALSE。
5. CNoAccessor類
CNoAccessor類用于將CCommand類的TAccessor參數(shù)設(shè)置為FALSE。
6. CNoRowset類
CNoAccessor類用于將CCommand類的TRowset參數(shù)設(shè)置為FALSE。
屬性類
屬性類包括:CDBPropIDSet類和CDBPropSet類。
1. CDBPropIDSet類
CDBPropIDSet類用于傳遞一個包含客戶請求的屬性信息的屬性ID數(shù)組。
OLE DB客戶用DBPROPIDSET結(jié)構(gòu)來傳遞一組客戶要得到的屬性信息的屬性標(biāo)識。在DBPROPIDSET結(jié)構(gòu)中被標(biāo)識的屬性屬于一個屬性集合。CDBPropIDSet類繼承了DBPROPIDSET結(jié)構(gòu)并添加了一個構(gòu)造函數(shù),用于初始化關(guān)鍵字段和AddPropertyID方法。
2. CDBPropSet類
CDBPropSet類用于設(shè)置服務(wù)器屬性。
OLE DB服務(wù)器和客戶用DBPROPSET結(jié)構(gòu)來傳遞DBPROP結(jié)構(gòu)數(shù)組。每一個DBPROP結(jié)構(gòu)代表了可以被設(shè)置的單個屬性。CDBPropSet類繼承了DBPROP結(jié)構(gòu)并添加了一個構(gòu)造函數(shù),用于初始化關(guān)鍵字段數(shù)據(jù)成員和AddProperty方法。
書簽類
OLE DB里客戶模板的書簽類是指CBookMark類,它被用于以索引的形式在行集中訪問數(shù)據(jù)。
錯誤類
OLE DB里客戶模板的錯誤類是指CDBErrorInfo類,它用于檢索OLE DB的出錯信息。這個類提供了使用OLE DB的IErrorRecords接口進(jìn)行OLE DB出錯處理的支持。這個接口向用戶返回一個或者多個錯誤記錄。調(diào)用GetErrorRecords方法可以得到一個出錯記錄數(shù),然后調(diào)用GetAllErrorInfo方法檢索每一條出錯記錄的信息。