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.
4 réponses
brièvement:
- Toujours utiliser des transactions
- N'utilisez pas
Close()
, à la place enveloppez vos appels sur unISession
à l'intérieur d'unusing
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()
ouEnumerable()
- de
NHibernate.ITransaction.Commit()
- de
ISession.Flush()
les déclarations SQL sont publiées dans l'ordre suivant
- toutes les insertions d'entités, dans le même ordre les objets correspondants ont été sauvegardés en utilisant
ISession.Save()
- toutes les mises à jour des entités
- toutes les suppressions de collection
- suppression, mise à jour et insertion de tous les éléments de la collection
- toutes les insertions de collecte
- 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éthodesISession.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'APIITransaction
est utilisée), flush automatiquement en utilisant la routine expliquée, ou never flush à moins queFlush()
ne soit explicitement appelé. Le dernier mode est utile pour les unités de travail de longue durée, où unISession
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 appelerISession.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. SinonClose()
le renvoie à la piscine.
à 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.
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();
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.