關於 OLE DB 和 .NET

軟件的進化

從歷史的角度看,ODBC 是人們爲使應用程序使用統一的方式訪問數據庫所作的第一次認真嘗試。正如軟件中的其他部分一樣,ODBC 旨在滿足特定的要求。它在信息技術永不停止的進化過程中,確立了一個新的發展階段。 ODBC 必須提供通用的(並希望是抽象的)API 來訪問數據庫,而不考慮其內部細節、語言和表組織結構。隨着時間的推移,不斷湧現出新的設計和生成數據驅動的應用程序的方法,ODBC 則越來越不適應形勢的發展。 因爲軟件也不例外地要經過進化過程,所以,ODBC 經過改編,使用了不同的名稱、不同的編程模型和全新的熱門功能才得以繼續存在,但它也保留了其自己的特性。ODBC 以 OLE DB 的名稱和功能繼續或多或少地提供開放式數據庫連接。 OLE DB 是將 Microsoft 通用數據訪問 (UDA) 策略的理論概念付諸實施的編程接口。UDA 通過一個基於 COM 的編程接口,提供訪問任何類型(關係型、非關係型和層次結構型)數據的功能。 OLE DB 是作爲一種組件技術而設計的,其特色是使用多層模型。一方面,它具有用於保存數據的服務器組件。另一方面,從 COM 橋樑的角度看,也具有知道如何連接和請求數據的客戶端組件。前者稱爲 OLE DB 數據提供程序;而後者則稱爲 OLE DB 使用者。 使用者和提供程序都是 COM 對象,它們之間通過一組 COM 接口進行通信。可以按照對抽象對象(例如,數據源會話命令行集合)所執行的操作,對此類基於 COM 的通信進行歸類。因此,實際情況是,使用者連接到某個數據源,打開一個會話,發出一個命令,並提取數據的行集合。 ODBC 的進化過程導致 UDA 和 OLE DB 提高了將所有企業數據融合在一起的能力,幾乎就像是一個關係表一樣,而不考慮其關係型、非關係型,甚至是層次結構型的特性。

OLE DB 模型

