DataSet AcceptChanges() and RejectChanges() Methods
To understand AcceptChanges() and RejectChanges() methods better, we need to understand the Row States and Row Versions. Datasets consist of DataTables, and each row of a DataTable is called a DataRow. Each DataRow has a RowState property. The following are the different Row States:
- Unchanged: When we call DataAdapter.Fill() method, data is loaded into the DataSet, and the RowState of all the rows will be unchanged.
- Modified: When we edit a row, the row state becomes modified.
- Deleted: If we delete a row, the row state becomes deleted.
At this point, if we invoke DataAdapter.Update() method, the respective INSERT, UPDATE, and DELETE commands are executed against the underlying database table, and AcceptChanges() is called automatically, based on the RowState.
When AcceptChanges() method is invoked, the RowState property of each DataRow changes, the newly added and updated or modified rows become unchanged, and the deleted rows are removed. For the Dataset, it is as if nothing has happened since it was last loaded, so no changes will be committed to the database when calling the Update() method.
When the RejectChanges() method of DataAdapter is invoked, RowState property of each DataRow of DataTable of DataSet changes. All the added rows are removed. All the modified and deleted rows become unchanged. Thus, it rejects all changes made to the DataSet since the last time it was loaded or since the AcceptChanges() method was last called.
We can invoke the AcceptChanges() and RejectChanges() at multiple levels as shown below:
- At the DataSet level - When AcceptChanges() method is invoked at the DataSet level, they get called automatically on each DataTable within the DataSet, and on each DataRow within each DataTable.
- At the DataTable level - When the AcceptChanges() method is invoked at the DataTable level, they get called automatically on each DataRow within each DataTable.
- At the DataRow level - Here, the AcceptChanges() method gets called only for the row, on which it is invoked.
DataSet ds = new DataSet();
// create a table with a single column
DataTable dt = ds.Tables.Add();
dt.Columns.Add("MyColumn", typeof(System.Int32));
DataRow row;
row = dt.NewRow();
row["MyColumn"] = 1;
dt.Rows.Add(row); // RowState = Added
ds.AcceptChanges(); // RowState = Unchanged
row["MyColumn"] = 2; // RowState = Modified
ds.RejectChanges(); // RowState = Unchanged, row["MyColumn"] = 1
row.Delete(); // RowState = Deleted
ds.RejectChanges(); // RowState = Unchanged
// The row isn't removed from the DataTable.
Don't get confused with AcceptChanges() and RejectChanges() methods. From a database perspective, both are the same; if we call the AcceptChanges() method, the Row State remains unchanged, so the DataAdapter doesn't fire any SQL command on the database. As a result, nothing gets committed to the database .
When we use RejectChanges() method, all changes made to the DataSet since it was last loaded rolls back. So, the dataset comes to its previous state. At this moment, when we call DataAdapter's Update() method, nothing is going to change in the database.