NHibernate ISession Flush: Où et quand l’utiliser, et pourquoi?

L’utilisation de session.Flush , en conjonction avec session.Commit , et session.Close une des choses qui me rend complètement confus.

Parfois session.Close travaux, par exemple, il commet toutes les modifications dont j’ai besoin. Je sais que je dois utiliser commit lorsque j’ai une transaction, ou une unité de travail avec plusieurs create / updates / deletes, afin de pouvoir choisir de restaurer si une erreur survient.

Mais parfois, je suis vraiment bloqué par la logique derrière la session.Flush . J’ai vu des exemples où vous avez une session.SaveOrUpdate() suivie par un flush, mais quand je supprime Flush cela fonctionne bien quand même. Parfois, je rencontre des erreurs sur la déclaration Flush, indiquant que la session a expiré et que sa suppression a permis de m’assurer que je ne rencontrais pas cette erreur.

Est-ce que quelqu’un a un bon guide pour savoir où et quand utiliser une chasse d’eau? J’ai vérifié la documentation NHibernate pour cela, mais je ne trouve toujours pas de réponse simple.

Brièvement:

  1. Toujours utiliser les transactions
  2. N’utilisez pas Close() , placez plutôt vos appels sur une ISession dans une instruction using ou gérez le cycle de vie de votre ISession ailleurs .

De la documentation :

De temps en temps, ISession exécute les instructions SQL nécessaires pour synchroniser l’état de la connexion ADO.NET avec l’état des objects en mémoire. Ce processus, flush, se produit par défaut aux points suivants

  • à partir de quelques invocations de Find() ou Enumerable()
  • à partir de NHibernate.ITransaction.Commit()
  • de ISession.Flush()

Les instructions SQL sont émises dans l’ordre suivant

  1. toutes les insertions d’entité, dans le même ordre, les objects correspondants ont été enregistrés en utilisant ISession.Save()
  2. toutes les mises à jour d’entité
  3. toutes les suppressions de collection
  4. toutes les suppressions, mises à jour et insertions d’éléments de collection
  5. toutes les insertions de collection
  6. toutes les suppressions d’entités, dans le même ordre, les objects correspondants ont été supprimés en utilisant ISession.Delete()

(Une exception est que les objects utilisant la génération d’ID natifs sont insérés lorsqu’ils sont enregistrés.)

Sauf lorsque vous Flush() explicitement Flush() , il n’y a absolument aucune garantie sur le moment où la session exécute les appels ADO.NET, uniquement l’ordre dans lequel ils sont exécutés . Cependant, NHibernate garantit que les méthodes ISession.Find(..) ne renverront jamais de données obsolètes; ils ne retourneront pas non plus les mauvaises données.

Il est possible de modifier le comportement par défaut pour que le vidage se produise moins fréquemment. La classe FlushMode définit trois modes différents: vider uniquement au moment de la validation (et uniquement lorsque l’API NHibernate ITransaction est utilisée), vider automatiquement en utilisant la routine expliquée, ou ne jamais vider à moins que Flush() soit appelée explicitement. Le dernier mode est utile pour les unités de travail de longue durée, où une ISession rest ouverte et déconnectée pendant longtemps.

Reportez-vous également à cette section :

Mettre fin à une session comporte quatre phases distinctes:

  • rincer la séance
  • valider la transaction
  • fermer la session
  • gérer les exceptions

Flushing la session

Si vous utilisez l’API ITransaction , vous n’avez pas à vous soucier de cette étape. Il sera effectué implicitement lorsque la transaction est validée. Sinon, vous devez appeler ISession.Flush() pour vous assurer que toutes les modifications sont synchronisées avec la firebase database.

Commettre la transaction de firebase database

Si vous utilisez l’API NHibernate ITransaction, cela ressemble à ceci:

 tx.Commit(); // flush the session and commit the transaction 

Si vous gérez vous-même des transactions ADO.NET, vous devez manuellement Commit() la transaction ADO.NET.

 sess.Flush(); currentTransaction.Commit(); 

Si vous décidez de ne pas commettre vos modifications:

 tx.Rollback(); // rollback the transaction 

ou:

 currentTransaction.Rollback(); 

Si vous annulez la transaction, vous devez immédiatement fermer et ignorer la session en cours pour vous assurer que l’état interne de NHibernate est cohérent.

Fermeture de l’ISession

Un appel à ISession.Close() marque la fin d’une session. 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 la fermer manuellement ou la renvoyer dans le pool. Sinon, Close() renvoie au pool.

À partir de NHibernate 2.0, les transactions sont requirejses pour les opérations de firebase database. Par conséquent, l’appel ITransaction.Commit() gérera tout vidage 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, ISession exécute les instructions SQL nécessaires pour synchroniser l’état de la connexion ADO.NET avec l’état des objects en mémoire.

Et toujours utiliser

  using (var transaction = session.BeginTransaction()) { transaction.Commit(); } 

une fois que les modifications ont été validées, cette modification à enregistrer dans la firebase database, 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 où je mets en place l’insertion d’identité, sauve l’entité puis la vider, puis désactive l’insertion d’identité. Sans ce flush, il semblerait que la mise en place et l’insertion de l’identité soient effectuées, puis l’enregistrement de l’entité.

L’utilisation de Flush () m’a permis de mieux contrôler ce qui se passait.

Voici un autre exemple:

Envoi d’un message NServiceBus dans TransactionScope

Je ne comprends pas bien pourquoi, mais Flush () a empêché mon erreur de se produire.