From time to time the ISession
will execute the SQL statements needed to synchronize the ADO.NET connection's state with the state of objects held in memory. This process, flush, occurs by default at the following points
- from some invocations of
Find()
or Enumerable()
- from
NHibernate.ITransaction.Commit()
- from
ISession.Flush()
The SQL statements are issued in the following order
- all entity insertions, in the same order the corresponding objects were saved using
ISession.Save()
- all entity updates
- all collection deletions
- all collection element deletions, updates and insertions
- all collection insertions
- all entity deletions, in the same order the corresponding objects were deleted using
ISession.Delete()
(An exception is that objects using native ID generation are inserted when they are saved.)
Except when you explicity Flush()
, there are absolutely no guarantees about when the Session executes the ADO.NET calls, only the order in which they are executed. However, NHibernate does guarantee that the ISession.Find(..)
methods will never return stale data; nor will they return the wrong data.
It is possible to change the default behavior so that flush occurs less frequently. The FlushMode
class defines three different modes: only flush at commit time (and only when the NHibernate ITransaction
API is used), flush automatically using the explained routine, or never flush unless Flush()
is called explicitly. The last mode is useful for long running units of work, where an ISession
is kept open and disconnected for a long time.
...
Ending a session involves four distinct phases:
- flush the session
- commit the transaction
- close the session
- handle exceptions
Flushing the Session
If you happen to be using the ITransaction
API, you don't need to worry about this step. It will be performed implicitly when the transaction is committed. Otherwise you should call ISession.Flush()
to ensure that all changes are synchronized with the database.
Committing the database transaction
If you are using the NHibernate ITransaction API, this looks like:
tx.Commit(); // flush the session and commit the transaction
If you are managing ADO.NET transactions yourself you should manually Commit()
the ADO.NET transaction.
sess.Flush();
currentTransaction.Commit();
If you decide not to commit your changes:
tx.Rollback(); // rollback the transaction
or:
currentTransaction.Rollback();
If you rollback the transaction you should immediately close and discard the current session to ensure that NHibernate's internal state is consistent.
Closing the ISession
A call to ISession.Close()
marks the end of a session. The main implication of Close() is that the ADO.NET connection will be relinquished by the session.
tx.Commit();
sess.Close();
sess.Flush();
currentTransaction.Commit();
sess.Close();
If you provided your own connection, Close()
returns a reference to it, so you can manually close it or return it to the pool. Otherwise Close()
returns it to the pool.
Best Answer
It doesn't look like ThreadLocalSessionContext can currently be used. There is no configuration that supports it's use and it's only referenced within NHibernate by a unit test.
According to the code CallSessionContext is a way of handling sessions in .Net remoting see comments in code below for more detail. It looks like NHibernate basically stores the session in the remoting call context. More info about remoting call contexts can be found here
ThreadStaticSessionContext is used for handling sessions in multi-threaded applications. It uses a [ThreadStatic] attribute to declare the session such that there is a session per thread. I currently use this. See this SO link for a code example of how you would use it: What is the best NHibernate session management approach for using in a multithread windows service application?
Also in addition to this it looks like NHibernate is adding another session context in version 3.2 called WcfOperationSessionContext. Below is the description from the code:
To answer your 2nd question it really depends on what type of application you are implementing and how you are using your sessions. Hopefully between the nhibernate documentation and the descriptions above you'll have a better idea of what context you should use.