2012-03-19 94 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,唯一約束將在此列上創建,以確保值是唯一的。