企業領域中的開發工作正日益變為更加利用 Internet 的功能和互操作性。重點已經從開發傳統的客戶端/服務器應用程序(需要嚴格定義用於交換數據的數據結構和協議)轉向了開發使用 XML 的 Web 應用程序。與傳統的客戶端/服務器應用程序一樣,Web 應用程序也通過 LAN 或 WAN 在不同的邏輯實體之間交換數據。但是,Web 應用程序使用公共 Internet 和 XML,而不使用專用連接和二進制數據格式。在需要訪問和更新存儲在關系數據庫(如 SQLServer)中的數據方面,大多數 Web 應用程序也和客戶端/服務器應用程序相似。Web 應用程序必須從 SQL Server 獲取 XML 查詢結果,並使用 XML 格式的數據更新 SQL Server。Microsoft 已經通過在 SQL Server 2000、XML for SQL Server 2000 (SQLXML) 和 .Net 框架中實現許多技術滿足了這些要求。(有關這些技術的概述,請參閱 2002 年 4 月的“Selecting XML Technologies for QuerIEs and Updates”,InstantDoc ID 24342。)這些技術為構建各種 Web 應用程序提供了堅實的基礎。但是,經過證明,處理數據庫更新總是比較困難。
Microsoft 提供了幾個用來更新數據庫的選項,包括 OpenXML、XML Bulk Load、updategram 和 Diffgram。我們已經在以前的專欄中研究了 OpenXML 和 XML Bulk Load;現在,該介紹 updategram 和 Diffgram 了。用來快速構建實際 Web 應用程序方案的每種技術都有很大的缺陷。在這些應用程序方案中,數據從某個 Web 應用程序進行請求、在客戶端位置進行遠程修改,隨後返回到該 Web 應用程序,以便所做的修改可以存儲在數據庫中。在這些方案中,對於 Web 應用程序有三個隱含要求。第一個是對開放式更新的需求。由於客戶端和服務器之間的 Internet 連接是異步的、短暫的並且有可能是不可靠的,因此 Web 應用程序需要進行開放式更新。如果沒有開放式更新,則由於在超時之前仍有許多鎖,應用程序和數據庫性能會迅速降低。第二個要求是,客戶端不需要(而且不應當預知)數據庫結構。第三個要求是,客戶端需要一種方法來傳送對數據進行的更改(包括並發信息),以便克服多個客戶端對服務器進行的競爭更新。Updategram 和 Diffgram 是相似的技術,它們都在不同程度上支持這三個要求。因此,假設您正在構建 Web 應用程序,那麼應當使用哪種技術?
Updategram
updategram 是一種 XML 文檔,它描述對 XML 查詢結果進行的更改。結合使用 updategram 和任何 SQLXML Web 版本,可以對數據庫進行開放式更新。Updategram 還支持更新數據庫中與 XML 中的分層關系相對應的一個或多個表。例如,可以將嵌套在 XML 定單元素中的定單項插入到數據庫的 Order 和 LineItem 表中。盡管 updategram 會嘗試滿足更新數據的三個要求,但是它們在以下幾個方面存在缺陷。
首先,ADO、SQL Server、SQLXML 或對象模型(如 XML 文檔對象模型 (DOM))不支持 updategram。這種缺陷會從三個方面降低 updategram 的有用性。第一,因為 ADO 和 DOM 不支持生成 updategram,所以您必須實現一個直接生成 updategram 語法的客戶端代碼。更糟糕的是,這項艱巨的任務不能在項目之間進行縮放;每當您希望生成一個 updategram 時,都必須實現該邏輯。第二,在將數據存儲到數據庫中之前,Web 應用程序通常需要使用業務邏輯來檢驗和驗證數據。同樣,您需要用一個對象模型來表達該業務邏輯(因為該技術使用開放式更新),以便確認在從數據庫檢索數據之後和嘗試更新數據之前之間的這段時間內,數據未發生變化。第三,對象模型在理想情況下可使您能夠以一種一致的方式來訪問更新的數據和原始值。但是,您也需要實現一個代碼,該代碼除了執行業務邏輯和並發檢查,還要解釋 updategram 語法。
Updategram 還有一個缺陷,就是無法調用存儲過程來執行數據庫更新。因此,通過使用存儲過程而實現的業務邏輯、約束和引用完整性都呈現為無用狀態。
updategram 用來表達數據集更改的方式可能會造成另一個問題。這些更改是用 XML 而不是關系數據庫表達的。盡管用這種方式表達所做的更改通常大有裨益(這是因為它向客戶端隱藏了數據庫的詳細信息),但是它還可能排除某些數據,而在將所做的更改提交到數據庫中之前,您可能需要這些數據來驗證所做的更改或執行業務邏輯。
最後,updategram 通常的應用方式也存在缺陷。因為 updategram 最適於進行批處理,所以,如果 SQL Server 能夠按照它處理 T-SQL UPDATE 語句的方式來處理 updategram 的話,updategram 則會生成最高效的結果。但是,當前的 SQLXML 實現在中間層處理 updategram,並生成由 SQL Server 執行的 SQL 語句,而不是直接處理 updategram。因此,盡管 updategram 從表面看非常適合在 Web 應用程序中更新數據,並且有可能適合一組范圍較窄的情形,但是,其缺點限制了對它們的廣泛應用。
Diffgram
Diffgram 是隨 ADO.NET 支持一起引入 .NET框架中的。Diffgram 與 updategram 相似,但是能夠解決 updategram 中一些固有的最嚴重的問題。最重要的是,Diffgram 通過 ADO.NET DataSet 對象提供對象模型支持。您可以通過持久性保持一個 Diffgram 格式的 DataSet,來直接從該 DataSet 定義中生成 Diffgram,也可以從持久性 Diffgram 中創建 DataSet。因此,當您構建業務邏輯時,不必編寫用來生成 Diffgram 或導航 Diffgram 結構的代碼。相反,您只需使用 DataSet 對象來編寫代碼。您還可以結合使用 DataSet 對象和 DataAdapter 對象,將以 Diffgram 表達的更改提交到數據庫中。(DataAdapter 是 ADO.Net 中的一個中間對象,它從數據庫中讀取數據並將所做的更改更新到數據庫。)另外,DataAdapter 支持通過存儲過程來進行更新,而且會在對數據進行了並發更新之後,引發一個程序事件。盡管對於程序員來說,Diffgram 比 updategram 方便得多,但是使用 Diffgram 也有一些注意事項。
首先,您需要讓 .NET 框架充分利用 Diffgram。.NET 框架和公共語言運行庫 (CLR) 尚未完全部署,因此 Web 客戶端可能還無法訪問 DataSet 的豐富功能,或者可能無法在中間層服務器上使用 .Net 框架。第二,Diffgram 不支持對使用標識列的表進行更新。如果數據庫架構使用標識列來自動為某些實體生成唯一的 ID,這些實體隨後又用於其他表中的外鍵,Diffgram 則無法處理更新。例如,當定單及其行項目存儲在單獨的表中,而且使用一個標識列(例如,定單號)做為 LineItems 表中引用其相關定單的外鍵時,Diffgrams 則無法成功地將行項目添加到數據庫中。唯一的解決辦法是親自編寫更新代碼,以便取消 Diffgram 的值。更大的障礙是,當不同的復雜類型(在 XML 架構定義 - XSD 中進行定義)使用相同的名稱但是位於不同的上下文中時,Diffgram 無法使用 XML。例如,一般會使用名稱“Vendor”來引用 ServiceProvider 類型和 ProductReseller 類型,這兩種類型具有不同的結構。如果客戶端使用不同的架構(或根本不使用架構)來構建數據集,則在解釋 Diffgram 時也可能遇到問題。因為 Diffgram 是對 DataSet 內容進行序列化的過程,所以您收到的 Diffgram 可能與您的數據庫或您知道的任何架構都不匹配,因此,更新數據庫就變得很難,甚至不可能。
如果 .Net 框架不可用,則 Web 客戶端應用程序通常必須生成一個 Diffgram,方法是編寫用來構造 Diffgram 格式的代碼。但是,在中間層,可以使用替代處理方法。SQLXML 2.0 和 3.0 可以通過兩種方法來處理 Diffgram 並更新數據庫:通過 ADO 的 XML 方言(使用 CommandStream 對象);通過 SQLXML 虛擬目錄(按照與處理 XML 模板大體相同的方式來處理 Diffgram)。這兩種方法都使用 XSD 映射架構來將 Diffgram 中的數據映射到數據庫結構
有選擇地使用 Diffgram
由於 ADO.Net 能夠自動生成 Diffgram,因此 Diffgram 比 updategram 更有用。但是,只有當您的數據庫不引用具有外鍵的標識列,而且您能夠控制客戶端代碼使用的 XML 架構時,才應當使用 Diffgram。如果能夠滿足這兩個條件,就可以確保成功地解釋 Web 應用程序接收的 Diffgram。
或許有一天,標准語言將像在 XML 文檔中表示那樣來表達對數據進行的更改,而不是基於編程模型處理數據的方式來進行表達。那時,我們將能夠快速構建 Web 應用程序,以便在不同的平台、語言、框架和數據庫管理系統之間交換數據以及對數據進行的更改。