The operation and rollback of DataTable are often required for WPF projects. TransactionScope is not applicable because the operation exists in multiple windows and methods.
So we thought of the Merge operation of DataTable.
1): first create a DataTable for testing
1 static DataTable CreateTestTable ()
2 {
3 var dt = new DataTable ();
4 var dc = new DataColumn ("ID", typeof (int ));
5 dt. Columns. Add (dc );
6 dt. PrimaryKey = new DataColumn [] {dc };
7 for (var I = 0; I <10; I ++)
8 {
9 var dr = dt. NewRow ();
10 dr [dc] = I;
Dt. Rows. Add (dr );
11}
12 return dt;
13}
Apparently, when all DataRow is inserted, RowState is Added
Because rollback is not suitable for operations on the original able, it is decided to create a deep copy of The DataTable.
2): create a deep copy of The DataTable
1 static DataTable CreateDeepCopyOfDataTable (DataTable oldTable)
2 {
3 var MS = new MemoryStream ();
4 BinaryFormatter bf = new BinaryFormatter ();
5 bf. Serialize (MS, oldTable );
6 ms. Seek (0, SeekOrigin. Begin );
7 var newTable = bf. Deserialize (MS) as DataTable;
8 ms. Close ();
9 return newTable;
10}
We create a Copy of the original data.
All operations work on the newly generated able,
Now, you don't have to consider the rollback problem because the new table has nothing to do with the old table.
Merge can be used when we want to save the operation. (If the table does not have a primary key, this method will not work)
Let's take a look at the changes in RowState during row merging (tested by ourselves)
Original table RowState OldTable |
Copy RowState NewTable |
Merged oldTable RowState OldTable. Merge (newTable ); |
Added |
Added, Modified, UnChanged |
Added |
Added |
Deleted |
Deleted |
Modified |
Added, Modified, UnChanged |
Modified |
Modified |
Deleted |
Deleted |
UnChanged |
Added, Modified, UnChanged |
Modified |
UnChanged |
Deleted |
Deleted |
The problem is that when we Delete (Row. Delete ();) a Row in the DataTable, if the original status of this Row is
When Added is used, its status changes to Detached, indicating that this row has been deleted from DataTable. Rows, which is equivalent
DataTable. Rows. Remove (row );
DataRow. Delete () only changes the RowState of DataRow.
DataRow is not removed from the Rows set of the DataTable.
In this case, if the row in the original table is Added, and the row in the copied table is deleted, the RowState of the row is
It will become Detached. When merged, this row in the original table cannot find any matching primary key,
Therefore, no release changes will occur, resulting in incorrect data after the merger.
The solution is very simple. When the copied table executes Row. Delete, set its RowState to UnChanged. (call the AcceptChagnes method)
Then execute Row. Delete ();
This article does not provide a good way to implement DataTable rollback, but analyzes the DataRow operation,
Its RowState changes.