DataAdapter 的 Update 方法可調用來將 DataSet 中的更改解析回資料來源。與 Fill 方法類似,Update 方法將 DataSet 的執行個體和可選的 DataTable 對象或 DataTable 名稱用作參數。DataSet 執行個體是包含已作出的更改的 DataSet,而 DataTable 標識從其中檢索更改的表。
當調用 Update 方法時,DataAdapter 將分析已作出的更改並執行相應的命令(INSERT、UPDATE 或 DELETE)。當 DataAdapter 遇到對 DataRow 的更改時,它將使用 InsertCommand、UpdateCommand 或 DeleteCommand 來處理該更改。這樣,您就可以通過在設計時指定命令文法並在可能時通過使用預存程序來盡量提高 ADO.NET 應用程式的效能。在調用 Update 之前,必須顯式設定這些命令。如果調用了 Update 但不存在用於特定更新的相應命令(例如,不存在用於已刪除行的 DeleteCommand),則將引發異常。
Command 參數可用於為 DataSet 中每個已修改行的 SQL 陳述式或預存程序指定輸入和輸出值。有關更多資訊,請參見將參數用於 DataAdapter。
如果 DataTable 映射到單個資料庫表或從單個資料庫表產生,則可以利用 DbCommandBuilder 對象自動產生 DataAdapter 的 DeleteCommand、InsertCommand 和 UpdateCommand。有關更多資訊,請參見自動產生命令。
Update 方法會將更改解析回資料來源;但是自上次填充 DataSet 以來,其他用戶端可能已修改了資料來源中的資料。若要使用當前資料重新整理 DataSet,請使用 DataAdapter 和 Fill 方法。新行將添加到該表中,更新的資訊將併入現有行。Fill 方法通過檢查 DataSet 中行的主索引值及 SelectCommand 返回的行來確定是要添加一個新行還是更新現有行。如果 Fill 方法發現 DataSet 中某行的主索引值與 SelectCommand 返回結果中某行的主索引值相匹配,則它將用 SelectCommand 返回的行中的資訊更新現有行,並將現有行的 RowState 設定為 Unchanged。如果 SelectCommand 返回的行所具有的主索引值與 DataSet 中行的任何主索引值都不匹配,則 Fill 方法將添加 RowState 為 Unchanged 的新行。
| 注意 |
如果 SelectCommand 返回 OUTER JOIN 的結果,則 DataAdapter 不會為產生的 DataTable 設定 PrimaryKey 值。您必須自己定義 PrimaryKey 以確保正確解析重複行。有關更多資訊,請參見為表定義主鍵。 |
要處理在調用 Update 方法時可能發生的異常,可以使用 RowUpdated 事件響應更新行時發生的錯誤(請參見使用 DataAdapter 事件),也可以在調用 Update 之前將 DataAdapter.ContinueUpdateOnError 設定為 true,並在更新完成後響應特定行的 RowError 屬性中儲存的錯誤資訊(請參見添加和讀取行錯誤資訊)。
| 注意 |
如果對 DataSet、DataTable 或 DataRow 調用 AcceptChanges,則將使 DataRow 的所有 Original 值都將被重寫為該 DataRow 的 Current 值。如果已修改將該行標識為唯一行的欄位值,那麼當調用 AcceptChanges 後,Original 值將不再匹配資料來源中的值。 |
樣本
以下樣本示範如何通過顯式設定 DataAdapter 的 UpdateCommand 來執行對已修改行的更新。請注意,在 UPDATE 語句的 WHERE 子句中指定的參數設定為使用 SourceColumn 的 Original 值。這一點很重要,因為 Current 值可能已被修改,並且可能不匹配資料來源中的值。Original 值是曾用來從資料來源填充 DataTable 的值。
Visual Basic 複製代碼
' Assumes connection is a valid SqlConnection.Dim adapter As SqlDataAdapter = New SqlDataAdapter( _"SELECT CategoryID, CategoryName FROM Categories", connection)adapter.UpdateCommand = New SqlCommand( _"UPDATE Categories SET CategoryName = @CategoryName " & _"WHERE CategoryID = @CategoryID", connection)adapter.UpdateCommand.Parameters.Add( _"@CategoryName", SqlDbType.NVarChar, 15, "CategoryName")Dim parameter As SqlParameter = adapter.UpdateCommand.Parameters.Add( _"@CategoryID", SqlDbType.Int)parameter.SourceColumn = "CategoryID"parameter.SourceVersion = DataRowVersion.OriginalDim dataSet As DataSet = New DataSetadapter.Fill(dataSet, "Categories")Dim row As DataRow = dataSet.Tables("Categories").Rows(0)row("CategoryName") = "New Category"adapter.Update(dataSet, "Categories")C# 複製代碼
// Assumes connection is a valid SqlConnection.SqlDataAdapter dataAdpater = new SqlDataAdapter("SELECT CategoryID, CategoryName FROM Categories", connection);dataAdpater.UpdateCommand = new SqlCommand("UPDATE Categories SET CategoryName = @CategoryName " +"WHERE CategoryID = @CategoryID" , connection);dataAdpater.UpdateCommand.Parameters.Add("@CategoryName", SqlDbType.NVarChar, 15, "CategoryName");SqlParameter parameter = dataAdpater.UpdateCommand.Parameters.Add("@CategoryID", SqlDbType.Int);parameter.SourceColumn = "CategoryID";parameter.SourceVersion = DataRowVersion.Original;DataSet dataSet = new DataSet();dataAdpater.Fill(dataSet, "Categories");DataRow row = dataSet.Tables["Categories"].Rows[0];row ["CategoryName"] = "New Category";dataAdpater.Update(dataSet, "Categories");自動遞增列
如果來自資料來源的表包含自動遞增列,則可以通過以下方法填充 DataSet 中的列:通過以預存程序輸出參數的形式返回自動遞增值並將其映射到表中的一列,或者使用 DataAdapter 的 RowUpdated 事件。有關相應的樣本,請參見檢索“標識”或“自動編號”值。
但是,DataSet 中的值可能會與資料來源中的值不同步並導致意外的行為。例如,請考慮一個包含自動遞增主鍵列 CustomerID 的表。如果在該 DataSet 中添加兩個新客戶,他們將收到自動遞增的 CustomerId 值 1 和 2。在向 DataAdapter 的 Update 方法傳遞第二個客戶行時,新添加的行會收到資料來源中的自動遞增 CustomerID 值 1,該值與 DataSet 中的值 2 不匹配。當 DataAdapter 使用傳回值填充 DataSet 中的行時,由於第一個客戶行的 CustomerID 是 1,因此將發生約束衝突。
為了避免這種行為,建議在使用資料來源中的自動遞增列和 DataSet 中的自動遞增列時,在 DataSet 中建立 AutoIncrementStep 為 -1 且 AutoIncrementSeed 為 0 的列,並確保資料來源產生從 1 開始並以正步長值遞增的自動遞增標識值。這樣,DataSet 將為自動遞增值產生負數,這些負數不會與資料來源所產生的正自動遞增值發生衝突。另一種方法是使用 Guid 類型的列而不是自動遞增列。產生 Guid 值的演算法在 DataSet 中產生的 Guid 不應與資料來源產生的 Guid 相同。有關定義 DataTable 中的列的更多資訊,請參見定義 DataTable 的架構。
插入、更新和刪除的排序
在許多情況下,以何種順序向資料來源發送通過 DataSet 作出的更改是相當重要的。例如,如果已更新現有行的主索引值並且添加了具有新主索引值的新行,則務必要在處理插入之前處理更新。
可以使用 DataTable 的 Select 方法來返回僅引用具有特定 RowState 的 DataRow 數組。然後可以將返回的 DataRow 數組傳遞到 DataAdapter 的 Update 方法來處理已修改的行。通過指定要更新的行的子集,可以控制處理插入、更新和刪除的順序。
樣本
例如,以下代碼確保首先處理表中已刪除的行,然後處理已更新的行,然後處理已插入的行。