轉自:http://blog.csdn.net/cui55/article/details/1371411
在 DataSet 中創建 DataTable 之后,您執行的活動可以與使用數據庫中的表時執行的活動相同。您可以添加、查看、編輯和刪除表中的數據;可以監視錯誤和事件;并且可以查詢表中的數據。在修改 DataTable 中的數據時,您也可以驗證更改是否正確,并決定是否以編程方式接受更改或拒絕更改。
本節內容
將數據添至表中:說明如何創建新行并將其添至表中。
在創建 DataTable 并使用列和約束定義其結構之后,您可以將新的數據行添至表中。要添加新行,可將一個新變量聲明為 DataRow 類型。調用 NewRow 方法時,將返回新的 DataRow 對象。然后,DataTable 會根據表的結構按 DataColumnCollection 的定義創建 DataRow 對象。
以下示例演示了如何通過調用 NewRow 方法來創建新行。
DataRow workRow = workTable.NewRow();
然后您可以使用索引或列名來操作新添加的行,如下例所示。
workRow["CustLName"] = "Smith"; workRow[1] = "Smith";
在將數據插入新行后,Add 方法可用于將行添至 DataRowCollection,如以下代碼所示。
workTable.Rows.Add(workRow);
您也可以通過傳入值的數組(類型化為 Object),調用 Add 方法來添加新行,如下例所示。
workTable.Rows.Add(new Object[] {1, "Smith"});
將類型化為 Object 的值的數組傳遞到 Add 方法,可在表內創建新行并將其列值設置為對象數組中的值。請注意,數組中的值會根據它們在表中出現的順序相繼與各列匹配。
以下示例將十行添至新建的 Customers 表中。
DataRow workRow;
for (int i = 0; i <= 9; i++) { workRow = workTable.NewRow(); workRow[0] = i; workRow[1] = "CustName" + i.ToString(); workTable.Rows.Add(workRow); } |
查看表中數據:說明如何訪問行中的數據,包括數據的原始版本和當前版本。
可以使用 DataTable 的 Rows 和 Columns 集合來訪問 DataTable 中的內容。也可以根據包括搜索標準、排序順序和行狀態等特定標準,使用 DataTable.Select 方法返回 DataTable 中數據的子集。此外,用主鍵值搜索特定行時,還可使用 DataRowCollection 的 Find 方法。
DataTable 對象的 Select 方法返回一組與指定條件匹配的 DataRow 對象。Select 采用篩選表達式、排序表達式和 DataViewRowState 的可選參數。篩選表達式根據 DataColumn 值(例如 LastName = 'Smith' 。排序表達式遵循用于為列排序的標準 SQL 約定,例如 LastName ASC, FirstName ASC 。有關編寫表達式的規則,請參閱DataColumn 類的 Expression 屬性。
提示 如果您將對 DataTable 的 Select 方法執行多次調用,可通過先為 DataTable 創建 DataView來提高性能。創建 DataView 會為表中的行編制索引。然后,Select 方法會使用該索引,這樣將顯著縮短生成查詢結果的時間。有關為 DataTable 創建 DataView 的信息,請參閱創建和使用 DataView。
Select 方法基于 DataViewRowState 確定要查看或操作的行的版本。下表說明了可能的 DataViewRowState 枚舉值。
成員名稱 |
說明 |
CurrentRows |
當前行,包括未更改的行、已添加的行和已修改的行。 |
Deleted |
已刪除的行。 |
ModifiedCurrent |
當前版本,它是原始數據的修改版本(請參閱ModifiedOriginal)。 |
ModifiedOriginal |
所有已修改行的原始版本。使用 ModifiedCurrent 時,當前版本可用。 |
Added |
新行。 |
None |
無。 |
OriginalRows |
原始行,包括未更改的行和已刪除的行。 |
Unchanged |
未更改的行。 |
在下面的示例中,DataSet 對象已經過篩選,這樣,您可以只使用其 DataViewRowState 設置為 CurrentRows的行。
DataRow[] currRows = workTable.Select(null, null, DataViewRowState.CurrentRows);
if (currRows.Length < 1 ) Console.WriteLine("No Current Rows Found"); else { foreach (DataColumn myCol in workTable.Columns) Console.Write("/t{0}", myCol.ColumnName);
Console.WriteLine("/tRowState");
foreach (DataRow myRow in currRows) { foreach (DataColumn myCol in workTable.Columns) Console.Write("/t{0}", myRow[myCol]);
Console.WriteLine("/t" + myRow.RowState); } }
Select 方法可用于返回具有不同 RowState 值或字段值的行。以下示例返回一個引用所有已刪除行的 DataRow數組,并返回另一個引用所有已排序行(按照 CustLName 排序,其中 CustID 列大于 5)的 DataRow 數組。
// Retrieve all deleted rows. DataRow[] delRows = workTable.Select(null, null, DataViewRowState.Deleted);
// Retrieve rows where CustID > 5, and order by CustLName. DataRow[] custRows = workTable.Select("CustID > 5", "CustLName ASC"); |
編輯表中的數據:說明如何修改行中的數據,包括掛起對行的更改,直至驗證并接受了建議的更改。
當您在 DataRow 中更改列值時,所做更改會立即置于行的 Current 狀態中。然后,RowState 會設置為Modified,并使用 DataRow 的 AcceptChanges 或 RejectChanges 方法來接受或拒絕所做更改。DataRow還提供了三種可用于在編輯行時將行的狀態掛起的方法。這些方法是 BeginEdit、EndEdit 和 CancelEdit。
當您直接在 DataRow 中修改列值時,DataRow 會使用 Current、Default 和 Original 行版本來管理列值。除這些行版本以外,BeginEdit、EndEdit 和 CancelEdit 方法還使用第四個行版本:Proposed。
在執行編輯操作(通過調用 BeginEdit 開始,并且通過使用 EndEdit 或 CancelEdit 或者通過調用AcceptChanges 或 RejectChanges 結束)的過程中,Proposed 行版本會存在。
在編輯操作過程中,您可以通過計算 DataTable 的 ColumnChanged 事件中的 ProposedValue 來將驗證邏輯應用于各列。ColumnChanged 事件保存 DataColumnChangeEventArgs,可保持對正在更改的列和ProposedValue 的引用。計算了建議值后,可以對其進行修改或取消編輯。編輯結束時,行從 Proposed 狀態中移出。
您可以通過調用 EndEdit 來確認編輯,也可以通過調用 CancelEdit 來取消編輯。請注意,盡管 EndEdit 確實已確認您所做的編輯,但在調用 AcceptChanges 之前,DataSet 并沒有實際接受更改。另外請注意,如果在EndEdit 或 CancelEdit 編輯結束之前調用 AcceptChanges,編輯將會終止,并接受 Current 和 Original 行版本的 Proposed 行值。調用 RejectChanges 會以同樣的方式結束編輯,并放棄 Current 和 Proposed 行版本。在調用 AcceptChanges 或 RejectChanges 之后調用 EndEdit 或 CancelEdit 不會起作用,因為編輯已經結束。
以下示例演示了如何將 BeginEdit 與 EndEdit 和 CancelEdit 一起使用。本示例也會檢查 ColumnChanged 事件中的 ProposedValue,并決定是否取消編輯。
DataTable workTable = new DataTable(); workTable.Columns.Add("LastName", typeof(String));
workTable.ColumnChanged += new DataColumnChangeEventHandler(OnColumnChanged);
DataRow workRow = workTable.NewRow(); workRow[0] = "Smith"; workTable.Rows.Add(workRow);
workRow.BeginEdit(); // Causes the ColumnChanged event to write a message and cancel the edit. workRow[0] = ""; workRow.EndEdit();
// Displays "Smith, New". Console.WriteLine("{0}, {1}", workRow[0], workRow.RowState);
protected static void OnColumnChanged(Object sender, DataColumnChangeEventArgs args) { if (args.Column.ColumnName == "LastName") if (args.ProposedValue.ToString() == "") { Console.WriteLine("Last Name cannot be blank. Edit canceled."); args.Row.CancelEdit(); } } |
行狀態與行版本:提供有關行的不同狀態的信息。
ADO.NET 用行狀態和版本管理表中的行。行狀態表示行的狀態。當修改行時,行版本會維護存儲于行中的值,包括當前值、原始值和默認值。例如,修改了某行中的一列后,該行會有一個 Modified 的行狀態,并且會存在兩個行版本:Current(包含當前行值)和 Original(包含修改該列前的行值)。
每個 DataRow 對象都具有 RowState 屬性,您可以檢查此屬性來確定行的當前狀態。下表給出了對各RowState 枚舉值的簡要說明。
RowState |
說明 |
Unchanged |
自上次調用 AcceptChanges 之后,或自 DataAdapter.Fill 創建了行之后,未做出過任何更改。 |
Added |
已將行添至表中,但尚未調用 AcceptChanges。 |
Modified |
已更改了行的一些元素。 |
Deleted |
已將該行從表中刪除,并且尚未調用 AcceptChanges。 |
Detached |
對于已經創建但不屬于任何 DataRowCollection 的行,設置為 Detached。新建行的 RowState設置為 Detached。通過調用 Add 方法將新的 DataRow 添至 DataRowCollection 之后,RowState 屬性的值設置為 Added。
對于已經使用 Remove 方法(或是在使用 Delete 方法之后使用了 AcceptChanges 方法)從DataRowCollection 中移除的行,也設置為 Detached。 |
在 DataSet、DataTable 或 DataRow 上調用 AcceptChanges 時,會移除行狀態為 Deleted 的所有行。剩余的行會被賦予 Unchanged 行狀態,并且 Original 行版本中的值會改寫為 Current 行版本值。調用RejectChanges 時,會移除行狀態為 Added 的所有行。剩余的行會被賦予 Unchanged 的行狀態,并且Current 行版本中的值會改寫為 Original 行版本值。
通過用列引用來傳遞 DataRowVersion 參數,您可以查看行的不同行版本,如下例所示。
DataRow custRow = custTable.Rows[0]; string custID = custRow["CustomerID", DataRowVersion.Original].ToString();
下表給出了各 DataRowVersion 枚舉值的簡要說明。
DataRowVersion |
說明 |
Current |
行的當前值。如果是有 Deleted 的 RowState 的行,則不存在此行版本。 |
Default |
特定行的默認行版本。Added、Modified 或 Unchanged 行的默認行版本是Current。Deleted 行的默認行版本是 Original。Detached 行的默認行版本是 Proposed。 |
Original |
行的原始值。如果是有 Added 的 RowState 的行,則不存在此行版本。 |
Proposed |
行的建議值。在對行進行編輯操作期間,或對于不屬于 DataRowCollection 的行,存在此行版本。 |
通過調用 HasVersion 方法并將 DataRowVersion 作為參數傳遞,您可以測試 DataRow 是否具有特定的行版本。例如,在調用 AcceptChanges 之前,DataRow.HasVersion(DataRowVersion.Original) 對新添加的行將返回 false。
例如,以下代碼示例顯示了表中所有已刪除行的值。已刪除的行沒有 Current 行版本,因此在訪問列值時必須傳遞 DataRowVersion.Original。
DataTable catTable = catDS.Tables["Categories"];
DataRow[] delRows = catTable.Select(null, null, DataViewRowState.Deleted);
Console.WriteLine("Deleted rows:/n");
foreach (DataColumn catCol in catTable.Columns) Console.Write(catCol.ColumnName + "/t"); Console.WriteLine();
foreach (DataRow delRow in delRows) { foreach (DataColumn catCol in catTable.Columns) Console.Write(delRow[catCol, DataRowVersion.Original] + "/t"); Console.WriteLine(); } |
從表中刪除行:說明如何從表中移除行。
用于從 DataTable 對象中刪除 DataRow 對象的方法有兩種:DataRowCollection 對象的 Remove 方法和DataRow 對象的 Delete 方法。Remove 方法從 DataRowCollection 中刪除 DataRow,而 Delete 方法只將行標記為刪除。當應用程序調用 AcceptChanges 方法時,才會發生實際的刪除。通過使用 Delete,您可以在實際刪除之前先以編程方式檢查哪些行標記為刪除。如果將行標記為刪除,其 RowState 屬性會設置為 Deleted。
在將 DataSet 或 DataTable 與 DataAdapter 和關系型數據源一起使用時,用 DataRow 的 Delete 方法移除行。Delete 方法只是在 DataSet 或 DataTable 中將行標記為 Deleted,而不會移除它。而 DataAdapter 在遇到標記為 Deleted 的行時,會執行其 DeleteCommand 以在數據源中刪除該行。然后,就可以用AcceptChanges 方法永久移除該行。如果使用 Remove 刪除該行,則該行將從表中完全移除,但DataAdapter 不會在數據源中刪除該行。
DataRowCollection 的 Remove 方法采用 DataRow 作為參數,并將其從集合中移除,如下例所示。
workTable.Rows.Remove(workRow);
作為對比,以下示例演示了如何調用 DataRow 上的 Delete 方法來將其 RowState 改為 Deleted。
workRow.Delete();
如果將行標記為刪除,并且調用 DataTable 對象的 AcceptChanges 方法,該行就會從 DataTable 中移除。相比之下,如果調用 RejectChanges,行的 RowState 就會恢復到被標記為 Deleted 之前的狀態。
注意 如果 DataRow 的 RowState 是 Added,則意味著已將其添至表中,然后將其標記為Deleted,從表中移除。 |
添加和讀取行錯誤信息:說明如何按行插入錯誤信息,以用于解決有關應用程序內行中數據的問題。
為了避免在編輯 DataTable 中的值時每次發生行錯誤都必須響應,可將錯誤信息添至行中,以便以后使用。DataRow 對象通過對各行提供 RowError 屬性來支持此功能。將數據添至 DataRow 的 RowError 屬性會將DataRow 的 HasErrors 屬性標記為 true。如果 DataRow 是 DataTable 的組成部分,且 DataRow.HasErrors是 true,則 DataTable.HasErrors 屬性也是 true。這也適用于 DataTable 所屬的 DataSet。為錯誤做測試時,可以檢查 HasErrors 屬性以確定錯誤信息是否已添至所有行。如果 HasErrors 為 true,則可使用 DataTable 的GetErrors 方法以便只返回和檢查有錯誤的行,如下例所示。
DataTable workTable = new DataTable("Customers"); workTable.Columns.Add("CustID", typeof(Int32)); workTable.Columns.Add("Total", typeof(Double));
workTable.RowChanged += new DataRowChangeEventHandler(OnRowChanged);
for (int i = 0; i < 10; i++) workTable.Rows.Add(new Object[] {i, i*100});
if (workTable.HasErrors) { Console.WriteLine("Errors In Table " + workTable.TableName);
foreach (DataRow myRow in workTable.GetErrors()) { Console.WriteLine("CustID = " + myRow["CustID"]); Console.WriteLine(" Error = " + myRow.RowError + "/n"); } }
protected static void OnRowChanged(Object sender, DataRowChangeEventArgs args) { // Check for zero values. if (args.Row["Total"].Equals(0D)) args.Row.RowError = "Total cannot be 0."; } |
接受或拒絕對行的更改:說明如何接受或拒絕對行的更改。
在檢驗過對 DataTable 中的數據所做更改的準確性之后,可使用 DataRow、DataTable 或 DataSet 的AcceptChanges 方法來接受更改,此方法會將 Current 行值設置為 Original 值,并會將 RowState 屬性設置為 Unchanged。接受或拒絕更改會清除所有 RowError 信息,并將 HasErrors 屬性設置為 false。接受或拒絕更改還可以影響在數據源中更新數據。有關更多信息,請參閱使用 DataAdapter 和 DataSet 更新數據庫。
如果 DataTable 上存在外鍵約束,使用 AcceptChanges 和 RejectChanges 接受或拒絕的更改就會根據ForeignKeyConstraint.AcceptRejectRule 傳播至 DataRow 的子行。
以下示例檢查有錯誤的行,在適用之處解決錯誤,拒絕無法解決錯誤的行。請注意,對于解決的錯誤,RowError值會重置為空字符串,導致將 HasErrors 屬性設置為 false。當解決或拒絕了所有的有錯誤的行時,就會調用AcceptChanges 來接受對整個 DataTable 的所有更改。
if (workTable.HasErrors) {
foreach (DataRow errRow in workTable.GetErrors()) { if (errRow.RowError == "Total cannot exceed 1000.") { errRow["Total"] = 1000; errRow.RowError = ""; // Clear the error. } else errRow.RejectChanges(); } }
workTable.AcceptChanges(); |
處理 DataTable 事件:提供可用于 DataTable 的事件的相關信息,包括修改列值和添加或刪除行時的事件。
DataTable 對象提供一系列可由應用程序處理的事件。下表說明了 DataTable 事件。
事件 |
說明 |
ColumnChanged |
在值已成功插入列時發生。 |
ColumnChanging |
在已提交列值時發生。 |
RowChanged |
在已成功編輯表中的行后發生。 |
RowChanging |
當正在更改表中的行時發生。 |
RowDeleted |
在表中的某行已被標記為 Deleted 之后發生。 |
RowDeleting |
在表中的某行被標記為 Deleted 之前發生。 |
以下示例創建 4 個事件:OnColumnChanged、OnColumnChanging、OnRowChanged 和OnRowChanging。這些事件中的每一個都在列或行更改時發生。
workTable.ColumnChanged += new DataColumnChangeEventHandler(OnColumnChanged); workTable.ColumnChanging += new DataColumnChangeEventHandler(OnColumnChanging); workTable.RowChanged += new DataRowChangeEventHandler(OnRowChanged); workTable.RowChanging += new DataRowChangeEventHandler(OnRowChanging);
protected static void OnColumnChanged(object sender, DataColumnChangeEventArgs args) { Console.Write(" ColumnChanged: "); Console.Write(args.Column.ColumnName + " changed to '" + args.ProposedValue + "'/n"); }
protected static void OnColumnChanging(object sender, DataColumnChangeEventArgs args) { Console.Write("ColumnChanging: "); Console.Write(args.Column.ColumnName + " equals '" + args.Row[args.Column] + "', changing to '" + args.ProposedValue + "'/n"); }
protected static void OnRowChanging(object sender, DataRowChangeEventArgs args) { if (args.Action != DataRowAction.Nothing) Console.WriteLine(" RowChanging: Action = " + args.Action + ", CustID = " + args.Row["CustID"]); }
protected static void OnRowChanged(object sender, DataRowChangeEventArgs args) { if (args.Action != DataRowAction.Nothing) Console.WriteLine(" RowChanged: Action = " + args.Action + ", CustID = " + args.Row["CustID"]); } |
posted on 2014-06-30 11:08
Ke 閱讀(2628)
評論(0) 編輯 收藏 所屬分類:
C#