拒绝对数据行中单个数据列的更改

本文关键字:数据 拒绝 单个 | 更新日期: 2023-09-27 18:35:02

我想拒绝对数据表中数据行上的单个数据列所做的更改。

我做了这个测试示例:

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# 框架,或者我是否必须使用替代解决方案?

替代解决方案也受到赞赏。

拒绝对数据行中单个数据列的更改

在我看来

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

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

如果使用事务将某些更新批处理在一起,则此方法存在一个问题。 假设在事务中,您调用 Adapter.Update 以将更改写入数据库,但由于违反约束,数据库拒绝了这些更改。 即使我调用交易。回滚(( 当我要求原始版本时,我仍然得到新版本。

就好像.Net调用AcceptChanges而不确保事务不会回滚一样。 这可能需要向堆栈溢出提出单独的问题才能获得解决方案。

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

table.ColumnChanging += OnColumnChanging;

方法OnColumnChange检查列名是否等于我要备份的列,并且调用不是来自代码的"还原值"部分(请参阅布尔值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(这是为了防止 OnColumnChange(( 备份正在还原的值(,然后将列恢复为其原始值,最后它将 isRevertingChanges 设置回 false,因此每次列更改时 OnColumnChange(( 将继续备份值。

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