2016-02-16 36 views
1

我想拒絕對DataTable中的DataRow上的單個DataColumn所做的更改。拒絕DataRow中單個DataColumn上的更改

我做了這個測試例子:

DataTable table = new DataTable(); 
table.Columns.Add("testColumn1"); 
table.Columns.Add("testColumn2"); 

DataRow row = table.NewRow(); 
row["testColumn1"] = "This change should be preserved"; 
row["testColumn2"] = "This change should be rejected"; 
table.Rows.Add(row); 

row.RejectChanges(); 

這將拒絕該行的所有更改。在我的情況下,用戶可能在其他列中有一些未保存的更改,因此使用此更改不適用於此場景。

我找的,只有將恢復爲「testcolumn2」的變化,例如類似的功能:

row["testColumn2"].RejectChanges(); 

我擡頭的文檔DataColumn類,但沒有找到任何類似的方法來DataRow.RejectChanges :

https://msdn.microsoft.com/en-us/library/system.data.datacolumn(v=vs.110).aspx

這是可以做到用C#框架或者我必須使用一個替代的解決方案?

備選方案也值得讚賞。

回答

1

您可以使用事件DataTable.ColumnChanging。這會在每次更改表中的DataColumn時觸發。

table.ColumnChanging += OnColumnChanging; 

OnColumnChanging檢查,列名等於我想備份列,而呼叫沒有從代碼的「恢復值」的一部分來(指布爾isRevertingChanges)的方法。

如果這兩個都是真的,它會創建一個備份列(如果它已存在,則跳過)。最後,它會將要覆蓋的值寫入行中的備份列。

private bool isRevertingChanges; 

void OnColumnChanging(object sender, DataColumnChangeEventArgs e) 
{ 
    if (!isRevertingChanges && e.Column.ColumnName.Equals(TestColumn2)) 
    { 
     if (!e.Row.Table.Columns.Contains(TestColumn2Backup)) 
      e.Row.Table.Columns.Add(TestColumn2Backup); 

     e.Row[TestColumn2Backup] = e.Row[TestColumn2]; 
    } 
} 

由於用於還原更改的標準,在這種情況下不相關的我與IF(真)代替它,因此代碼的復歸部分每次觸發。

首先它將isRevertingChanges變量設置爲true(這是爲了防止OnColumnChanging()對正在恢復的值進行備份),然後將列恢復爲其原始值,最後將isRevertingChanges設置回原來的值如此,OnColumnChanging()會在每次更改列時繼續備份值。

if (true) 
{ 
    isRevertingChanges = true; 
    row[TestColumn2] = row[TestColumn2Backup]; 
    isRevertingChanges = false; 
} 

下面是完整的源代碼:

[TestClass] 
public class RejectDataColumnChanges 
{ 
    private bool isRevertingChanges; 

    private const string TestColumn1 = "testColumn1"; 
    private const string TestColumn2 = "testColumn2"; 
    private const string TestColumn2Backup = "testColumn2Backup"; 

    private const string PreservedMessage = "This change should be preserved"; 
    private const string RejectedMessage = "This change should be rejected"; 

    [TestMethod] 
    public void RejectDataColumnChangesTest() 
    { 
     DataTable table = new DataTable("testTable1"); 
     table.Columns.Add(TestColumn1); 
     table.Columns.Add(TestColumn2); 

     DataRow row = table.NewRow(); 
     row[TestColumn1] = PreservedMessage; 
     row[TestColumn2] = PreservedMessage; 
     table.Rows.Add(row); 

     table.ColumnChanging += OnColumnChanging; 

     row[TestColumn2] = RejectedMessage; 

     Assert.AreEqual(PreservedMessage, row[TestColumn1]); 
     Assert.AreEqual(RejectedMessage, row[TestColumn2]); 
     Assert.AreEqual(PreservedMessage, row[TestColumn2Backup]); 

     if (true) 
     { 
      isRevertingChanges = true; 
      row[TestColumn2] = row[TestColumn2Backup]; 
      isRevertingChanges = false; 
     } 

     Assert.AreEqual(PreservedMessage, row[TestColumn1]); 
     Assert.AreEqual(PreservedMessage, row[TestColumn2]); 
     Assert.AreEqual(PreservedMessage, row[TestColumn2Backup]); 
    } 

    void OnColumnChanging(object sender, DataColumnChangeEventArgs e) 
    { 
     if (!isRevertingChanges && e.Column.ColumnName.Equals(TestColumn2)) 
     { 
      if (!e.Row.Table.Columns.Contains(TestColumn2Backup)) 
       e.Row.Table.Columns.Add(TestColumn2Backup); 

      e.Row[TestColumn2Backup] = e.Row[TestColumn2]; 
     } 
    } 
} 
1

在我看來,它使用的DataRowVersion列的值設置爲初始值的最簡單的解決方案:

row["testColumn2"] = row["testColumn2", DataRowVersion.Original]; 

有如果您正在使用事務批量處理某些更新,則此方法存在一個問題。假設在事務中調用Adapter.Update將更改寫入數據庫,但DB由於違反約束而拒絕它們。即使在我調用transaction.RollBack()的時候,當我要求原始版本時,我仍然得到新版本。

這就好像。網絡調用AcceptChanges而不確保事務不會被回滾。這可能需要一個單獨的問題來堆棧溢出來獲得解決方案。