Zuber
Zuber

Reputation: 577

Why evicting objects from Session does not commit changes to database?

I am using NHibernate in my application and have the following situation. (Note that the situation here is much more simplified for the sake of understanding)

An object is queried from the database. It is edited and updated using Session.Update(). The object is then Evicted from the Session (using Session.Evict(obj)) before the transaction is committed. Expected result is that the changes are persisted to the database.

This used to work fine when I had my Id column as a NHibernate identity column. Recently, we changed the Id column to be non-identity. As a result, the above scenario does not persist to the database unless I explicitly call Session.Flush() before I Evict.

Can someone point/explain to me the reason for this behavior?

This link, NHibernate Session.Flush & Evict vs Clear, mentions something about Evict and the identity column, which to me is not very clear.

Upvotes: 2

Views: 5598

Answers (2)

Diego Mijelshon
Diego Mijelshon

Reputation: 52735

Your workflow is not correct.

First, when you retrieve an object from the database, session.Update(entity) does not do anything. Changes will happen automatically on Flush/Commit

Next, Evict removes all knowledge the session has of the object, therefore it will not persist any changes applied to it. You should almost never use this method under normal conditions, which makes me think you are not handling the session correctly.

Third, the fact that using identity causes inserts to happen immediately on Save is a limitation, not a feature.

The correct workflow is:

using (var session = factory.OpenSession())
using (var transaction = session.BeginTransaction())
{
    var entity = session.Get<EntityType>(id);
    entity.SomeProperty = newValue;
    transaction.Commit();
}

The exact structure (using statements, etc) can change in a desktop application, but the basic idea is the same.

Upvotes: 9

Firo
Firo

Reputation: 30813

Identity forces NHibernate to immediatly save the entity to the database on session.Save() non identity allows it to batch the inserts to send them as a whole. Evict will remove all information of the object from the session. So while with identity it forgets about the entity it is already in the database even if the session doesnt know.

to remedy that you can

  • set Flushmode.Auto (forces immediate flushing)
  • call session.Flush() before Evict
  • Evict after the transaction completed

which is the best option depends on the context

Upvotes: 2

Related Questions