187 votes

Purge de l'ISession de NHibernate : Où et quand l'utiliser, et pourquoi ?

L'une des choses qui m'embrouillent le plus est l'utilisation de session.Flush, en conjonction avec session.Commit et session.Close.

Parfois, session.Close fonctionne, c'est-à-dire qu'il commet 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 de revenir en arrière si une erreur se produit.

Mais parfois, je suis vraiment déconcerté par la logique qui sous-tend session.Flush. J'ai vu des exemples où vous avez une session.SaveOrUpdate() suivie d'un flush, mais lorsque je supprime Flush, tout fonctionne bien. Parfois, je rencontre des erreurs dans l'instruction Flush, indiquant que la session a expiré, et le fait de supprimer cette instruction m'a permis de ne pas rencontrer cette erreur.

Quelqu'un a-t-il une bonne idée de l'endroit ou du moment où il faut utiliser un Flush ? J'ai consulté la documentation de NHibernate à ce sujet, mais je n'ai toujours pas trouvé de réponse claire.

236voto

Matt Hinze Points 9686

En bref :

  1. Utilisez toujours les transactions
  2. N'utilisez pas Close() au lieu d'envelopper vos appels dans un ISession à l'intérieur d'un using déclaration ou gérer le cycle de vie de votre session IS ailleurs .

De 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, la chasse d'eau, se produit par défaut aux points suivants

  • de certaines invocations de Find() ou Enumerable()
  • de NHibernate.ITransaction.Commit()
  • de ISession.Flush()

Les instructions SQL sont émises dans l'ordre suivant

  1. toutes les insertions d'entités, dans le même ordre que les objets correspondants ont été sauvegardés à l'aide de la fonction ISession.Save()
  2. toutes les mises à jour des entités
  3. toutes les suppressions de collections
  4. toutes les suppressions, mises à jour et insertions d'éléments de la collection
  5. toutes les insertions de collections
  6. toutes les suppressions d'entités, dans le même ordre que celui dans lequel les objets correspondants ont été supprimés à l'aide de la fonction ISession.Delete()

(A l'exception des objets utilisant la génération native d'ID qui sont insérés lors de leur sauvegarde).

Sauf quand vous êtes explicitement Flush() Il n'y a absolument aucune garantie quant au moment où la session exécute les appels ADO.NET, mais seulement quant à l'ordre dans lequel ils sont exécutés. . Cependant, NHibernate garantit que le fichier ISession.Find(..) ne renverront jamais des données périmées, ni des données erronées.

Il est possible de modifier le comportement par défaut de manière à ce que la purge soit moins fréquente. Le site FlushMode définit trois modes différents : uniquement la purge au moment de la livraison (et uniquement lorsque la classe NHibernate ITransaction est utilisée), effectuer un vidage automatique à l'aide de la routine expliquée, ou ne jamais effectuer de vidage à moins que l'API Flush() est appelé explicitement. Le dernier mode est utile pour les unités de travail de longue durée, où une unité de travail de type ISession est maintenu ouvert et déconnecté pendant une longue période.

...

Voir également cet article :

La fin d'une session comporte quatre phases distinctes :

  • purger la session
  • valider la transaction
  • clôturer la session
  • gérer les exceptions

Vider la session

Si vous utilisez le ITransaction API, vous n'avez pas besoin de vous soucier de cette étape. Elle sera exécutée implicitement lorsque la transaction sera validée. Sinon, vous devez appeler ISession.Flush() pour s'assurer que toutes les modifications sont synchronisées avec la base de données.

Validation de la transaction de la base de données

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 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 afin de garantir la cohérence de l'état interne de NHibernate.

Fermeture de la session IS

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, afin que vous puissiez le fermer manuellement ou le remettre dans le pool. Sinon, Close() le renvoie dans la piscine.

14voto

Sean Carpenter Points 5588

À partir de NHibernate 2.0, les transactions sont requises pour les opérations de la base de données. Par conséquent, le ITransaction.Commit() s'occupera du 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.

1voto

kapilgandhi Points 1

De temps en temps, l'ISession exécute 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();
            }

après que les changements ont été engagés que ces changements pour sauver dans la base de données nous utilisons transaction.Commit() ;

0voto

Paul T Davies Points 889

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, vous pouvez voir une section de code où j'ai activé l'insertion d'identité, sauvegardé l'entité, puis vidé, et enfin désactivé l'insertion d'identité. Sans cette purge, il semble que l'insertion d'identité soit activée et désactivée, puis que l'entité soit sauvegardée.

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 à l'intérieur du TransactionScope

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X