This is one of the biggest differences that I found I had to adjust to going from SQL based db access to nHibernate.
the Session object acts as a 1st level cache, meaning that any object you load from the db is cached within the Session.
So, what you receive as a result from a Load(), or Get() or list() .. etc is a reference to a cached object in the Session. As you make changes to these objects, the session is aware of what changes you are making. These changes are queued up in the session and can be flushed to the db in a variety of ways.
There is a FlushMode property on the Session itself which controls this flushing behaviour. If that is set to Auto (which I believe is the default) the session will flush itself from time to time without you even knowing.
If you have wrapped your code in a Transaction (i.e. Session.BeginTransaction()), when that transaction is Committed a flush will occur.
Of course, you can also force a flush as you have indicated.
Flushing becomes even more complicated as in certain situations (I'm not sure of the exact algorithm), a session will flush before performing a query and conversely, will query before performing a Save.
Sounds a bit like you have no control, but you do. You can set the FlushMode to either Flush on Commit, or Never. Oviously Commit allows you to control when flushing is performed via transactions ... this is what I use and it seems to work well. I also use Never sometimes when performing queries and I do not want the Session doing any extra loading / flushing behind my back.
In your case, if you don't want the object you have changed to be flushed, you can either Close() the session which leaves the object as transient ... you can re-attach it to another session by calling SaveOrUpdate() at a later point in your execution.
You can also use the Evict() method on the session to evict that object from the first level cache and therefore the session will not be able to track any changes made to that object and they will not be flushed.
Hope this helps ....
|