【问题标题】:Reject changes on a single DataColumn in a DataRow拒绝对 DataRow 中单个 DataColumn 的更改
【发布时间】:2016-05-27 20:22:57
【问题描述】:

我想拒绝对 DataTable 中 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# 框架有关还是我必须使用替代解决方案?

其他解决方案也值得赞赏。

【问题讨论】:

    标签: c# .net datatable datarow datacolumn


    【解决方案1】:

    在我看来,最简单的解决方案是使用 DataRowVersion 将列的值设置为其原始值:

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

    如果您使用事务将一些更新批处理在一起,则此方法存在一个问题。假设在事务中调用 Adapter.Update 将更改写入 DB,但 DB 由于违反约束而拒绝它们。即使当我调用 transaction.RollBack() 时,当我要求原始版本时,我仍然会得到新版本。

    就好像 .Net 调用 AcceptChanges 时没有确保事务不会回滚。这可能需要向 Stack Overflow 提出单独的问题才能获得解决方案。

    【讨论】:

      【解决方案2】:

      您可以使用事件 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(true),因此每次都会触发代码的恢复部分。

      首先它将 isRevertingChanges 变量设置为 true(这是为了防止 OnColumnChanging() 对正在恢复的值进行备份),然后将列恢复为其原始值,最后将 isRevertingChanges 设置回 false所以 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];
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-05-12
        • 1970-01-01
        • 1970-01-01
        • 2012-05-19
        • 1970-01-01
        • 1970-01-01
        • 2015-12-24
        • 1970-01-01
        相关资源
        最近更新 更多