Oftentimes we encounter problems when we perform update using LoadDataRow or rollback data using RejectChanges after the Delete method. Why do the methods sometimes not do what we want?
Googling a solution for LoadDataRow, we may find that most people resolve the update performed by LoadDataRow must call DataTable.AcceptChanges first. Does this solution work for you 100%? There are still some unresolved posts left unanswered. They follow the solution to call AcceptChanges but the problem still exists. Why?
Deleting a DataRow and then immediately performing RejectAccepts to rollback cause us to receive System.Data.RowNotInTableException. What is it going on? Is the DataRow marked as Deleted? Why can't I rollback?
The above problems are related to either the RowState of a DataRow or if we set up the constraints on DataTable correctly.Assuming there is no constraint problem, the DataRow must be either Unchanged or Modified when we perform an update using the LoadDataRow method on an existing DataRow. The same principle applies to the RejectChanges after calling the Delete method. Apparently, the operations requires an Original version existed for the DataRow. When the RowState of DataRow is Unchanged or Modified, an Original version of the DataRow has been created/existed. Thus, any operations after it won't cause a problem.
If you receive a System.Data.ConstraintException in regard to System.Data.UniqueConstraint.CheckConstraint, please ensure the primary key set up properly. Most likely, setting the Unique property of a DataColumn without primary key to true will cause this problem to occur.
If you receive a System.Data.ConstraintException in regard to System.Data.DataTable.EnableConstraints, please ensure an Original version existed for the DataRow. It means the RowState of the DataRow is still in the state of Added and you need to commit changes first by calling the AcceptChanges method to update the state to Unchanged.
Similarly, if you receive a System.Data.RowNotInTableException when you try to roll back the DataRow after having called the Delete method, a AcceptChanges call is required before the Delete method. After AcceptChanges, an Original version of the DataRow is created and the RowState of the DataRow is set to Unchanged. From this state onwards, any modification including the LoadDataRow method, or calling the Delete method and then the RejectChanges method can be performed.
To sum up what the RowState means is described in the following table.Detached | The DataRow is created but it hasn't been added to a DataTable yet. Since it does not exist in a DataTable, no operations can be performed at the DataTable level. |
---|---|
Added | The DataRow is added to a DataTable but the DataTable has not accepted changes yet. At this stage, it requires AcceptChanges to create Original version for other update operations including rollback. |
Unchanged | The DataRow has not changed since the last AcceptChanges call. At this stage, an Original version of the DataRow has already existed. Thus, any operations can be performed without a problem. |
Modified | The DataRow has been modified since the last AcceptChanges call. Like Unchanged, an Original version of the DataRow has already existed in this stage. A DataRow with Modified row state can continously be modified but the RejectChanges will only roll the data back to the last AcceptChanges call. Any modification made in between is disgarded because the Original version of the DataRow is only pointing the copy when the last AcceptChanges is called. |
Deleted | The DataRow was deleted by using the Delete method of the DataRow only when the RowState of the DataRow is Unchanged or Modified. |
I also attach some test results I conducted for reference.
- LoadDataRow and ConstraintException [ LoadOption | AcceptChanges ]
- About DataRow.Delete, .AcceptChanges and .RejectChanges