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

l'Une des choses qui me confus est l'utilisation de session.Flush ,en collaboration avec session.Commit , et session.Close .

parfois session.Close fonctionne, par exemple, il engage tous les changements dont j'ai besoin. Je sais que j'ai besoin d'utiliser commit lorsque j'ai une transaction, ou une unité de travail avec plusieurs creates/updates/deletes, de sorte que je puisse choisir de revenir en arrière 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 retire Flush il fonctionne très bien de toute façon. Parfois, je tombe dans des erreurs sur L'énoncé Flush disant que la session s'est arrêtée, et l'enlever a fait en sorte que je ne suis pas tombé dans cette erreur.

est-ce que quelqu'un a une bonne directive pour savoir où et quand utiliser une chasse d'eau? J'ai vérifié la documentation de NHibernate pour ça, mais je ne trouve toujours pas de réponse simple.

181
demandé sur geo 2008-09-04 12:04:04

4 réponses

brièvement:

  1. Toujours utiliser des transactions
  2. N'utilisez pas Close() , à la place enveloppez vos appels sur un ISession à l'intérieur d'un using déclaration ou gérer le cycle de vie de votre ISession ailleurs .

à Partir de la documentation :

de temps en temps le ISession exécutera le Les déclarations SQL nécessaires pour synchroniser ADO.NET l'état de la connexion avec l'état des objets gardés en mémoire. Ce processus, flush, se produit par défaut aux points suivants

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

les déclarations SQL sont publiées dans l'ordre suivant

  1. toutes les insertions d'entités, dans le même ordre les objets correspondants ont été sauvegardés en utilisant ISession.Save()
  2. toutes les mises à jour des entités
  3. toutes les suppressions de collection
  4. suppression, mise à jour et insertion de tous les éléments de la collection
  5. toutes les insertions de collecte
  6. toutes les suppressions d'entités, dans le même ordre les objets correspondants ont été supprimés en utilisant ISession.Delete()

(une exception est que les objets utilisant la génération native ID sont insérés quand ils sont sauvegardés.)

sauf lorsque vous explicitez Flush() , il n'y a absolument aucune garantie sur le moment où la Session exécute le ADO.NET les appels, seulement l'ordre dans lequel ils sont exécutés . Cependant, NHibernate garantit que les méthodes ISession.Find(..) ne retourneront jamais les données périmées; renvoie les mauvaises données.

il est possible de changer le comportement par défaut de sorte que flush se produit moins fréquemment. La classe FlushMode définit trois modes différents: seulement flush au moment de la propagation (et seulement lorsque L'API ITransaction est utilisée), flush automatiquement en utilisant la routine expliquée, ou never flush à moins que Flush() ne soit explicitement appelé. 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 un long moment.

...

voir aussi cette section :

la fin d'une session comporte quatre phases distinctes:

  • vider la session
  • valider la transaction
  • clôture de la session
  • gérer les exceptions

Rinçage de la Session

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

Valider 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 ADO.NET transactions vous-même vous devriez manuellement Commit() le ADO.NET transaction.

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

si vous décidez de ne pas effectuer vos modifications:

tx.Rollback();  // rollback the transaction

ou:

currentTransaction.Rollback();

si vous annulez la transaction, vous devez immédiatement fermer et rejeter la session en cours pour vous assurer que L'état interne de NHibernate est cohérent.

Clôture de la session

Un appel à ISession.Close() marque la fin d'une session. L'implication principale de Close () est que le ADO.NET la session abandonnera la connexion.

tx.Commit();
sess.Close();

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

si vous avez fourni votre propre connexion, Close() renvoie une référence à celle-ci, de sorte que vous pouvez la fermer manuellement ou la retourner à la piscine. Sinon Close() le renvoie à la piscine.

229
répondu Matt Hinze 2015-11-12 13:53:38

à partir de NHibernate 2.0, les transactions sont requises pour les opérations de PD. Par conséquent, l'appel ITransaction.Commit() gérera tout rinçage nécessaire. Si pour une raison quelconque vous n'utilisez pas les transactions NHibernate, alors il n'y aura pas de chasse d'eau automatique de la session.

13
répondu Sean Carpenter 2008-09-04 17:17:08

de temps en temps l'ISession exécutera les instructions SQL nécessaires pour synchroniser ADO.NET l'état de la connexion avec l'état des objets gardés en mémoire.

et toujours utiliser

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

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

1
répondu ganders 2014-09-22 15:59:28

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 l'insertion d'identité sur, Enregistrer l'entité puis tirer la chasse, puis mettre l'insertion d'identité off. Sans cette chasse d'eau, il semble que le réglage d'identité insert on et off puis sauver l'entité.

L'utilisation de Flush () m'a donné plus de contrôle sur ce qui se passait.

voici un autre exemple:

Envoi NServiceBus message à l'intérieur TransactionScope

Je ne comprends pas très bien pourquoi sur celle-ci, mais Flush() a empêché mon erreur de se produire.

0
répondu Paul T Davies 2017-05-23 12:25:55