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.

Était-ce utile?

La solution

Brièvement:

  1. Utilisez toujours les transactions
  2. Ne pas utiliser Close(), envoyez plutôt vos appels sur un ISession à l'intérieur d'un using 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() ou Enumerable()
  • depuis NHibernate.ITransaction.Commit()
  • depuis ISession.Flush()

Les instructions SQL sont émises dans l'ordre suivant

  1. toutes les insertions d'entités, dans le même ordre, les objets correspondants ont été enregistrés en utilisant ISession.Save()
  2. toutes les mises à jour d'entité
  3. toutes les suppressions de collections
  4. toutes les suppressions, mises à jour et insertions d'éléments de collection
  5. toutes les insertions de collections
  6. 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 le ISession.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 NHibernate ITransaction API est utilisée), vider automatiquement à l'aide de la routine expliquée, ou ne jamais vider à moins que Flush() est appelé explicitement.Le dernier mode est utile pour les unités de travail de longue durée, où un ISession 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 appeler ISession.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.Sinon Close() 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top