當談到數據訪問時,您有兩個基本選擇。一個是統一數據訪問策略,正如 UDA 允許您做的一樣。另一個是統一數據結構。它迫使您將您可能擁有的每一位信息從其當前的數據存儲設備移到單個綜合數據庫服務器。 通過使用 OLE DB,您可以試圖將客戶端目前需要的所有內容融合在一起。如果換另一個方法,您可以強制客戶端升級到更強大的、唯一的新 DBMS,DBMS 有能力處理您所需的任何格式的信息。 與 ODBC 相比,OLE DB 與數據的物理結構的相關性要小得多。此外,它並不是嚴格基於 SQL。OLE DB 命令可以是 SQL 語句,但也可以是其他內容。通常,可以將它們看作是按照目標提供程序可以理解的任何語法編寫的文本字符串。 與 ODBC 類似,在設計 OLE DB 時充分考慮了 C++,以便最大程度地提高中間層模塊中數據訪問的性能。由於這些相同的原因,在 Visual Basic 或 ASP 中不能直接使用 OLE DB。 而無數的分佈式系統應該使用 Visual Basic 來生成組件。這就是爲什麼 Microsoft 推出了 ActiveX 數據對象 (ADO) 庫的主要原因。 與原始 OLE DB SDK 相比,ADO 具有更加豐富的編程接口。毋庸置疑,可以在 C++ 應用程序中使用 ADO,儘管如此,但與相應的 ADO 代碼相比,OLE DB 調用經過較少的代碼層,並且可以更直接地獲取數據。 雖然 ADO 明確建立在 OLE DB 之上,但對原始 OLE DB 接口的調用和通過 ADO 運行庫發出的調用具有不同的相對速度。這一事實引發了一種基於語言的分化。哪個更好,更建議使用哪一個呢?是選擇 OLE DB 的 C++ 高性能級別,還是選擇 Visual Basic 組件中更方便、更寬鬆的 ADO 模型? 除提供程序和使用者以外,OLE DB 模型還包含第三個元素,即 OLE DB 服務。服務是一個 COM 組件,用於處理使用者返回的行集合。其工作方式就如同一種掛鉤一樣,用於監視使用者和提供程序之間的所有通信。ADO 主要依靠 OLE DB 服務來添加其擴展功能,例如,數據成形、持久性和斷開連接的記錄集。 隨着人們越來越重視生成基於 COM 的分佈式應用程序,很多針對特定領域的最佳做法已經制訂出來了。爲了提高 Web 應用程序的可伸縮性,人們轉而使用數據訪問斷開連接模型。 在 nutshell 中,數據使用者和數據提供程序之間並不始終保持連接。在建立連接後,您發出給定查詢,從內存中的庫中提取記錄,並斷開與數據源的連接。您以脫機方式處理這些記錄,如果需要的話,隨後再重新連接並提交您的更改。此模型並不適用於所有人。但在其適用的場合中,它在提高可伸縮性和總體性能方面具有非常高的價值。 很多系統已經通過客戶端遊標服務進行(重新)轉換以使用 ADO 記錄集,此服務支持數據斷開連接。人們並沒有明確將 OLE DB 視爲此類交互模型,因此,通過中間 OLE DB 服務來擴展 ADO。 OLE DB 的結構具有內在的靈活性,因此,在斷開連接的情況下可以成功地使用 OLE DB,但這顯然並不代表最佳的工作方式。這種實現方式的另一個微妙的限制是,很多工作都是依賴 ADO 記錄集來完成的,因而,人們不免會懷疑它們並不總能有效地完成工作。如何才能使此類對象在連接和斷開連接的情況下、有和沒有 XML 的情況下以及進行構造或從磁盤加載的情況下工作時都能具有最快的速度呢? 此外,如果您考慮到 ADO 功能集與原始 OLE DB SDK 具有非常大的差異,那麼,您就會知道它與 OLE DB 具有很大的不一致性。 因此,ADO.NET 成爲數據訪問技術進化過程的下一個階段。從名稱上看,ADO.NET 似乎只是 ADO 的後續版本。OLE DB 在 .NET 中又是什麼情況呢?

.NET 託管提供程序

按照達爾文進化論的永恆法則來看,現在 OLE DB 技術必須向前邁進一步以滿足新用戶的需求。在 .NET 中,Web 應用程序主要是斷開連接的應用程序,該應用程序使用新設計的特別工具來管理數據。 .NET 框架提供了處理數據的類。這些類(特別是 ADO.NET 和 XML 命名空間)提供了收集、讀取和寫入功能。ADO.NET 和 XML 子系統最終取代了 ADO 和 OLE DB SDK,因此,現在使用一種與語言無關的方法來獲取或設置數據。 ADO.NET 類在提取數據源方面甚至比 ADO 做得更好,這是因爲它具有以數據爲中心的明確設計,與此相反,ADO 卻仍然使用以數據庫爲中心的模型。 OLE DB 提供程序的 .NET 副本稱爲託管提供程序。下面的圖中說明了它們的角色。

圖 1. 託管提供程序的結構示意圖

