2011-10-26 50 views
3

我有一个类User的两个实例。这些对象中的每一个都有自己的DataSet,SQLiteConnection,SQLiteDataAdapter等。我试图模拟学校工作中的“丢失更新”异常。ADO.NET和数据集丢失更新

数据库表如下所示:

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; 
} 
+0

如果你想“模拟丢失更新异常”,那么你已经实现了它。基本上丢失更新意味着多个“事物”(实体,对象等)试图更新相同的单个项目(在本例中为数据库行)。该项目的最后更新是设置的。所以在你的情况下,Salary是15,而不是17,因为第二个'User'对象是最后一个执行更新。不知道这是否解释了你要求的内容? –

+0

@JasonEvans谢谢。是的,我想我已经达到了异常。但现在我必须证明我可以如何阻止这种情况发生和/或处理代码情况。 –

+0

嗯,不确定是诚实的,因为你期待使用交易。也许你需要重新设计你的代码,以便只有一个对象可以更新数据库?如果这是不可接受的,那么你需要研究ADO.NET的'悲观锁定'策略。对不起,我不能有更多的帮助。 –

回答

0

您可以使用乐观并发。指定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; 
... 

调用更新后,检查有多少记录受到影响;如果没有,那么这是一个丢失更新