DataTable在RejectChanges上抛出异常

时间:2012-03-19 09:52:25

标签: c# .net-4.0 datatable

我在使用DataTable时发现了这个错误。 我向DataTable添加了一个主键列,而不是向该表添加了一行,删除了该行,并向表中添加了具有相同键的行。这有效。当我尝试在其上调用RejectChanges()时,我ConstraintException说该值已经存在。 这是一个例子:

    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

我认为由于删除了行,因此不应抛出异常(因为行处于删除状态,所以不会违反约束)。我可以做些什么吗?任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:3)

我认为这与导致错误问题的原因相同,因为第一个将被拒绝的是您的delete操作:

DataTable.RejectChanges() should rollback rows in reverse order

两种可能的解决方法:

  

循环通过DataRows以相反的顺序回滚它们。所以   新记录在之前的记录被删除之前被删除   寿命。

DataRowCollection rows = dataTable.Rows;
for (int i = rows.Count - 1; i >= 0; i--)
{
    rows[i].RejectChanges();
}

禁用约束,以便可以完成回滚。在此之后,重新启用会受到限制。

  1. 您可以使用LINQ-to-DataSet定义自己的"回滚顺序":

    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
    }
    
  2. 以下是您"禁用"的方式对DataTable暂时的约束:

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

答案 1 :(得分:0)

您可以使用列unique列的true属性来避免这种情况。

即。 column.Unique = true;

只要此属性更改为true,就会在此列上创建唯一约束,以确保值是唯一的。