在RejectChanges数据表引发异常数据表、异常、RejectChanges

2023-09-07 13:11:04 作者:野味小生

我发现这个bug,同时与一个DataTable的工作。 我添加了一个主键列到DataTable,比添加一行到该表,删除该行,并添加行具有相同的键表。这个工程。当我试图打电话 RejectChanges()就可以了,我得到了 ConstraintException 说值已经是present。 下面是例子:

  VAR的dataTable =新的DataTable();
    VAR列=新的DataColumn(ID的typeof(十进制));
    dataTable.Columns.Add(列);
    dataTable.PrimaryKey =新的[] {列};

    小数的id = 1;

    变种oldRow = dataTable.NewRow();
    oldRow [专栏] = ID;

    dataTable.Rows.Add(oldRow);
    dataTable.AcceptChanges();

    oldRow.Delete();

    变种NEWROW = dataTable.NewRow();
    NEWROW [专栏] = ID;

    dataTable.Rows.Add(NEWROW);
    dataTable.RejectChanges(); //这是它崩溃
 

我觉得既然该行被删除,异常不应随意(约束没有被破坏,因为排在被删除状态)。有什么我能做些什么呢?任何帮助是AP preciated。

解决方案

我认为这有相同的原因不是因为第一个将被拒绝是以下错误的问题你的删除的行动:

DataTable.RejectChanges()应该回滚以相反的顺序排

有两种可能的解决方法:

  

通过数据行循环滚动回以相反的顺序。因此,   新的记录被删除了previous的人被带到前回   生活。

  DataRowCollection行= dataTable.Rows;
的for(int i = rows.Count  -  1; I> = 0;我 - )
{
    行[I] .RejectChanges();
}
 
GIT push of current branch was rejected remote changes need to be merged before pushing

禁用限制,以便回滚可以做到的。在那之后重新启用限制。

您可以使用LINQ到数据集定义自己的回退阶:

  VAR rollbackPlan =(从研发中dataTable.AsEnumerable()
               其中,r.RowState!= DataRowState.Unchanged
               让我们一阶= r.RowState == DataRowState.Deleted? 1:0
               让二阶= r.RowState == DataRowState.Added? 1:0
               排序依据一阶上升,二阶上升
               选择R).ToList();
的foreach(在rollbackPlan的DataRow R)
{
    r.RejectChanges(); //不会崩溃了
}
 

下面是你禁用约束的方式数据表暂时

  VAR constraintBackup = dataTable.Constraints.Cast< System.Data.Constraint>()了ToList()。
dataTable.Constraints.Clear();
dataTable.RejectChanges(); //不会崩溃了
的foreach(在constraintBackup System.Data.Constraint C)
{
    dataTable.Constraints.Add(C);
}
 

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);
}