J'ai enquêté sur des transactions et il semble qu'elles se prennent en charge dans EF aussi longtemps que je passe false
à SaveChanges()
puis appelle AcceptAllChanges()
s'il n'y a pas d'erreur:
SaveChanges(false);
// ...
AcceptAllChanges();
Et si quelque chose tourne mal? ne dois-je pas revenir en arrière ou, dès que ma méthode sort du champ d'application, la transaction est-elle terminée?
Qu'advient-il des colonnes d'indentation qui ont été affectées à mi-chemin de la transaction? Je suppose que si quelqu'un d'autre a ajouté un enregistrement après le mien avant que le mien ne tourne mal, cela signifie qu'il y aura une valeur d'identité manquante.
Y a-t-il une raison d'utiliser la TransactionScope
classe standard dans mon code?
c#
entity-framework
transactions
Mark Smith
la source
la source
SaveChanges(fase); ... AcceptAllChanges();
était un modèle en premier lieu. Remarquez comment la réponse acceptée à la question ci-dessus est écrite par l'auteur d'un blog - et ce blog est référencé dans l'autre question. Tout se rassemble.Réponses:
Avec Entity Framework, la plupart du temps
SaveChanges()
est suffisant. Cela crée une transaction ou s'inscrit dans une transaction ambiante et effectue tout le travail nécessaire dans cette transaction.Parfois, même si l'
SaveChanges(false) + AcceptAllChanges()
association est utile.L'endroit le plus utile pour cela est dans les situations où vous souhaitez effectuer une transaction distribuée dans deux contextes différents.
C'est à dire quelque chose comme ça (mauvais):
Si
context1.SaveChanges()
réussit maiscontext2.SaveChanges()
échoue, la transaction distribuée entière est abandonnée. Mais malheureusement, Entity Framework a déjà ignoré les modificationscontext1
, vous ne pouvez donc pas rejouer ou enregistrer efficacement l'échec.Mais si vous changez votre code pour qu'il ressemble à ceci:
Pendant que l'appel à
SaveChanges(false)
envoie les commandes nécessaires à la base de données, le contexte lui-même n'est pas modifié, vous pouvez donc le refaire si nécessaire, ou vous pouvez interroger leObjectStateManager
si vous le souhaitez.Cela signifie que si la transaction lève réellement une exception, vous pouvez compenser, en réessayant ou en enregistrant l'état de chaque contexte
ObjectStateManager
quelque part.Voir mon article de blog pour en savoir plus.
la source
SaveChanges(false)
effectue la mise à jour réelle de la base de données, tout enAcceptAllChanges()
disant à EF: "D'accord, vous pouvez oublier quelles choses doivent être enregistrées, car elles ont été enregistrées avec succès." En cas d'SaveChanges(false)
échec,AcceptAllChanges()
il ne sera jamais appelé et EF considérera toujours votre objet comme ayant des propriétés qui ont été modifiées et doivent être sauvegardées dans la base de données.Si vous utilisez EF6 (Entity Framework 6+), cela a changé pour les appels de base de données à SQL.
Voir: http://msdn.microsoft.com/en-us/data/dn456843.aspx
utilisez context.Database.BeginTransaction.
Depuis MSDN:
la source
throw;
extrait de code MSDN et indiqué clairement qu'il ne s'agit pas de l'original de l'article MSDN.Rollback()
est appelé au cas où il parle à MySql ou à quelque chose qui n'a pas ce comportement automatique.Parce que certaines bases de données peuvent lever une exception à dbContextTransaction.Commit () alors mieux cela:
la source
false
danscontext.SaveChanges();
, et en plus appelcontext.AcceptAllChanges();
.