正如在 OLE DB 中一樣,您可以識別兩種交互的層,爲了保持諧音,我將它們稱爲託管使用者層和託管提供程序層。要處理數據,.NET 應用程序不需要挑出特殊的類或組件來作爲使用者模塊。 .NET 應用程序只使用原始框架中的 DataSetDataReader 對象,並立即成爲“託管”數據使用者。要物理地提取數據,您應該使用從 DataSetCommandDBCommand 繼承的特殊類的實例。這些類表示到數據源的鏈接。 無需指示更常規的對象來處理給定提供程序,您只需使用已知道如何處理該給定提供程序的派生類即可。因此,實際情況是,SQLDataSetCommand 處理 SQL Server 數據庫,而 ADODataSetCommand 包裝所有現有的 OLE DB 提供程序。 託管提供程序就隱藏在這些 DataSetCommand 類當中。您不會意識到它們的存在,並且從不需要明確知道它們。您使用類並設置屬性,然後就萬事大吉了。 從內部來看,上圖中的託管提供程序層使用的交互模型與 OLE DB(甚至更早的 ODBC)中的交互模型並沒有多大差異。使用者命令類針對的是包裝數據源的特定組件。它知道發出的用於讀取和寫入源上的行的協議。它還以 .NET 類完全知道如何處理的格式返回結果。 爲了便於理解,讓我們看一些在 OLE DB 和 .NET 中檢索數據時都會用到的元素。

 

OLE DB 提供程序

.NET 託管提供程序

標識

COM progID

包裝在命令類中

獲得結果的方式

通過行集合或 ADO 記錄集

通過 DataSet 或 DataReader 類

更新方式

通過提供程序特定的命令

通過提供程序特定的命令

傳輸格式

二進制文件

XML

表 1. 比較 OLE DB 和 .NET 數據提供程序

在 OLE DB 中,目標提供程序是通過其 COM progID 標識的。而在 .NET 中,此類細節隱藏在訪問器類中。 OLE DB 提供程序始終返回行集合;COM 對象主要公開 IRowset 接口。如果通過 ADO 訪問數據,則將行集合轉換爲更豐富且可編寫腳本的對象(稱爲“記錄集”)。 .NET 應用程序對不同的功能使用不同的類。DataReader 類是一種簡單、快速的只進遊標,它在連接方式下工作並針對每條記錄提供訪問。在完成此過程後,必須顯式斷開連接。相比之下,DataSet 對象是一個內存中的斷開連接的表集合。其填充的內容源於 DataSetCommand 類。DataSet 對象的內容基於 DataSetCommand 類從數據源返回的 XML 流。 我將在後面幾期中討論 DataReaderDataSet 類。 數據以二進制格式從提供程序傳輸到使用者,如果您使用 OLE DB 的話,還要通過 COM 封送處理方可傳輸。而在 .NET 中,託管提供程序返回 XML 流。 這兩種提供程序均支持查詢語言,通常爲帶有供應商特定的專用擴展的 SQL。通過這種語言,您可以執行更新並詢問數據源。 那麼,OLE DB 和 .NET 數據提供程序有什麼差異呢?抽象地說,它們使用相同版本的數據訪問。但託管提供程序要簡單和專用得多。它們可提供更好的性能,原因主要有以下兩個:首先,託管提供程序並不使用 COM Interop 橋樑來獲取和設置數據。而在這一點上,作爲 COM 組件,OLE DB 提供程序則別無他選。再者,託管提供程序通常利用供應商對數據源內部情況的瞭解,以快得多的速度獲取和設置行。這也正是 OLE DB 提供程序所具有的功能;但在 .NET 中使用時,OLE DB 提供程序也爲其基於 COM 的特性付出了相應的代價,它們需要編寫額外的代碼來將數據轉換爲 .NET 特定的類。

現有的託管提供程序

從 Beta 1 起,.NET 框架提供兩個託管提供程序:一個用於 SQL Server(版本 7.0 和更高版本),一個用於您能通過 OLE DB 提供程序訪問的所有數據源。 SQL Server 託管提供程序隱藏在特定的類中,例如,SQLDataReaderSQLDataSetCommandSQLCommand。這些類利用直接訪問來訪問低級 SQL Server 文件系統。下圖給出了提供程序的類示意圖,它將以前的常規架構映射到 SQL Server 的託管提供程序。

圖 2. SQL Server 託管提供程序的類示意圖

OLE DB 託管提供程序在 .NET 中的作用與 ODBC 的 OLE DB 提供程序在 Windows DNA 系統中的作用相同。基本上,它代表了向後兼容性,並生動地說明了任何 .NET 應用程序都可以處理 OLE DB 支持的任何現有數據源。OLE DB 託管提供程序的類示意圖如下所示。

