2010-09-16 10 views
5

Évaluation de .NET Entity Framework J'essaie de trouver les bons modèles pour gérer les mises à jour simultanées avec un mode de concurrence optimiste.Handle Entity Framework OptimisticConcurrencyException

Dans les documentation et beaucoup d'autres endroits que je vois le schéma suivant:

 

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 

Je vois les problèmes suivants avec ce

  • il implémente automatiquement la dernière en victoires au lieu d'utiliser optimiste mode
  • il n'est pas robuste: les modifications simultanées entre .Refresh et .SaveChanges peuvent provoquer une nouvelle exception OptimisticConcurrencyException

Est-ce correct ou manque-t-il quelque chose?

Dans une interface utilisateur je laisse normalement l'utilisateur résoudre le conflit d'accès concurrentiel:

 

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 

Dans la logique métier que j'utilise normalement une boucle de nouvelle tentative dans toute transaction commerciale (lecture et mise à jour):

 

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ème EF Je prévois de résumer la boucle:

 

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

Voir:

Functional Optimistic Concurrency in C#

Retryable actions in C#

Répondre

6

Ce:

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

... est complètement inutile. Si la seule chose que vous faites lorsque vous "gérez" l'exception est de l'ignorer et de l'enregistrer de toute façon, vous devez désactiver la concurrence optimiste; vous écrivez du code pour contourner une fonctionnalité optionnelle.

Donc, oui, je dirais que la documentation ne vous donne pas de bons conseils ici.

Votre code d'interface utilisateur proposé est une meilleure solution.