3

I have noticed, by using log4net, that when calling ISession.Update, it updates all the changed objects.
For example:


// 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();
}

Is this the default behavior of NHibernate or has something to do with my mapping file?
Can I make NHibernate update one by one?

sh_kamalh
  • 3,853
  • 4
  • 38
  • 50
  • Do you use multiple transactions per session? And why do you get the user before starting the transaction? – Paco Sep 18 '10 at 20:21
  • Yes multiple transactions per session. I always leave the session open and use a new transaction for each operation. I get the User instance by calling session.Get, pass the user to the UI to make changes then update it. – sh_kamalh Sep 19 '10 at 11:56
  • Why do you use a separate transaction for each operation? That sound very strange. – Paco Sep 19 '10 at 19:23
  • Any suggestion for session and transaction management in NHibernate. I basically have a UserRepository that considers each operation as a unit of work and persist to the DB once it is finished. So adding/updating a user opens a new transaction and saves/updates the user then commit or rollback in case of exception. – sh_kamalh Sep 20 '10 at 10:08

2 Answers2

13

It's the normal and default behavior:

Hibernate maintains a cache of Objects that have been inserted, updated or deleted. It also maintains a cache of Objects that have been queried from the database. These Objects are referred to as persistent Objects as long as the EntityManager that was used to fetch them is still active. What this means is that any changes to these Objects within the bounds of a transaction are automatically persisted when the transaction is committed. These updates are implicit within the boundary of the transaction and you don’t have to explicitly call any method to persist the values.

From Hibernate Pitfalls part 2:

Q) Do I still have to do Save and Update inside transactions?

Save() is only needed for objects that are not persistent (such as new objects). You can use Update to bring an object that has been evicted back into a session.

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

I've just discovered that if I get an object from an NHibernate session and change a property on object, NHibernate will automatically update the object on commit without me calling Session.Update(myObj)!

Answer: You can set Session.FlushMode to FlushMode.Never. This will make your operations explicit ie: on tx.Commit() or session.Flush(). Of course this will still update the database upon commit/flush. If you do not want this behavior, then call session.Evict(yourObj) and it will then become transient and NHibernate will not issue any db commands for it.

Community
  • 1
  • 1
rebelliard
  • 9,592
  • 6
  • 47
  • 80
  • Just to make sure I understand, setting the Session.FlushMode to FlushMode.Never then calling Session.Update will update only user1 in my example. – sh_kamalh Sep 19 '10 at 11:53
  • @sh_kamalh Although I'd prefer Evict(obj), take a loot at http://nhforge.org/doc/nh/en/index.html#manipulatingdata-flushing – rebelliard Sep 19 '10 at 12:57
  • Sorry for taking that much to mark this as answer. But I was not quite understanding the concepts of NHibernate. Evict is working correctly. – sh_kamalh Nov 12 '10 at 16:34
2

This is the default behavior when FlushMode of session is Auto or Commit.

In these cases calling transaction.Commit() flushes the session & updates ALL persistent objects

So if you remove the calls Session.Update it wouldn't make any difference

Can I make NHibernate update one by one?

Yes. use FlushMode.Never or postpone commiting the session if possible. I guess you don't need to use Evict for this case