ADO.NET 和数据集中的更新丢失
Posted
技术标签:
【中文标题】ADO.NET 和数据集中的更新丢失【英文标题】:Lost Update in ADO.NET and DataSets 【发布时间】:2011-12-15 17:46:57 【问题描述】:我有一个名为User
的类的两个实例。这些对象中的每一个都有自己的 DataSet、SQLiteConnection、SQLiteDataAdapter 等。我试图在此处模拟“丢失更新”异常以用于学校作业。
数据库表如下所示:
ID Name Salary
---------------------
1 John 10
数据集在构造User
对象时填充。这些对象中的每一个都更新同一行。第一个对象将行 ID 1 的薪水增加 2,结果为 12。第二个对象也将薪水增加 5,结果为 15,但我们预计为 17,或者至少是一个异常,因此回滚事务。但也不例外。我做错了什么?
这是我在 User
类中的更新代码
public bool IncreaseSalary(int raise)
int currentSalary = Convert.ToInt32(_dataSet.Tables["Employees"].
Rows[0]["Salary"]);
_dataSet.Tables["Employees"].Rows[0]["Salary"] = currentSalary + raise;
_connection.Open();
SQLiteTransaction transaction = _connection.BeginTransaction();
_employeesDataAdapter.SelectCommand.Transaction = transaction;
_employeesDataAdapter.UpdateCommand.Transaction = transaction;
_employeesDataAdapter.DeleteCommand.Transaction = transaction;
_employeesDataAdapter.InsertCommand.Transaction = transaction;
int result = _employeesDataAdapter.Update(_dataSet);
transaction.Commit();
_dataSet.Clear();
_employeesDataAdapter.Fill(_dataSet);
return result > 0;
【问题讨论】:
如果您尝试“模拟丢失更新异常”,那么您已经实现了。基本上丢失更新意味着多个“事物”(实体、对象等)正在尝试更新同一个项目(在这种情况下是数据库行)。该项目的最后更新是已设置的更新。因此,在您的情况下,Salary 是 15,而不是 17,因为第二个User
对象是最后一个执行更新的对象。不确定这是否解释了您的要求?
@JasonEvans 谢谢。是的,我想我已经实现了异常。但现在我必须演示如何阻止这种情况发生和/或在代码中处理这种情况。
嗯,说实话,你看起来正在使用事务。也许您需要重新设计您的代码,以便只有一个对象可以更新数据库?如果这不可接受,那么您需要查看 ADO.NET 的 Pessimistic Locking
策略。抱歉,我无法提供更多帮助。
【参考方案1】:
您可以使用乐观并发。指定要使用的 UpdateCommand,您可以在其中检查原始值,以防它们已被其他人更改。一个例子:
...
myAdapter.UpdateCommand = new SQLiteCommand("UPDATE Dept SET DeptNo = :DeptNo, DName = :DName WHERE DeptNo = :oldDeptNo", sqConnection);
myAdapter.UpdateCommand.Parameters.Add("DeptNo", SQLiteType.Int32, 0, "DeptNo");
myAdapter.UpdateCommand.Parameters.Add("oldDeptNo", SQLiteType.Int32, 0, "DeptNo").SourceVersion = DataRowVersion.Original;
...
调用更新后,检查有多少条记录受到影响;如果没有,那么它是一个丢失的更新。
【讨论】:
以上是关于ADO.NET 和数据集中的更新丢失的主要内容,如果未能解决你的问题,请参考以下文章