為ADO 程式員設計的 ADO.NET (轉)

來源:互聯網
上載者:User
ado|程式|程式員|設計 摘要:本文討論如何以 ADO.NET 方式實現基本資料庫操作,以及何時使用 ADO.NET 代替 ADO。

目錄
.NET 中的資料訪問
讀取資料
DataSet、DataTable 和 Recordset
轉換現有代碼
更新資料
XML 擴充支援
總結

自若干年前推出開放式資料庫連接 (ODBC) API (API) 以來,出現了各種各樣的資料庫訪問技術,而 ADO.NET 是其中最新的一種。在這過程中,發生了許多有趣的事。例如,COM 闖入資料庫領域,開始培植 OLE DB 的殖民進程。然後,大致相當於 OLE DB 自動化版本的 ActiveX® Data Objects (ADO) 被選來統治 Windows® 資料庫開發人員的 Visual Basic® 和 ASP 社區。

通過 .NET,Microsoft 正在提供通用架構(即 Framework Class Library),其中將包括所有現有的 Windows API 甚至更多的內容。特別值得一提的是,它包括大量常用的庫,而這些庫現在需要通過各個 COM 物件分別獲得。在這些庫中,您會發現 XML 和 ADO 物件模型,它們被整合到了叫做 ADO.NET 的類子樹中。

ADO.NET 事實上成為構建資料感知 .NET 應用程式的基礎。和 ADO 不同的是,ADO.NET 遵循更通用的原則,不那麼專門面向資料庫。ADO.NET 集合了所有允許資料處理的類。這些類表示具有典型資料庫功能(如索引、排序和視圖)的資料容器物件。儘管 ADO.NET 是 .NET 資料庫應用程式的權威解決方案,但從總體設計上來看,它不象 ADO 模型那樣以資料庫為中心,這是 ADO.NET 的一大特點。

ADO.NET 與 ADO 有很大差異。ADO.NET 是新的資料訪問編程模型,需要開發人員的全面理解、投入和新思維。然而,一旦開始掌握 ADO.NET,您將意識到:原有的 ADO 技巧非常有助於您以不同、卻更巧妙和可靠的方式來建立有效應用程式和解決各種老問題。

在這篇文章的其餘部分,我將集中介紹如何以 ADO.NET 方式實現基本的資料庫操作。我想說明,在什麼時候 ADO.NET 是比 ADO 更好的選擇,而您最好在什麼時候應放棄 ADO。ADO.NET 並不是將 ADO 改良以符合 .NET 基礎結構而形成的。只要您看一下 ADO.NET 的文法、代碼設計和移植,就會明白這一點。

.NET 中的資料訪問
在 ADO.NET 中訪問資料來源的方式由Managed 提供者確定。從功能上講,Managed 提供者與 OLE DB 的提供者非常相似,但有兩個重要的不同之處。首先,管理提供者在 .NET 環境中工作,通過 DataReader 和 DataTable 等 .NET 類檢索和公開資料。其次,因為它們的體繫結構針對 .NET 進行了最佳化,所以比較簡單。

目前 ADO.NET 提供了兩種Managed 提供者:一種用於 SQL Server™ 7.0 或更高版本,另一種用於其他所有您可能已經安裝的 OLE DB 提供者。在這兩種情況下您分別使用不同的類,但遵循相似的命名規則。除首碼外,名稱都是相同的。前一種情況首碼為 SQL,後一種情況則是 ADO。

您應該使用 SQL 類訪問 SQL Server 表,因為它們直接進入資料庫伺服器的內部 API,跳過了由 OLE DB 提供者表示的中介層。ADO 類是 OLE DB 提供者上的 .NET 介面,它們使用 COM Interop 橋進行工作。

ADO.NET 對象的初學者可參閱 Omri Gazitt 的文章介紹 ADO+:用於 Microsoft .NET 架構的資料訪問服務(英文)和我的 ADO+ 推動資料種類的演變(英文)一文。前者技術性較強,針對 ADO.NET 程式模型提供了高水平的評註性概述。後者主要介紹 ADO.NET 的目標和它與 XML、指令碼以及其他技術之間的聯絡。

讀取資料
需要從資料來源中讀取資料的 ADO.NET 應用程式首先要建立連線物件。根據目標提供者的不同,該連線物件可以是 SQLConnection 或 ADOConnection。請記住,您可以使用 ADO.NET 類來串連到 SQL Server 資料庫,但我們不建議這樣做。其唯一的缺點是,您的代碼要通過不必要的額外代碼層。它先將 ADO 的Managed 提供者調入,然後Managed 提供者再調用 SQL Server OLE DB 提供者。而 SQL Server Managed 提供者和 OLE DB 提供者一樣直接操作資料。

