拒绝DataRow中单个DataColumn的更改

时间:2016-02-16 13:58:11

标签: c# .net datatable datarow datacolumn

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

也赞赏其他解决方案。

2 个答案:

答案 0 :(得分:2)

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

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

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

就好像.Net调用AcceptChanges而不确保事务不会被回滚。这可能需要一个单独的问题来Stack Overflow来获得解决方案。

答案 1 :(得分:1)

您可以使用事件DataTable.ColumnChanging。每次对表中的DataColumn进行更改时都会触发此操作。

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];
    }
}

OnColumnChanging方法检查列名是否等于我要备份的列,并且该调用不是来自代码的“revert value”部分(请参阅boolean isRevertingChanges)。

如果这两个都为真,则会创建一个备份列(如果已存在则跳过此列)。最后,它将要覆盖的值写入行的备份列。

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

由于在这种情况下恢复更改的标准无关紧要,我已将其替换为if(true),因此每次都会触发代码的恢复部分。

首先它将isRevertingChanges变量设置为true(这是为了防止OnColumnChanging()对正在恢复的值进行备份),然后将列恢复为原始值,最后将isRevertingChanges设置为false所以每次列更改时,OnColumnChanging()都会继续备份值。

[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];
        }
    }
}

以下是完整的源代码:

toString()