Using NHibernate with ASP.NET

Note: this is a copy of the original page from NHibernate Wiki. It could use some editing...

The stateless nature of HTTP creates a few challenges with regard to using NHibernate compared to Winforms. One challenge is where to store the SessionFactory, and another one is how to handle each user's NHibernate Session. This page is created to collect information, tips & tricks and experiences concerning using NHibernate with ASP.Net.

Please help! If you have any information related to using NHibernate with ASP.Net, please add it to this page! Feel free to add or edit content, as well as creating new sections, if needed.

 

 

Configuration

When using ASP.Net, it is often most convenient to put the NHibernate and Log4Net configuration in the web.config file.


Session Handling


SessionFactory

It seems like most people create a singleton SessionFactory from which they create their Sessions. (anyone has some more input on this?)

Session

Forum discussions:

ThreadStatic

What you should not do is to put a ThreadStatic attribute on the Session object. Check out the NHibernate Users FAQ for more information.


Context.Items

One strategy (also see NHibernate Users FAQ is to store a user's Session in Context.Items, using Application_BeginRequest and Application_EndRequest.

Base page class

Another way is to have a base class for all your pages and do the session handling there.

Lars Arne Brekken: What are the pros and cons here? This creates too much coupling between the UI and the DAL, in my opinion

Bob Archer: I agree. I don't think the UI layer should include or know anything about the session factory or the session. The UI layer should talk to the DAO layer to request objects. If you have your SessionFactory or sessions in the UI layer (which HTTPSessions only exist in a Web forms UI layer) then you are really breaking the encapsulation of the UI tier.

Another problem with starting a session in Begin Request, what if you don't NEED the session. Then you are creating a connection to an external resource for no reason. With non-nhibernate apps you wouldn't create a dbconnection this way, you don't it only when you need it. This certainly shouldn't be tied to the page lifecycle.

Sergey Koshcheyev: This shouldn't actually be a problem, I think, since sessions don't open a connection until they actually need one, so there aren't any external resources held.

Session and SessionFactory in one service class

Andrew Mayorov: I've attached three files to this page: session.cs, sessionopener.cs, transaction.cs (available here). Use them as a base or skeleton in your application. Following is the description of some features.

Session.Current returns an instance of NHibernate session, bound to current HTTP request. If there is no current session exist, it will be created. Please note, that disconnected session is created. You need to connect it manually before use. If used not in ASP.NET environment (so there is no request), then current session will be bound to the calling thread. It's useful for reusing persitence classes in desktop application and for unit tests.

Use Session.OpenConnection to connect session to the database with given connection.

// Obtain connection here. It can be either open or closed.
IDbConnection c = ...;

// Open the session
using( Session.OpenConnection( c ) )
{
    ...
}
// At this point the session will be automatically disconnected.
// If OpenConnection opened the connection, it will be closed.

If you need to use distributed transactions (COM+ transactions), you can start them with Session.BeginTransaction method.

using( Transaction t = Session.BeginTransaction() )
{
    // Use the session or perform other transacted activities.
    // Don't forget to open the connection before use.
    ...

    // Vote that transaction was completed succesfully.
    // You can also use SetAbort method for explicit rollback.
    t.SetCommit();
}
// At this point, the transaction will be automatically finished.
// It will be either committed or aborted, according to it's state.

Use Session.Flush to flush changes to the database. Session will not flush itself automatically.

At the beginning of HTTP request call Session.BeginRequest. At the end - Session.EndRequest. Latter could be also used to close and destroy current session. It could be helpful in tests.

At the application init, use Session.Configuration property to configure session factory. Factory will be automatically created at the first access of the Session.Factory property.


Framework solution - NHibernate.Burrow

One of the NHibernate Contrib (a family for Non-core NHibernate extension projs) projects - NHibernate.Burrow, provides a conversation based session/transaction management and other facilitates.


Other resources