ADO 和 ADO.NET 連線物件之間的顯著差異是:ADO.NET 串連不支援 CursorLocation 屬性。請注意,這並不是一個文檔錯誤,而是一個有爭議的設計問題。為了突出以資料為中心的原則,ADO.NET 沒有遊標的顯式實現。

在 ADO 中,您習慣了用遊標從資料庫或其他任何 OLE DB 相容的資料來源中抽取記錄。您可以選擇用戶端或伺服器資料指標,每種遊標都有幾個預先設定的遊標類型。ADO.NET 則設計為從資料來源中抽取資料,並提供新的編程介面來讀取和分析資料。

在 ADO 中,您通過指定串連和命令文本來建立 Recordset 對象。對於遊標的位置和類型,Recordset 有一定策略。您可以按下列方式之一讀取資料:

在記憶體中建立選定記錄的靜態副本,然後在從資料來源中斷連線時根據需要處理這些記錄。ADO 稱之為靜態資料指標。


通過快速、僅向前的唯讀遊標來滾動資料,這種遊標工作在記錄的靜態快照中。ADO 稱之為唯讀遊標。


通過伺服器端的兩種遊標來訪問資料,這些遊標需要保持良好的串連,但您可以在各個不同層次上隨時檢測其他已串連的使用者的更改。ADO 稱它們為鍵集和動態資料指標。
前兩種方式都在中斷連線的記錄集內工作,並從用戶端緩衝讀取資訊,這是它們的相似之處。另外,在面向 Web 的環境中和對於新的 n 層系統,這兩種方式被證明是使用頻率最高的。

在 ADO 中,以上所有這些方式與不同類型的遊標相對應。您將在本文後面發現,雖然 ADO.NET 有很大不同,但它能實現您用 ADO 可實現的任何功能。只不過您的代碼將從實際資料來源及其實體儲存體媒介和格式中抽取資料。

ADO.NET 提供兩個對象來處理從資料來源中抽取的資料。它們是 DataSet 和 DataReader 對象。前者是記錄在記憶體中的緩衝,您可以從任何方向隨意訪問和修改。後者是高度最佳化的對象,專為以僅向前方式滾動唯讀記錄而設計。請注意 DataSet 看起來象靜態資料指標,但實際上,在 .NET 中與 ADO 唯讀遊標相對應的是 DataReader 對象。

在 ADO.NET 中,不支援伺服器端遊標。然而,這不意味著您不能使用遊標。您需要做的是在 .NET 中匯入 ADO 類型庫。在項目視窗的 References 節點上單擊右鍵就行了。匯入之後,您便可以開始在應用程式中使用本地 ADO 對象了。

儘管我承認下決心轉向 .NET 是一件很難的事情,但我個人還是建議您考慮用 .NET 重寫現有應用程式。可以把完全匯入 ADO 作為邁向 .NET 的第一步,這無須投入太多的時間和資源。然而,請記住這隻是漫漫長路上的第一步。這絕不是您邁向 .NET 的唯一一步。.NET 具有超值價值的的真正原因在於統一和一致的編程介面以及對本地類的廣泛使用。您可以匯入 COM 類別型庫,但匯入 COM 類別型庫只能作為臨時解決方案或者中間步驟,我們並不鼓勵這樣做。

使用 ADO.NET 時,應當充分考慮到它統一了資料容器類編程介面這一事實。無論您打算編寫何種應用程式,Windows 表單、Web Form還是 Web 服務,都可以通過同一組類來處理資料。不管在後端的資料來源是 SQL Server 資料庫、OLE DB、XML 檔案還是一個數組,您都可以通過相同的方法和屬性來滾動和處理它們的內容。



圖 1:Solution Explorer 菜單

如果您堅持在 .NET 中使用 ADO,請準備面對一些副作用。例如,您需要額外的代碼才能夠從資料繫結控制項中使用記錄集。

DataSet、DataTable 和 Recordset
在 ADO.NET 中,沒有與 Recordset 對象直接對應的對象。最接近的是 DataTable 對象。儘管這兩個對象的功能幾乎一樣,但它們在各自的架構中起不同的作用。