圖 3. OLE DB 託管提供程序的類示意圖

注意,在 Beta 2 中,應該將 ADOxxx 類重命名爲 OleDbxxx。 OLE DB 託管提供程序向調用者公開 .NET 類,但利用指定的 OLE DB 提供程序來獲取行。.NET 應用程序和基礎 OLE DB 提供程序(COM 對象)之間的通信是通過 COM Interop 橋樑進行的。 通常,在 .NET 中,您可以通過這兩種提供程序訪問 SQL Server 7.0(和更高版本)表。SQL Server 託管提供程序直接訪問 DBMS 文件系統以請求數據。而 OLE DB 託管提供程序依靠 SQL OLE DB 提供程序的服務,因此需要穿過一個額外的代碼層。 目前,如果您的任何目標數據源不是 SQL Server,則 OLE DB 託管提供程序是您必須使用的唯一方法。通過此相同的通道,您還可以訪問任何 ODBC 數據源。 OLE DB 託管提供程序是建立在 COM Interop 橋樑上的瘦包裝類,它調用本機 OLE DB 提供程序。除設置和終止調用以外,此類模塊還負責將返回的行集合包裝到 DataSetADODataReader 對象中,以使 .NET 能夠進行進一步的處理。 在 .NET 代碼級別,通過本機託管提供程序或 OLE DB 提供程序訪問 SQL Server 表實質上就是更改相關類的前綴。以下是 SQL Server 代碼:

Dim strConn, strCmd As String strConn = "DATABASE=Northwind;SERVER=localhost;UID=sa;PWD=;" strCmd = "SELECT * FROM Employees" Dim oCMD As New SQLDataSetCommand(strCmd, strConn) Dim oDS As New DataSet oCMD.FillDataSet(oDS, "EmployeesList")

以下是 OLE DB 提供程序代碼(不同之處以粗體表示):

Dim strConn, strCmd As String strConn = "Provider=SQLOLEDB;" strConn += "DATABASE=Northwind;SERVER=localhost;UID=sa;PWD=;" strCmd = "SELECT * FROM Employees" Dim oCMD As New ADODataSetCommand(strCmd, strConn) Dim oDS As New DataSet oCMD.FillDataSet(oDS, "EmployeesList")

正如您所看到的一樣,表面上看差別非常小;只是連接字符串和命令類而已。但使用一個類或另一個類會產生非常大的差異。

有關 OLE DB 的存在主義問題

.NET 託管提供程序代表了數據訪問技術進化過程的下一階段,但從 Beta 1 起,不再有用於編寫數據源特定的託管提供程序的記錄 SDK。等到發行 Beta 2 時,仍無法迴避有關 OLE DB 和 .NET 的一些基本問題。 爲 OLE DB 開發的所有代碼都是遺留代碼嗎?公司在爲其自己的數據編寫提供程序所做的(並且通常正在做的)所有工作會帶來什麼回報? 請相信,OLE DB 並不是一種淘汰的技術。它仍然是功能豐富的、通用的、與 .NET 無關的編程接口的基本規範。它並不是 .NET 所特有的,但它於 .NET 上得到了很好的支持。 也就是說,如果您要公開自定義數據,則不能忽視 .NET 和託管提供程序的出現。那麼,您的數據提供程序應配備的最佳接口是什麼呢?您打算如何立即(例如,從下星期一早晨 8 點開始)公開您的數據呢? .NET 利用開放的標準,並在很大程度上基於 XML。考慮到這一點,如果您要公開基於文本的專用數據,只需考慮使用 XML 發佈它即可(可能使用自定義架構)。.NET 中有很多用於處理 XML 數據的工具,所以提供一個包裝類根本不成問題。 對於更復雜的數據存儲,OLE DB 提供程序仍然有效,因爲您需要面向更大的用戶羣,他們可能並不侷限於 .NET。對於 .NET 特定的應用程序,託管提供程序的確可以提供非常大的性能優勢,但在這種情況下我會非常謹慎的,尤其是在星期一。不要忘了,目前尚未發佈託管提供程序的 SDK,但 Microsoft 承諾提供託管提供程序 SDK。 因此,總而言之,我應該在本星期一早晨開始編寫的下一個數據提供程序將包含一對 OLE DB 提供程序以及一個用 XML 編寫的 .NET 包裝類。我的第一個選擇並不是通過 COM Interop 將 .NET 類包裝在 OLE DB 提供程序的外圍。我傾向於使用相同的源代碼(已進行了一定的改編)。在這種情況下,使用託管 C++ 語言可能是便於重複使用“物理”代碼的最好方法。

