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 和数据集中的更新丢失的主要内容,如果未能解决你的问题,请参考以下文章

Ado.net 断开更新整个表

在运行时将 ADO.Net DataSet 指向不同的数据库?

从 ADO.NET 类型化数据集创建 SQL 数据库

ADO.NET 执行部分更新/插入

ADO.Net 同步和 SQL CE

将 Excel 范围转换为 ADO.NET 数据集或数据表等