2012-03-19 21 views
4

DataTableで作業しているときにこのバグが見つかりました。 DataTableにプライマリキー列を追加しました。そのテーブルに1つの行を追加し、その行を削除し、同じキーを持つ行をテーブルに追加しました。これは機能します。私がRejectChanges()に電話しようとしたとき、私はConstraintExceptionという値がすでに存在すると言っています。ここで は一例です:RejectChangesのDataTableスロー例外

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 

私は(行が削除された状態であるため、制約が破られていない)行が削除されているため、例外がスローされるべきではないと思います。私はこれについて何かできることはありますか?どんな助けもありがとうございます。

私が拒否されている最初は、あなたの delete動作であるので、これは、次のバグの問題よりも、同じ原因であることを前提とし

答えて

2

:経由

サイクル:

DataTable.RejectChanges() should rollback rows in reverse order

2つの回避策DataRowはそれらを逆の順序でロールバックします。新しいレコードは の前のレコードが削除されてから になります。

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

ロールバックを行うことができるので、制約を無効にします。その後の制約を再び有効にします。

  1. あなたは、LINQをツー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

これは類似していますが、逆の順序でロールバックする必要はありません。まず「削除されていない」行と削除された行の変更を拒否する必要があります。 – Vale

+0

2番目の回避策は機能します(ただし、どのように制約を無効にしますか)。たとえば、最後の行を削除したり、前の行のIDを変更したりすることができるため、最初の方法は一般的な解決策ではありません。 – Vale

+0

@Vale:私の答えを編集して、正しいロールバックオーダーを強制する方法を示しました。 –

0

これを回避するには、uniqueカラムのプロパティtor。

すなわちcolumn.Unique = true;

とすぐに、このプロパティをtrueに変更されたとして、ユニーク制約は、値が一意であることを確認するために、この列に作成されます。