Recordset 是一個大型物件,具有許多 ADO 功能,但還是有所欠缺。Recordset 在很多方面效能優良,例如可建立性、中斷連線時仍能工作、功能豐富等等。但是,在某些方面仍然有待提高。例如,由於 Recordset 固有的 COM 特性,通過網路進行序列化的工作將非常繁重。又如它是二進位對象,所以在不同的平台上啟動並執行模組很難共用它,而且它不能穿過防火牆。另外,Recordset 表示多個記錄的單個表。如果該表是由一個或多個 JOIN 產生的,更新未經處理資料源可能會很困難。如果您要使中斷連線的記錄集和未經處理資料源保持協調,資料來源必須能夠識別 SQL。然而,您的記錄集很可能是通過非 SQL 提供者建立的。

在 ADO.NET 中,ADO Recordset 的所有功能被拆分成幾個較簡單的對象,DataReader 就是其中之一。DataReader 類比快速、僅向前的唯讀遊標的操作。

DataTable 是一個表示資料來源的簡單對象。您可以手動構造 DataTable,也可以通過 DataSet 命令自動填滿它。DataTable 不區分它所包含的資料的來源。該對象允許您在記憶體中處理資料,以及執行瀏覽、排序、編輯、應用篩選器、建立視圖等操作。

ADO 中沒有與 DataSet 相對應的對象。DataSet 對象是一個容器類,是實現 ADO.NET 資料幫浦的關鍵對象。DataSet 將一個或多個 DataTable 對象分組。DataTable 通過象行和列這樣的通用集合公開它的內容。當您嘗試從資料表中讀取資料時,您可能會經過兩個不同的對象層:DataTableMapping 和 DataView。

DataTableMapping 對象描述了資料來源中的資料列和 DataTable 對象之間的映射關係。當填充 DataSet 時,DataSetCommand 對象要使用這個類。它維護資料集中的抽象列和資料來源中的物理列之間的連結。

表的視圖通過 DataView 對象實現。它表示 DataTable 的自訂視圖,可以綁定到特定控制項(如 Windows 表單和 Web Form中的資料格)中。該對象相當於 SQL CREATE VIEW 語句在記憶體中的實現。

DataSet 中的所有表都可以通過一個公用域放入關係中。這個關係由 DataRelation 對象管理。這看起來很象 ADO 的資料形成,但有一點重要區別。您不需要使用資料形成語言,您最終會擁有一個非常靈活的結構體系。ADO.NET 導航模型使您可以輕而易舉地從某一張表內的主行移入它的所有子行。

DataRelation 對象相當於 JOIN 語句在記憶體中的實現,可用於建立資料類型相同的列的父/子關係。一旦建立了關係,就不允許出現任何會破壞這種關係的更改,如果出現就會導致運行時異常。視圖和關係是實現主表/明細表架構的兩種方式。要記住,視圖只是放在記錄上的掩碼,而關係是設定在兩個表的一個或多個列之間的動態連結。如果使用關係,您不能更改順序或設定條件。

如果您的代碼需要一對一外鍵關係,並且不更改資料,那麼您最好不要使用無格式的 JOIN 命令。如果您需要額外的篩選功能,就應該使用 ADO.NET 自訂視圖。

轉換現有代碼
有許多 ASP 頁面使用 ADO 對象來抽取資料。讓我們來討論幾種典型的情況,您在不久的將來移植和改編代碼時可能會遇上這些情形。

如果您有從單個記錄集產生報表的 ASP 頁面,DataReader 對象將是您最好的夥伴。
您瀏覽 DataReader 對象時,它會將結果輸出到頁面。

String strConn, strCmd;
strConn = "DATABASE=MyAgenda;SERVER=localhost;UID=sa;PWD=;";
strCmd = "Select * From Names where ID=" + contactID.Text;
SQLConnection oCN = new SQLConnection(strConn);
SQLCommand oCMD = new SQLCommand(strCmd, oCN);
oCN.Open();
SQLDataReader dr;
oCMD.Execute(out dr);
while (dr.Read()) {
// 使用 dr.GetString(index) 或
// dr["field name"] 的方法 Response.Write 來輸出資料
}

您還可以用 HasMoreRows 屬性快速檢查 DataReader 是否為空白。如果您只需要快速探索一系列記錄,沒有比 DataReader 更好更快的對象了。它同樣適用於查詢單個記錄。您不能編輯 DataReader 的內容,但您可以將其內容移入更易於管理的對象,例如 DataTable 或者一個或多個 DataRow 對象。

當您需要處理表和記錄之間的複雜關係時,DataReader 就不再是合適的工具了。在 ADO 中, 最終您需要處理記錄集。您的資料模型連結越多,SQL 命令就越複雜。導航模型仍然是順序的,最後放入緩衝的資料往往多於你所需要的。DataSet 和 DataRelation 對象是這種表關聯式模式的基礎。

