熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

剖析 ADO.NET 批處理更新(深入研究數據訪問)

2013-11-13 09:58:09  來源: .NET編程 

  ADONET 應用程序和基礎數據源之間的交互基於一個具有雙向信道的雙體系結構您可以使用各個特定於提供程序的命令或批處理更新過程來訪問數據源以讀取和寫入行在這兩種情況下數據訪問都會產生完全雙向綁定並涉及各種不同的對象和方法您可以使用如 SqlCommand 和 OleDbCommand 等命令類來執行單個命令可使用數據適配器對象來下載斷開連接的數據提交更新的行集雖然 數據集 是數據適配器用於返回和提交記錄塊的容器對象但各個命令通過數據讀取器對象返回數據
  
  更新是通過各個命令存儲過程完成的通常托管提供程序理解的任何命令文本一般都被稱為更新更新命令總是執行嵌入在語句正文中的新數據更新命令總是需要一個打開的連接可能還需要一個正在進行的事務處理或一個新的事務處理批處理更新則是一個略有不同的方法分支從最高的抽象級別來看您並不發出命令無論它可能有多麼復雜取而代之的是您提交在客戶端修改的當前行的快照並等待數據源批准批處理更新背後的關鍵概念是數據斷開連接的概念您下載行表通常為數據集根據需要在客戶端對它進行修改然後將這些行的新映像提交到數據庫服務器您所作的是提交更改而不是執行一個對數據源創建更改的命令這就是更新(我在 July column 一文中討論過這個問題)和批處理更新之間的本質區別
  
  下圖說明了 ADONET 的雙更新體系結構
  

  
