This is the sample code copied from
MSDN.
1 private void DemonstrateRowBeginEdit()
2 {
3 DataTable table = new DataTable("table1");
4 DataColumn column =
new 5 DataColumn("col1",Type.GetType("System.Int32"));
6 table.RowChanged+=
new 7 DataRowChangeEventHandler(Row_Changed);
8 table.Columns.Add(column);
9
10 // Add a UniqueConstraint to the table. 11 table.Constraints.Add(new UniqueConstraint(column));
12 13 // Add five rows.
14 DataRow newRow;
15
16 for(
int i = 0;i<5; i++)
17 {
18 // RowChanged event will occur for every addition. 19 newRow= table.NewRow();
20 newRow[0]= i;
21 table.Rows.Add(newRow);
22 }
23 // AcceptChanges.
24 table.AcceptChanges();
25
26 // Invoke BeginEdit on each. 27 Console.WriteLine(
28 "\n Begin Edit and print original and proposed values \n");
29 foreach(DataRow row in table.Rows)
30 {
31
32 row.BeginEdit();
33 row[0]=(int) row[0]+10;
34 Console.Write(
"\table Original \table" +
35 row[0, DataRowVersion.Original]);
36 Console.Write(
"\table Proposed \table" +
37 row[0,DataRowVersion.Proposed] + "\n");
38 }
39 Console.WriteLine("\n");
40 // Accept changes 41 table.AcceptChanges();
42 // Change two rows to identical values after invoking BeginEdit. 43 table.Rows[0].BeginEdit();
44 table.Rows[1].BeginEdit();
45 table.Rows[0][0]= 100;
46 table.Rows[1][0]=100;
47 try
48 {
49 /* Now invoke EndEdit. This will cause the UniqueConstraint
50 to be enforced.*/ 51 table.Rows[0].EndEdit();
52 table.Rows[1].EndEdit();
53 }
54 catch(
Exception e)
55 {
56 // Process exception and return. 57 Console.WriteLine("Exception of type {0} occurred.",
58 e.GetType());
59 }
60 }
61
62 private void Row_Changed(
object sender,
63 System.Data.DataRowChangeEventArgs e)
64 {
65 DataTable table = (DataTable) sender;
66 Console.WriteLine(
"RowChanged " + e.Action.ToString()
67 + "\table" + e.Row.ItemArray[0]);
68 }
The followings are the event sequences I have observed when executing
DemonstrateRowBeginEdit method.
- When line 21 is executed, for each row added, 1 RowChanged event is fired and 'Change' is passed as DataRowChangeEventArgs.Action argument.
- When line 24 is executed, for each row added, 1 RowChanged event is fired and 'Commit' is passed as DataRowChangeEventArgs.Action argument.
- When line 41 is executed, for each row modified, 2 RowChanged events are fired and 'Change' and 'Commit' are passed as DataRowChangeEventArgs.Action argument separately.
- When line 51 is executed, 1 RowChanged event is fired and 'Change' is passed as DataRowChangeEventArgs.Action argument.
- When line 52 is executed, System.Data.ConstraintException is thrown.
Some other behaviors are observed after the code is modified.
- If line 32 is commented out, System.Data.VersionNotFoundException is thrown at line 36 for 'There is no Proposed data to access'.
- If line 32 and line 36 are commented out, when line 33 is executed, 1 RowChanged event is fired and 'Change' is passed as DataRowChangeEventArgs.Action argument. And when line 41 is executed, for each row modified, 1 RowChanged event is fired and 'Commit' is passed as DataRowChangeEventArgs.Action argument.
- If "Console.WriteLine(table.Rows[0][0]);" is inserted before line 51, default version of the data is accessed(via Reflector) and "100" is printed.
- If "Console.WriteLine(table.Rows[0][0, DataRowVersion.Current]);" is inserted before line 51, "10" is printed.
- If "Console.WriteLine(table.Rows[0][0, DataRowVersion.Current]);" is inserted after line 51, "100" is printed.
- If "Console.WriteLine(table.Rows[0][0, DataRowVersion.Original]);" is inserted after line 51, "10" is printed.
- If "table.Rows[0].AcceptChanges(); Console.WriteLine(table.Rows[0][0, DataRowVersion.Original]);" is inserted after line 51, "100" is printed.
The experiment confirms the following DataRow behaviors:
- DataRow.BeginEdit method temporarily suspends events.
- DataRow.EndEdit method invokes 1 RowChanged event.
- DataTable.AcceptChanges method invokes 2 RowChanged events for each row modified.
- The default version of DataRow is updated after DataRow.EndEdit method is called.
- The original version of DataRow is updated after DataRow.AcceptChanges method is called.
So why should I care about BeginEdit method? Without calling BeginEdit method, for each column in a row I modify, one RowChanged event is fired. If 10 columns per row are modified, 10 RowChanged events are fired for every modified row.
If the DataTable is updated by a background thread, and is attached to a data-bound control, say, DataGridView, which is controlled by a UI thread. Those updates would cause too many events fired and might result in some weird behaviors of that data-bound control. DataRow.BeginEdit method allows us to suspend events temporarily. After completing modification, we call
EndEdit or
AcceptChanges method to notify that data-bound control to update changes.
Note: To update a data object bounded to a UI control from a background thread, be sure to read the article first.