2010-09-18 1 views
3

J'ai remarqué, en utilisant log4net, que lors de l'appel de ISession.Update, il met à jour tous les objets modifiés.
Par exemple:NHibernate ISession.Update


// Change 2 instances 
user1.IsDeleted = true; 
user2.UserName = "Xyz"; 
// Call session.Update to update the 2 users 
using (ITransaction transaction = session.BeginTransaction()) 
{ 
    Session.Update(user1); // This updates both user1 & user2 
    transaction.Commit(); 
} 
using (ITransaction transaction = session.BeginTransaction()) 
{ 
    Session.Update(user2); // Now there is no need for this 
    transaction.Commit(); 
} 

Est-ce le comportement par défaut de NHibernate ou a quelque chose à voir avec mon fichier de mappage? Puis-je faire une mise à jour de NHibernate une par une?

+0

Utilisez-vous plusieurs transactions par session? Et pourquoi obtenez-vous l'utilisateur avant de commencer la transaction? – Paco

+0

Oui plusieurs transactions par session. Je laisse toujours la session ouverte et utilise une nouvelle transaction pour chaque opération. Je reçois l'instance de l'utilisateur en appelant session.Get, passe l'utilisateur à l'interface utilisateur pour apporter des modifications puis le mettre à jour. –

+0

Pourquoi utilisez-vous une transaction distincte pour chaque opération? Cela semble très étrange. – Paco

Répondre

12

Il est le normal et default behavior:

Hibernate maintient un cache d'objets qui ont été insérées, mises à jour ou supprimés. Il maintient également un cache de Objets qui ont été interrogés à partir de la base de données . Ces objets sont appelés Objets persistants en tant que tant que le EntityManager utilisé pour les récupérer est toujours actif. Cela signifie que les modifications apportées à ces objets dans les limites d'une transaction sont automatiquement confirmées lorsque la transaction est validée. Ces mises à jour sont implicite dans les limites de la transaction et vous n'avez pas besoin d'appeler explicitement toute méthode pour conserver les valeurs.

De Hibernate Pitfalls part 2:

Q) Dois-je encore faire Enregistrer et mise à jour dans les transactions?

Save() n'est nécessaire que pour les objets qui ne sont pas persistants ( ). Vous pouvez utiliser Mettre à jour pour amener un objet qui a été expulsé dans une session.

De NHibernate's automatic (dirty checking) update behaviour:

Je viens de découvrir que si je reçois un objet d'une session NHibernate et modifier une propriété sur l'objet, NHibernate mettra automatiquement à jour l'objet sur commettre sans moi en appelant Session.Update (myObj)!

Réponse: Vous pouvez définir Session.FlushMode sur FlushMode.Never. Cela rendra vos opérations explicites, c'est-à-dire: sur tx.Commit() ou session.Flush(). Bien sûr, cela mettra toujours à jour la base de données lors de la validation/vidage. Si vous ne voulez pas ce comportement, appelez session.Evict (yourObj) et il deviendra puis passera en mode transitoire et NHibernate ne lui enverra aucune commande db.

+0

Juste pour m'assurer que je comprends, en réglant le Session.FlushMode à FlushMode.Never puis appeler Session.Update mettra à jour seulement user1 dans mon exemple. –

+0

@sh_kamalh Bien que je préfère Evict (obj), prenez un butin à http://nhforge.org/doc/nh/en/index.html#manipulatingdata-flushing – rebelliard

+0

Désolé de prendre autant pour marquer cela comme réponse. Mais je ne comprenais pas très bien les concepts de NHibernate. Evict fonctionne correctement. –

2

Ceci est le comportement par défaut lorsque FlushMode de la session est Auto ou Commit.

Dans ces cas d'appel transaction.Commit() Bouffées de la session & met à jour TOUS les objets persistants

Donc, si vous supprimez les appels Session.update il ne fera aucune différence

Puis-je faire NHibernate mise à jour une par une?

Oui. utilisez FlushMode.Never ou reportez la validation de la session si possible. Je suppose que vous n'avez pas besoin d'utiliser Evict pour ce cas