OLE DB 的歸宿

從現在起,一些年後我這裏所做的預測將會得到印證。從長遠看,我大膽地預測 OLE DB 將與 SGML 的結局類似(OLE DB 相對更加悽慘),SGML(標準通用標記語言)是 XML 的前身。 SGML 的出現是爲了解決數據交換問題,但其卻從未成爲實際的標準,這可能是因爲它功能太強,太複雜,而不便於日常使用。實際情況是,它的創造性原則只有在正確地進行範圍縮小以及專門化以產生 XML 後,已被廣泛地採用了。 我的預測是,在 .NET 站穩腳跟後,OLE DB 的重要性就會逐漸降低,直至消失。不知道這一過程實際要持續多長時間,但我相信它必定要經歷這一消亡過程。 不久後,我將給出引用的材料。請繼續關注我們的工作。

對話欄:的確,我現在感覺被遺棄了

您可能生活在另一個時空!您怎能將現有的 ADO 代碼(多數情況下是在六個月前後編寫的)定義爲遺留代碼呢?.NET 尚未到達其 beta 計劃的第二階段,您又怎能借技術/平臺 .NET 的名義進行定義呢?

要是不稍稍誇張一點,生活豈非平淡無奇?不管怎樣說,您說得非常對。 我們真的可以將最近在很多 DNA 系統中發現的所有 ADO 代碼化石定義爲遺留代碼嗎?我的回答仍然是“是的,我們應該這樣做”。但我知道它聽起來確實讓人感到泄氣。 我認爲“遺留代碼”就是與宿主平臺核心不再保持一致的代碼。相信我,這就是 .NET 中即將出現的情況。當然,一定會有辦法在 .NET 中集成現有代碼、組件和應用程序。 .NET 並非徹底性的變革,在今後幾年中,它將吸收 Windows 中軟件的任何有機成分。抗拒這種趨勢是徒勞的,您必將順應這種潮流。無論代碼的年齡有多長,按照我對遺留代碼的定義,真正重要的是源和運行庫之間的一致性。 .NET 改變了 Windows 運行庫,使之成爲託管運行庫。雖然 COM 和 Windows SDK 沒有被淘汰,但您必須按照另一種模型來編寫代碼。不管這種新運行庫的基礎是什麼,您必須遵循一種特殊的新模型。而此模型將是未來的 Windows 模型。 Windows 並沒有被淘汰,但它將會發生變化。COM 並沒有被淘汰,但它必須採用 .NET 類的形式。ADO 並沒有被淘汰,它仍然有效,但 ADO.NET 的 .NET 功能纔是 ADO 的未來。 .NET 並不只是 Windows 6.0,ADO.NET 也不是人們可能稱爲 ADO 3.0 的產品的別緻的新名稱。它是完全不同的,並且涉及到產品的方方面面。它是一個新平臺。爲方便起見,它或者是另一個平臺,或者是遺留代碼(集成後)。 遺留代碼沒有年齡限制。我知道人們在本週、六個月後甚至在 .NET 實際發行後,仍會在編寫 DNA 系統。我並不是說這樣做一定是錯誤的,或者應該絕對避免。我只是想讓您知道您是在逆流而上。


 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章