為了管理父/子關係,ADO 還封裝了資料形成引擎。從功能上講,資料形成和 ADO.NET 關係是一樣的。然而,從設計方面來看,它們幾乎沒有什麼共同點。形成記錄集將所有資訊嵌入單個列表對象。ADO.NET 關係是您可以隨時在兩個資料表之間建立的動態連結。為了在執行單個 ADO 命令的過程中建立一個階層記錄集,ADO 要依靠 Shaping OLE DB 服務提供者,並且使用特定的類 SQL 語言。

在 ADO.NET 中,關係中涉及的每個對象總是被看成單獨的個體。關係本身作為對象被公開,並且具有一定的行為規則。例如,DataRelation 對象可以從父行到子行一層層變更。您可以通過將 ForeignKeyConstraint 對象添加到 DataTable 的 Constraints 集合中來進行此操作。ForeignKeyConstraint 對象表示當刪除或更新數值和行時,對通過外鍵關係相關聯的一組列的約束。如前面提到的,一旦設定好了關係,在它按程式預設終止之前,您不能進行可能破壞該關係的更改。

另外,關係是不可傳遞的。您可以建立兩組不同的關係,例如客戶和訂單、訂單和產品之間的關係。然而,當在訂單中導航以尋找某一位客戶時,您不能從一個訂單跳到與之相關的產品行。您必須另外開啟訂單/產品關係,定位到您需要的訂單,然後才能擷取相關的行。這就是為什麼有時候最好不要通過原來的無格式 SQL JOIN 語句實現一對一關聯性的原因。

需要在 ASP Session 對象中儲存記錄嗎?利用 ADO.NET 和 DataSet 對象,您可以相當安全的操作而不會導致在在 GIT 中儲存 ADO 記錄集可能會導致存取違規(英文)中所討論的問題,也不會有線程相似性的麻煩。

更新資料
更新資料時,Web 應用程式通常使用無格式 SQL 陳述式,或者使用更好的參數化預存程序。然而,當需要使用未串連的資料時,您可能想使用內建服務來更新所有需要修訂的記錄。ADO 提供了批更新機制來實現這個功能。

UpdateBatch 方法用於把儲存在副本緩衝中的 Recordset 更改發送到伺服器,以更新資料來源。它採用開放式鎖定,允許所有掛起的本地更改。它還在單個操作中把所有更改傳送到資料來源。僅當更改提交後資料來源鎖定要更改的記錄時,才會出現開放式鎖定。開放式鎖定使兩個使用者可以同時訪問同一個記錄,但一個使用者輸入的更改很快會被另一使用者所覆蓋。當然,這種方式要求資料來源能夠檢測和防止資料衝突。還要求整個資料來源比較穩定,不會發生頻繁的更改。否則,不難想象協調費用將很快超過替代嚴格鎖定所帶來的節約。事實上,使用 UpdateBatch 方法,在任何更改失敗時都會返回一個錯誤。然後,您可以通過 Errors 集合和 Error 對象來訪問該錯誤。

要理解 ADO.NET 模型為什麼是更新資料的更強大的工具,理解 ADO 中開放式鎖定的工作原理是非常關鍵的。在 ADO 代碼中,您無法控制調用 UpdateBatch 之後所發生的一切。也就是說,更新是在伺服器上通過滾動已更改的行,然後比較原始值和資料來源中對應記錄中的當前值來進行的。當所有的值都一致了,才對錶執行適當的 SQL 陳述式(INSERT、UPDATE 或 DELETE)。

問題在於您不能控制實際應用於更改的 SQL 陳述式。伺服器端的更新代碼並不比您編寫的代碼好,如果您採用非 SQL 提供者,它甚至無法運行。在本節的開頭,我曾講過 Web 應用程式通常通過參數化預存程序來更新資料。然而,如果您使用批更新就不同了。

在 ADO.NET 中,這個模型已經有所擴充。現在它採用更通用的架構,允許您自己指定基本操作命令,例如插入、刪除、更新和選擇等。其用意很明顯:不論何種資料來源,都可以從中抽取資料並提供同樣的支援。在 ADO.NET 中進行批更新,您需要建立 DataSetCommand 對象即 SQLDataSetCommand 或 ADODataSetCommand。

注意:在 Beta 2 中,DataSetCommand 對象將被稱為 DataAdapter 對象。

