J'ai actuellement une méthode qui lit les données pour déterminer si une mise à jour est nécessaire, puis pousse la mise à jour à la base de données (dépendance injectée). La méthode est frappée très fort, et j'ai trouvé des bogues liés à la concurrence, à savoir, plusieurs mises à jour puisque plusieurs threads lisent les données avant la première mise à jour. J'ai résolu cela en utilisant une serrure, ça marche plutôt bien. Comment puis-je utiliser un TransactionScope pour faire la même chose? Puis-je? Va-t-il bloquer un autre thread comme le ferait un verrou? De plus, puis-je 'verrouiller' un 'id' spécifique comme je le fais avec un verrou (je garde un dictionnaire qui stocke un objet à verrouiller pour chaque identifiant)? J'utilise Entity Framework 5, bien qu'il soit masqué par un référentiel et un modèle d'unité de travail.TransactionScope Au lieu d'utiliser un verrou
Répondre
Le verrouillage du niveau d'application peut ne pas être une solution à ce problème. Tout d'abord, vous devez généralement verrouiller uniquement un enregistrement unique ou une plage d'enregistrements. Ensuite, vous devrez peut-être verrouiller d'autres modifications et entrer dans un code assez complexe.
Cette situation est généralement gérée avec une concurrence optimiste ou pessimiste. Concurrence optimiste - vous aurez une colonne additionnelle générée par la base de données (la base de données a généralement un type spécial comme timestamp ou rowversion). La base de données mettra automatiquement à jour cette colonne chaque fois que vous mettez à jour l'enregistrement. Si vous configurez cette colonne en tant que version de ligne EF inclura la colonne dans la condition where de la mise à jour => la mise à jour exécutée recherchera l'enregistrement avec la clé et la version de ligne données. Si l'enregistrement est trouvé, il sera mis à jour. Si l'enregistrement n'est pas trouvé cela signifie que l'enregistrement avec la clé n'existe pas ou quelqu'un d'autre a mis à jour l'enregistrement puisque le processus courant a chargé ses données => vous obtiendrez une exception et vous pouvez essayer d'actualiser les données et sauvegarder les modifications. Ce mode est utile pour les enregistrements qui ne sont pas trop mis à jour. Dans votre cas, cela peut causer juste un autre problème.
Merci pour les commentaires! Ce que j'ai déployé pour le moment est une combinaison d'un verrou au niveau de l'application (basé sur les performances, si un TryEnter échoue ignore l'action), dans lequel existe une portée d'application avec isolationlevel.repeatableread pour gérer le cas rare d'une concurrence issue de l'extérieur de la méthode. Une mauvaise solution? – ccook
- 1. Transactionscope
- 2. Obtention d'un verrou sur une seule entrée de dictionnaire au lieu d'un dictionnaire entier?
- 3. Synchronisé avec un objet fictif au lieu de ce
- 4. TransactionScope et procédure stockée?
- 5. Nuances TransactionScope
- 6. TransactionScope question
- 7. TransactionScope - IEnlistmentNotification
- 8. Nested TransactionScope
- 9. TransactionScope et erreur: ORA-02049
- 10. Différence entre verrou (verrou) et verrouillage (variable_qui_utilise_I_am_using)
- 11. Verrou avec petit overhead ou sans verrou
- 12. Exception dans TransactionScope
- 13. Intermittent System.ArgumentNullException utilisant TransactionScope
- 14. NHibernate, transactions et TransactionScope
- 15. Verrou de table d'insertion SQL WCF Transaction Scope
- 16. Utilisation de transactions ADO.Net dans un TransactionScope?
- 17. Plusieurs niveaux d'isolation requis pour un TransactionScope?
- 18. Utiliser un NSMutableArray au lieu d'un NSFetchedResultsController
- 19. Déclencheur TextBlock au lieu d'utiliser un convertisseur
- 20. Renvoyer un int au lieu d'un datatable
- 21. TransactionScope et dans sproc
- 22. TxSelect et TransactionScope
- 23. asp.net mvc transactionscope class
- 24. (. *) Au lieu de (. *?)
- 25. TransactionScope et niveau d'isolement
- 26. TransactionScope et Transactions
- 27. .NET TransactionScope sur Oracle
- 28. Rebus Envoyer à TransactionScope
- 29. instanciation TransactionScope retourne null
- 30. Nested/Child TransactionScope Rollback
Qu'en est-il d'un ReadWriterLockSlim à la place? Si vous avez plusieurs lectures et peu d'écritures c'est beaucoup mieux qu'un verrou. (comment TransactionScope rendrait-il thread-safe?) –
Ce serait mieux que juste le verrou (+1). Mais, il ne me permettrait pas de travailler en toute sécurité sur les données ailleurs, ou de travailler à partir d'une autre machine sur les mêmes données. – ccook
ReaderWriterLockSlim est généralement recommandé pour être utilisé _without_ accès récursif autorisé, et permet d'écrire du code encore problématique si cela est permis, une situation périlleuse. Tout aussi périlleux, sinon plus, que celui qu'il a résolu. –