2010-09-16 141 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代碼是更好的解決方案。