处理实体框架OptimisticConcurrencyException

时间:2010-09-16 10:15:05

标签: .net entity-framework

评估.NET实体框架我尝试使用乐观并发模式找到正确的模式来处理并发更新。

documentation和其他许多地方,我看到以下模式:


Try
  ' Try to save changes, which may cause a conflict. 
  Dim num As Integer = context.SaveChanges()
  Console.WriteLine("No conflicts. " & num.ToString() & " updates saved.")
Catch generatedExceptionName As OptimisticConcurrencyException
  ' Resolve the concurrency conflict by refreshing the 
  ' object context before re-saving changes. 
  context.Refresh(RefreshMode.ClientWins, orders)

  ' Save changes. 
  context.SaveChanges()
  Console.WriteLine("OptimisticConcurrencyException handled and changes saved")
End Try

我看到了这个

的以下问题
  • 它会自动实现last-in-wins而不是使用乐观模式
  • 它不健壮:.Refresh和.SaveChanges之间的并发更改会导致新的OptimisticConcurrencyException

这是正确的,还是我错过了什么?

在UI中,我通常让用户解决并发冲突:


Try
   _ctx.SaveChanges()
Catch ex As OptimisticConcurrencyException
   MessageBox.Show("Data was modified by another User." & vbCrLf &
   "Click 'Refresh' to show the current values and reapply your changes.",
   "Concurrency Violation", MessageBoxButton.OK)
End Try

在业务逻辑中,我通常使用围绕整个业务事务(读取和更新)的重试循环:


Const maxRetries = 5, retryDelayMs = 500
For i = 1 To maxRetries
    Try
        Using ctx As New EFConcurrencyTest.ConcurrencyTestEntities
            ctx.Inventories.First.QuantityInStock += 1
            System.Threading.Thread.Sleep(3000) 'Cause conflict
            ctx.SaveChanges()
        End Using
        Exit For
    Catch ex As OptimisticConcurrencyException
        If i = maxRetries Then Throw
        System.Threading.Thread.Sleep(retryDelayMs)
    End Try
Next

使用EF我打算封装循环:


ExecuteOptimisticSubmitChanges(Of EFConcurrencyTest.ConcurrencyTestEntities)(
    Sub(ctx)
        ctx.Inventories.First.QuantityInStock += 1
        System.Threading.Thread.Sleep(3000) 'Cause conflict
    End Sub)

见:

Functional Optimistic Concurrency in C#

Retryable actions in C#

1 个答案:

答案 0 :(得分:6)

此:

Catch ex As OptimisticConcurrencyException
  ' Resolve the concurrency conflict by refreshing the 
  ' object context before re-saving changes. 
  context.Refresh(RefreshMode.ClientWins, orders)

  ' Save changes. 
  context.SaveChanges()
  Console.WriteLine("OptimisticConcurrencyException handled and changes saved")

......完全没有意义。如果你“处理”异常时唯一要做的就是忽略它并保存,你应该只关闭乐观并发;您正在编写代码来解决可选功能。

所以,是的,我说文档在这里没有给你很好的建议。

您建议的UI代码是更好的解决方案。