处理实体框架OptimisticConcurrencyException实体、框架、OptimisticConcurrencyException

2023-09-05 00:12:08 作者:潇洒↘过头ぃ

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

Evaluating the .NET Entity Framework I try to find the right patterns to handle concurrent updates with optimistic concurrency mode.

在文档和其他许多地方我看到了下面的模式

In the documentation and many other places I see the following pattern:



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

我看到下面的问题,这

I see the following problems with this

自动实现后进胜利,而不是使用乐观模式 这是不健壮:.REFRESH和.SaveChanges之间的并发变化可能会造成新的OptimisticConcurrencyException

这是正确的,还是我失去了一些东西?

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

In a UI I normally let the user resolve the concurrency conflict:



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

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

In business logic I normally use a retry loop around the whole business transaction (reading and updating):



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我打算封装循环:

With EF I plan to encapsulate the loop:



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

请参阅:

功能乐观并发C#

在C#可重试动作

推荐答案

本:

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")

...是完全没有意义的。如果你这样做,当你处理唯一的例外是忽略它和保存,无论如何,你应该只把乐观并发关闭;你写code,以解决一个可选功能。

...is completely pointless. If the only thing you do when you "handle" the exception is to ignore it and save anyway, you should just turn optimistic concurrency off; you're writing code to work around an optional feature.

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

So, yes, I'd say the documentation is not giving you good advice here.

您提出的UI code是一个更好的解决方案。

Your proposed UI code is a better solution.