擁有 DataSetCommand 對象之後,您便可以調用它的 Update 方法。DataSetCommand 提供 InsertCommand、DeleteCommand、UpdateCommand 和 SelectCommand 等屬性。它們都是 Command 對象。但是,除非預設行為無法滿足需要,否則您不必設定它們。這與在 ADO 中一樣。在 Update 過程中,如果沒有設定任何 xxxCommand 屬性,但是存在主鍵資訊,將自動產生 Command 對象。請注意,要使上述過程正確進行,必須為所涉及的資料表設定主鍵。

以下代碼顯示了如何為 DataSet 的 EmployeesList 表設定主鍵:

DataColumn[] keys = new DataColumn[1];
keys[0] = m_oDS.Tables["EmployeesList"].Columns["EmployeeID"];
m_oDS.Tables["EmployeesList"].PrimaryKey = keys;

主鍵基本上是 DataColumn 對象的一個數組。

如果您要使用預存程序來更新表,或者採用專用非 SQL 資料提供者,您會經常用到這些命令屬性。

XML 擴充支援
在 ADO 中,XML 只不過是輸入和輸出格式。然而在 ADO.NET 中,XML 是一種資料格式,提供了操作、組織、共用和傳遞資料的手段。任何帶入 DataSet 的資料,無論其來源,都能通過雙面編程模型進行處理。您可以順序交替訪問資訊,或者按行訪問,也可以按照 XML 文件物件模型驅動的非順序、階層路徑進行訪問。

DataSet 將資料和架構作為 XML 文檔進行讀寫。資料和架構都可以通過 HTTP 傳輸,並且能在所有支援 XML 的平台上使用。相同的資料在不同的時候可以通過不同的架構來呈現,這是通過 XSLT 實現的。您可以使用 ReadXmlSchema 方法編寫架構。XML 結構描述包括資料集中的表的說明,以及表的關係和約束。在調用 ReadXmlData 方法填充 DataSet 之前,應該先完成這個步驟。

以下程式碼範例是一個顯示可更新資料表的最簡單的 ASP.NET 頁面。

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.IO" %>

<script runat="server" language="C#">
void Page_Load(Object source, EventArgs e)
{
   DataSet data = new DataSet();
   
   // 載入 XML 資料和架構
   StreamReader sr;
   sr = new StreamReader(Server.MapPath("data.xml"));
   data.ReadXml(sr);
   sr.Close();
   
   // 添加通過 URL 傳遞的新記錄
   if (Request.QueryString.Count >0)
   {
      DataTable dt = data.Tables[0];
      DataRow dr = dt.NewRow();
      dr["FirstName"] = Request.QueryString["First"];
      dr["LastName"] = Request.QueryString["Last"];
      dt.Rows.Add(dr);
      dt.AcceptChanges();
      
      StreamWriter sw;
      sw = new StreamWriter(Server.MapPath("data.xml"));
      data.WriteXml(sw);
      sw.Close();
   }

      // 重新整理 UI(由網格組成)
   grid.DataSource = data.Tables[0].DefaultView;
   grid.DataBind();
}
</script>

如圖 2 所示,您可以將新的行添加到表中。然而,它不涉及 SQL Server 或 Access 表。它只是一個 XML 檔案,在處理它的代碼中,沒有使用 XML 節點或 XMLDOM 方法。您可以用相同的直觀資料表介面來讀取和更新 XML 記錄。您的工作方式與在 ADO 中大致相同,但此處的模型更深入、更龐大,有更多的潛力供您去發掘。



圖 2:可更新表的樣本

總結
Web 應用程式的成功改變了典型分布式系統的面貌。現在大多數分布式系統都是 n 層系統,這類系統對擴充性和互通性的要求越來越高。因此,非串連資料處理和 XML 成為最佳實務,並為業界廣為接受。  

ADO.NET 嘗試將當今一些最好的實踐統一在 .NET 下。這種用於資料訪問的編程模型全面而又非常強大。但這個模型可能尚不能滿足每一個人的要求,在將來的模型設計中還需要邁出一大步。然而,請記住現在 ADO.NET 還只是 Beta 版,只有有限的文檔支援。

ADO 程式員從 Beta 版中獲益最多,因為他們熟悉了 ADO.NET 的許多方面,包括最高層次的抽象即啟發性模型。ADO.NET 代碼與現有的 ADO 代碼不相容,但功能相似。要充分利用 ADO.NET,您應該花些功夫來理解概念本身,而不僅僅是找出移植代碼的最快方式。無論您選擇何種 .NET 編程模型,Windows 表單、Web Form還是 Web 服務,ADO.NET 都會協助您處理好資料訪問的問題。


相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。