拒绝对 DataRow 中单个 DataColumn 的更改
Reject changes on a single DataColumn in a DataRow
我想拒绝对 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 class 的文档,但找不到任何与 DataRow.RejectChanges 类似的方法:
https://msdn.microsoft.com/en-us/library/system.data.datacolumn(v=vs.110).aspx
这可能与 C# 框架有关,还是我必须使用替代解决方案?
也欢迎其他解决方案。
您可以使用事件 DataTable.ColumnChanging。每次对 table.
中的 DataColumn 进行更改时都会触发此事件
table.ColumnChanging += OnColumnChanging;
OnColumnChanging 方法检查列名是否等于我要备份的列,并且调用不是来自代码的 "revert value" 部分(请参阅布尔值 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];
}
}
}
在我看来,最简单的解决方案是使用 DataRowVersion 将列的值设置为其原始值:
row["testColumn2"] = row["testColumn2", DataRowVersion.Original];
如果您使用事务将一些更新批处理在一起,则此方法存在一个问题。假设在您调用 Adapter.Update 的事务中将更改写入数据库,但数据库由于违反约束而拒绝了它们。即使当我调用 transaction.RollBack() 时,当我要求原始版本时,我仍然会得到新版本。
就好像 .Net 调用 AcceptChanges 时并没有确保事务不会被回滚。这可能需要向 Stack Overflow 提出单独的问题才能获得解决方案。
我想拒绝对 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 class 的文档,但找不到任何与 DataRow.RejectChanges 类似的方法:
https://msdn.microsoft.com/en-us/library/system.data.datacolumn(v=vs.110).aspx
这可能与 C# 框架有关,还是我必须使用替代解决方案?
也欢迎其他解决方案。
您可以使用事件 DataTable.ColumnChanging。每次对 table.
中的 DataColumn 进行更改时都会触发此事件table.ColumnChanging += OnColumnChanging;
OnColumnChanging 方法检查列名是否等于我要备份的列,并且调用不是来自代码的 "revert value" 部分(请参阅布尔值 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];
}
}
}
在我看来,最简单的解决方案是使用 DataRowVersion 将列的值设置为其原始值:
row["testColumn2"] = row["testColumn2", DataRowVersion.Original];
如果您使用事务将一些更新批处理在一起,则此方法存在一个问题。假设在您调用 Adapter.Update 的事务中将更改写入数据库,但数据库由于违反约束而拒绝了它们。即使当我调用 transaction.RollBack() 时,当我要求原始版本时,我仍然会得到新版本。
就好像 .Net 调用 AcceptChanges 时并没有确保事务不会被回滚。这可能需要向 Stack Overflow 提出单独的问题才能获得解决方案。