2010-09-16 121 views
5

评估.NET实体框架我试图找到正确的模式来处理具有乐观并发模式的并发更新。处理实体框架OptimisticConcurrencyException

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 

我看到这个

  • 下面的问题,它会自动实现后进胜利,而不是使用乐观模式
  • 它不健壮:.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 

w ^第i个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#

回答

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代码是更好的解决方案。