【问题标题】:DataTable throwing exception on RejectChangesDataTable 在 RejectChanges 上引发异常
【发布时间】:2012-03-19 09:52:25
【问题描述】:

我在使用 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

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

【问题讨论】:

    标签: c# .net-4.0 datatable


    【解决方案1】:

    我认为这与以下错误问题的原因相同,因为第一个将被拒绝的是您的 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);
      }
      

    【讨论】:

    • 这是类似的东西,但我不认为它应该以相反的顺序回滚。它应该首先拒绝对“未删除”行的更改,而不是对已删除的更改。
    • 第二种解决方法将起作用(但是如何禁用约束)。第一个不是通用解决方案,因为用户可以删除,例如,最后一行,而不是更改前一行的 id。
    • @Vale:编辑了我的答案以展示如何强制正确的回滚顺序。
    • @Vale:展示了如何临时“禁用”数据表上的约束。
    • 这是迄今为止最好的解决方案。如果没有更好的建议,我会尽快接受您的回答。
    【解决方案2】:

    您可以通过使用列 tor trueunique 属性来避免这种情况。

    column.Unique = true;

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

    【讨论】:

      猜你喜欢
      • 2016-11-28
      • 1970-01-01
      • 1970-01-01
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-24
      • 2012-04-17
      相关资源
      最近更新 更多