Обрабатывать Entity Framework OptimisticConcurrencyException - PullRequest
5 голосов
/ 16 сентября 2010

Оценка .NET Entity Framework Я пытаюсь найти правильные шаблоны для обработки одновременных обновлений в режиме оптимистичного параллелизма.

В документации и во многих других местах я вижу следующую схему:


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

Это правильно, или я что-то упустил?

В пользовательском интерфейсе я обычно позволяюпользователь разрешает конфликт параллелизма:


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

С EF я планирую инкапсулировать цикл:


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

См .:

Функциональный оптимистический параллелизм в C #

Retryable действия в C #

1 Ответ

6 голосов
/ 16 сентября 2010

Это:

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

... совершенно бессмысленно.Если единственное, что вы делаете, когда вы «обрабатываете» исключение, это игнорировать его и сохранять в любом случае, вам следует просто отключить оптимистичный параллелизм;вы пишете код для обхода дополнительной функции.

Итак, да, я бы сказал, что документация здесь не дает вам хороших советов.

Предлагаемый вами код пользовательского интерфейса - лучшее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...