I found this bug while working with a DataTable.
I added a primary key column to a DataTable, than added one row to that table, removed that row, and added row with the same key to the table. This works. When I tried to call RejectChanges()
on it, I got ConstraintException
saying that value is already present.
Here is the example:
var dataTable = new DataTable();
var column = new DataColumn("ID", typeof(decimal));
dataTable.Columns.Add(column);
dataTable.PrimaryKey = new [] {column };
decimal id = 1;
var oldRow = dataTable.NewRow();
oldRow[column] = id;
dataTable.Rows.Add(oldRow);
dataTable.AcceptChanges();
oldRow.Delete();
var newRow = dataTable.NewRow();
newRow[column] = id;
dataTable.Rows.Add(newRow);
dataTable.RejectChanges(); // This is where it crashes
I think since the row is deleted, exception should not be thrown (constraint is not violated because row is in deleted state). Is there something I can do about this? Any help is appreciated.
I assume that this has the same cause than following bug issue since the first that will be rejected is your delete
action:
DataTable.RejectChanges() should rollback rows in reverse order
Two possible workarounds:
Cycles through the DataRows rolling them back in reverse order. So the new records are removed before the previous ones are brought back to life.
DataRowCollection rows = dataTable.Rows;
for (int i = rows.Count - 1; i >= 0; i--)
{
rows[i].RejectChanges();
}
Disables constrains so the rollback can be done. Reenables constrains after that.
You could use LINQ-to-DataSet to define your own "rollback-order":
var rollbackPlan = (from r in dataTable.AsEnumerable()
where r.RowState != DataRowState.Unchanged
let firstOrder = r.RowState==DataRowState.Deleted? 1 : 0
let secondOrder = r.RowState==DataRowState.Added? 1 : 0
orderby firstOrder ascending, secondOrder ascending
select r).ToList();
foreach (DataRow r in rollbackPlan)
{
r.RejectChanges(); // Does not crash anymore
}
Here's the way you "disable" constraints on a DataTable
temporarily:
var constraintBackup = dataTable.Constraints.Cast<System.Data.Constraint>().ToList();
dataTable.Constraints.Clear();
dataTable.RejectChanges(); // Does not crash anymore
foreach (System.Data.Constraint c in constraintBackup)
{
dataTable.Constraints.Add(c);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With