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