问题描述
在和许多其他地方我看到以下模式:
尝试
'尝试保存更改,这可能会导致冲突。
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#中的功能乐观并发性
这样:
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#
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!