ADONET 應用程序和數據源之間的兩個雙向交互

  
  在進一步詳細討論 ADONET 批處理更新之前我需要闡明常常會導致某種誤解的批處理更新模型的一個方面雖然更新和批處理更新在 ADONET 內的實際實現方面有著本質的區別但它們遵循的是同一個更新模型更新和批處理更新都是通過直接的並且特定於提供程序的語句來完成的當然由於批處理更新通常涉及到更多的行所以這些語句會被組合為一個批處理調用批處理更新會對目標數據集的行進行從頭到尾的循環只要發現更新的行就會發出適當的更新命令(INSERTDELETE 或 UPDATE)對更新的行進行通信時將運行一個預定義的直接 SQL 命令從本質上來說這就是批處理更新
  
  這個過程是理所當然的實際上如果批處理更新使用完全不同的更新模型就需要來自數據源的特殊支持(這正是向 SQL Server 提交 XML updategram 時發生的情況)批處理更新只是一個用來簡化多個行更新提交的客戶端提供的軟件機制在任何情況下每個新行提交總是通過數據源直接命令的正常通道完成的
  
  到目前為止本文只提及了 SQL 命令但這些提及的內容都明確表明了 ADO 批處理更新實現和 ADONET 批處理更新實現之間的一個重要區別在 ADO 中批處理更新只可能發生在基於 SQL 的數據源上而在 ADONET 中批處理更新則可能發生在任何種類的托管提供程序上其中包括那些不應該通過 SQL 查詢語言公開其數據的托管提供程序現在我們可以開始討論 ADONET 批處理更新編程的關鍵內容了
  
  准備用於提交的數據集
  ADONET 批處理更新通過數據適配器對象的 更新 方法進行數據只能以每個表為基礎進行提交如果您調用 更新 時沒有指定表名則使用 Table 這個默認的表名如果不存在具有該名稱的表則會產生異常更新 首先檢查每個表行的 RowState 屬性然後為所指定表中的每個插入行更新行或刪除行准備自定義的 INSERTUPDATE 或 DELETE 語句
  
  更新 方法有幾個超載它可以采用數據集和數據表提供的對某個數據表甚至是一個 DataRow 對象數組該方法會返回一個整數值即成功更新的行數
  
  為了最大限度地減少網絡通信通常會對正在操作的數據集的一個子集調用 更新毫無疑問這個子集只包含當時已修改的行您可以通過調用數據集的 GetChanges 方法來獲得這樣的子集
  
  if (dsHasChanges())
  {
  DataSet dsChanges = dsGetChanges();
  adapterUpdate(dsChanges MyTable);
  }
  
  另外您可以使用 HasChanges 方法檢查數據集是否發生了更改HasChanges 返回一個布爾值
  
  GetChanges 返回的數據集包含當時已插入刪除或修改的行但這裡所說的當時是什麼時間呢?這正是 ADONET 批處理更新比較復雜的一個方面必須與表行的當前狀態一起處理
  
  行的狀態
  數據表 中的每一行都是通過 DataRow 對象呈現的DataRow 對象主要是作為父 數據表 對象的 Rows 集合的一個元素而存在的從概念上來看數據庫行固有地鏈接到了某個給定表的結構就是由於這個原因ADONET 中的 DataRow 類不提供公用構造函數創建新 DataRow 對象的唯一方式是借助於對 數據表 對象的某個實時實例調用名為 NewRow 的方法剛剛創建好的行還不屬於父表的 Rows 集合但該行與此集合的關系決定了該行的狀態下表顯示了 RowState 屬性的一些可取值這些值組合在了 DataRowState 枚舉中
  
  Added
   該行已添加到表中
  
  Deleted
   該行已標記為從父表刪除
  
  Detached
   該行已創建但尚未添加到表中或者該行已從表行的集合中刪除
  
  Modified
   該行中的某些列已更改
  
  Added
   該行已添加到表中
  
  Unchanged
   在創建後或上次調用 AcceptChanges 方法後未對該行進行任何更改
  
  每一行的 RowState 屬性都會影響 HasChanges 方法的返回值以及 GetChanges 返回的子數據集的內容
  
  從這些可取值的范圍可以看出RowState 的值主要取決於對行已經執行的操作ADONET 表基於兩個方法 - AcceptChanges 和 RejectChanges - 來實現類似事務處理的提交模型從數據源下載表時或在內存中新建表時所有行都是沒有更改的您輸入的所有更改不會立即變為永久性更改隨時都可以通過調用 RejectChanges 來回滾更改您可以在三個級別調用 RejectChanges 方法
  
  &#; 在數據集級別上可拒絕所有更改(無論是什麼更改)
  
  &#; 在數據表級別上可取消某個表中的所有更改
  
  &#; 在某個特定的行級別上可還原到該行以前的狀態
  
  方法 AcceptChanges 能夠提交所有正在進行的更改它使得數據集會將當前值接受為新的原始值因此所有掛起的更改都被清除與 RejectChanges 一樣也可以對整個數據集某個表或某個行調用 AcceptChanges
  
  當您開始一個批處理更新操作時只會考慮提交那些標記為 AddedDeleted 和 Modified 的行如果您恰好在批處理更新之前調用了 AcceptChanges則對數據源不進行任何持久更改
  
  另一方面一旦批處理更新操作成功完成您必須調用 AcceptChanges 來清除掛起的更改並將當前數據集值標記為原始值注意如果省略了最後對 AcceptChanges 的調用數據集中則會保留掛起的更改從而導致在下次進行批處理更新時重新發出這些更改
  
  // Get changes in the DataSet
  dsChanges = dsGetChanges();
  // Performs the batch update for the given table
  daUpdate(dsChanges strTable);
  // Clears any pending change in memory
  dsAcceptChanges();
  
  上面的代碼說明了 ADONET 批處理更新背後的三個主要步驟
  
  如果從數據集表中刪除行請注意您使用的方法是 刪除 還是 移除刪除 方法會通過將行標記為 刪除執行邏輯刪除移除 方法則從 Rows 集合中物理刪除該行因此通過 移除 刪除的行不會標記為刪除因此在後面的批處理更新期間也不會被處理如果您的最終刪除目標是從數據源刪除行則應使用 刪除
  
  更新的深入內容
  有三個操作可改變表的狀態
  
  &#; 插入一個新行
  
  &#; 刪除一個現有的行
  
  &#; 更新一個現有的行
  
  
  對於其中的每一個關鍵操作數據適配器都會定義一個作為屬性公開的自定義的命令對象這樣的屬性包括 InsertCommandDeleteCommand 和 UpdateCommand程序員負責為這些屬性分配有意義的命令對象例如SqlCommand 對象
  
  僅提供的 InsertCommandDeleteCommand 和 UpdateCommand 屬性就代表了從 ADO 到 ADONET 的巨大突破利用這種屬性您可以對內存中的更新提交到數據庫服務器的方式進行前所未有的控制如果您不滿意 ADONET 生成的更新代碼現在則可以修改這些更新代碼而不會否定批處理更新的整體特性使用 ADO 的時候您對庫靜默生成的 SQL 命令毫無控制權而在 ADONET 中利用公開顯示的命令對象您可以使用更符合用戶期望的自定義存儲過程或 SQL 語句來應用更新特別是您可以對交叉引用的表使用批處理更新系統甚至可以諸如 Active Directory&#; 或 Indexing Services 這樣的非 SQL 數據提供程序為目標
  
  更新命令應該針對表中每個更改的行運行並且必須非常通用以適應不同的值對於這種任務非常適合使用命令參數只要您可以將它們綁定到數據庫列的值ADONET 參數對象公開兩個用於這種綁定的屬性例如 SourceColumn 和 SourceVersion尤其是 SourceColumn它表示一種指示參數值的間接方式您可以使用列名設置 SourceColumn 屬性並且使批處理更新機制不時地提取有效值而不是使用 Value 屬性
From:http://tw.wingwit.com/Article/program/net/201311/12146.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.