É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#