处理实体框架OptimisticConcurrencyException [英] Handle Entity Framework OptimisticConcurrencyException

查看:148
本文介绍了处理实体框架OptimisticConcurrencyException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



文档和许多其他地方我看到以下模式:

 

尝试
'尝试保存更改,这可能会导致冲突。
Dim num As Integer = context.SaveChanges()
Console.WriteLine(No conflict。&num.ToString()&updates saved。)
Catch generatedExceptionName作为OptimisticConcurrencyException
'在重新保存更改之前,通过刷新
'对象上下文来解决并发冲突。
context.Refresh(RefreshMode.ClientWins,orders)

'保存更改。
context.SaveChanges()
Console.WriteLine(OptimisticConcurrencyException处理和更改保存)
结束尝试


我看到以下问题:




  • 它会自动实现最后的胜利,而不是使用乐观模式

  • 它不健壮:.Refresh和.SaveChanges之间的并发更改可能导致新的OptimisticConcurrencyException



这是正确的还是我缺少某些东西?



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

 

尝试
_ctx.SaveChanges()
Catch ex As OptimisticConcurrencyException
MessageBox.Show(Data被另一个用户修改。&vbCrLf&
点击刷新显示当前值并重新应用您的更改。,
并发违规,MessageBoxButton.OK)
结束尝试



在商务ss逻辑我通常在整个业务交易(阅读和更新)周围使用重试循环:

 

Const maxRetries = 5, retryDelayMs = 500
对于i = 1 To maxRetries
尝试
使用ctx作为新的EFConcurrencyTest.ConcurrencyTestEntities
ctx.Inventories.First.QuantityInStock + = 1
System.Threading .Thread.Sleep(3000)'原因冲突
ctx.SaveChanges()
结束使用
退出
Catch ex As OptimisticConcurrencyException
如果i = maxRetries然后抛出
System.Threading.Thread.Sleep(retryDelayMs)
结束尝试
下一个



使用EF我打算封装循环:

 

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



请参阅:

rel =nofollow noreferrer> C#中的功能乐观并发性



C#中的可重试操作

解决方案

这样:

  Catch ex As OptimisticConcurrencyException 
'通过刷新
'对象上下文来解决并发冲突重新保存更改。
context.Refresh(RefreshMode.ClientWins,orders)

'保存更改。
context.SaveChanges()
Console.WriteLine(OptimisticConcurrencyException处理和更改保存)

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



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



UI代码是一个更好的解决方案。


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

  • it automatically implements last-in-wins instead of using optimistic mode
  • it is not robust: concurrent changes between .Refresh and .SaveChanges can cause a new OptimisticConcurrencyException

Is this correct, or am I missing something?

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

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)

See:

Functional Optimistic Concurrency in C#

Retryable actions in C#

解决方案

This:

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

...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.

Your proposed UI code is a better solution.

这篇关于处理实体框架OptimisticConcurrencyException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