NHibernate ISession Flush :Où et quand l’utiliser, et pourquoi ?
-
09-06-2019 - |
Question
L'une des choses qui me rend complètement confus est l'utilisation de session.Flush
, en collaboration avec session.Commit
, et session.Close
.
Parfois session.Close
fonctionne, par exemple, il valide tous les changements dont j'ai besoin.Je sais que je dois utiliser commit lorsque j'ai une transaction ou une unité de travail avec plusieurs créations/mises à jour/suppressions, afin de pouvoir choisir d'annuler si une erreur se produit.
Mais parfois, je suis vraiment bloqué par la logique derrière session.Flush
.J'ai vu des exemples où vous avez un session.SaveOrUpdate()
suivi d'un flush, mais quand je supprime Flush, cela fonctionne bien de toute façon.Parfois, je rencontre des erreurs dans l'instruction Flush indiquant que la session a expiré et sa suppression m'a permis de ne pas rencontrer cette erreur.
Quelqu'un a-t-il une bonne idée pour savoir où et quand utiliser un Flush ?J'ai consulté la documentation de NHibernate à ce sujet, mais je ne trouve toujours pas de réponse simple.
La solution
Brièvement:
- Utilisez toujours les transactions
- Ne pas utiliser
Close()
, envoyez plutôt vos appels sur unISession
à l'intérieur d'unusing
déclaration ou gérer le cycle de vie de votre ISession ailleurs.
Depuis La documentation:
De temps en temps le
ISession
exécutera les instructions SQL nécessaires pour synchroniser l'état de la connexion ADO.NET avec l'état des objets conservés en mémoire.Ce processus, flush, se produit par défaut aux points suivants
- de quelques invocations de
Find()
ouEnumerable()
- depuis
NHibernate.ITransaction.Commit()
- depuis
ISession.Flush()
Les instructions SQL sont émises dans l'ordre suivant
- toutes les insertions d'entités, dans le même ordre, les objets correspondants ont été enregistrés en utilisant
ISession.Save()
- toutes les mises à jour d'entité
- toutes les suppressions de collections
- toutes les suppressions, mises à jour et insertions d'éléments de collection
- toutes les insertions de collections
- toutes les suppressions d'entités, dans le même ordre, les objets correspondants ont été supprimés à l'aide de
ISession.Delete()
(Une exception est que les objets utilisant la génération d'ID natif sont insérés lors de leur enregistrement.)
Sauf quand tu es explicite
Flush()
, il n'y a absolument aucune garantie sur le moment où la session exécute les appels ADO.NET, seulement sur l'ordre dans lequel ils sont exécutés..Cependant, NHibernate garantit que leISession.Find(..)
les méthodes ne renverront jamais de données obsolètes ;ils ne renverront pas non plus les mauvaises données.Il est possible de modifier le comportement par défaut afin que le vidage se produise moins fréquemment.Le
FlushMode
class définit trois modes différents :vider uniquement au moment de la validation (et seulement lorsque le NHibernateITransaction
API est utilisée), vider automatiquement à l'aide de la routine expliquée, ou ne jamais vider à moins queFlush()
est appelé explicitement.Le dernier mode est utile pour les unités de travail de longue durée, où unISession
est maintenu ouvert et déconnecté pendant une longue période.
...
Référez-vous également à cette section:
La fin d'une session implique quatre phases distinctes :
- vider la session
- valider la transaction
- clôturer la séance
- gérer les exceptions
Vider la session
Si vous utilisez le
ITransaction
API, vous n'avez pas à vous soucier de cette étape.Elle sera effectuée implicitement lorsque la transaction sera validée.Sinon tu devrais appelerISession.Flush()
pour garantir que toutes les modifications sont synchronisées avec la base de données.Validation de la transaction de base de données
Si vous utilisez l'API NHibernate ITransaction, cela ressemble à :
tx.Commit(); // flush the session and commit the transaction
Si vous gérez vous-même les transactions ADO.NET, vous devez manuellement
Commit()
la transaction ADO.NET.sess.Flush(); currentTransaction.Commit();
Si vous décidez de ne pas valider vos modifications :
tx.Rollback(); // rollback the transaction
ou:
currentTransaction.Rollback();
Si vous annulez la transaction, vous devez immédiatement fermer et abandonner la session en cours pour vous assurer que l'état interne de NHibernate est cohérent.
Clôture de la session IS
Un appel à
ISession.Close()
marque la fin d’une séance.La principale implication de Close() est que la connexion ADO.NET sera abandonnée par la session.tx.Commit(); sess.Close(); sess.Flush(); currentTransaction.Commit(); sess.Close();
Si vous avez fourni votre propre connexion,
Close()
renvoie une référence à celui-ci, vous pouvez donc le fermer manuellement ou le remettre dans le pool.SinonClose()
le renvoie à la piscine.
Autres conseils
À partir de NHibernate 2.0, les transactions sont requises pour les opérations de base de données.Par conséquent, la ITransaction.Commit()
l'appel se chargera de tout rinçage nécessaire.Si, pour une raison quelconque, vous n'utilisez pas les transactions NHibernate, il n'y aura pas de vidage automatique de la session.
De temps en temps, l'ISession exécutera les instructions SQL nécessaires pour synchroniser l'état de la connexion ADO.NET avec l'état des objets conservés en mémoire.
Et utilisez toujours
using (var transaction = session.BeginTransaction())
{
transaction.Commit();
}
une fois les modifications validées, ces modifications doivent être enregistrées dans la base de données, nous utilisons transaction.Commit();
Voici deux exemples de mon code où il échouerait sans session.Flush() :
http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html
à la fin de ceci, vous pouvez voir une section de code dans laquelle j'active l'insertion d'identité, enregistre l'entité puis vide, puis désactive l'insertion d'identité.Sans ce vidage, il semblait activer et désactiver l'insertion d'identité, puis enregistrer l'entité.
L'utilisation de Flush() m'a donné plus de contrôle sur ce qui se passait.
Voici un autre exemple :
Envoi d'un message NServiceBus dans TransactionScope
Je ne comprends pas vraiment pourquoi, mais Flush() a empêché mon erreur de se produire.