2012-03-19 89 views
4

我在使用DataTable时发现了这个错误。 我向DataTable添加了主键列,而不是向该表中添加了一行,删除了该行,并向表中添加了具有相同键的行。这工作。当我试图打电话给RejectChanges()时,我得到ConstraintException表示价值已经存在。 这里是例子:DataTable在RejectChanges上抛出异常

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

我认为这具有相同的原因不是因为:第一,将被拒绝下列错误的问题是你的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到数据集定义自己的“回滚序”:

    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

这是类似的东西,但我不认为它应该以相反的顺序回滚。它应该首先拒绝“未删除”行上的更改,而不是删除。 – Vale 2012-03-19 10:05:01

+0

第二个解决方法将起作用(但您如何禁用约束)。首先不是一个通用的解决方案,因为用户可以删除最后一行,而不是更改前一行的id。 – Vale 2012-03-19 10:21:01

+0

@Vale:编辑我的答案,显示如何强制执行正确的回滚顺序。 – 2012-03-19 10:23:05

0

您可以通过使用unique栏的属性true

column.Unique = true;

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