This page is out of date: see the NHibernate website for up-to-date information.
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:
- ASP.Net and NHibernate session
- Using a single ISession during page execution?
- NHibernate sessions in ASP.NET
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.
- Session handling HttpModule by Ed Courtenay
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
- Sessions and transactions, Open Session in View
- Tobin Harris has a page on the subject: Using NHibernate with ASPX
- Benjamin Day has created a sample application using HttpModule for Session management
- Billy McCafferty has provided an overview of NHibernate best practices within ASP.NET applications including session management and integration with C# 2.0 generics.
- NHibernate.Helper project by Simon Green
- NHibernator by Tomer Avissar. A NHibernate Helper that supports multiple databases, including ASP.NET support using OpenSessionInViewModule and Winform environments support using thread local storage.
Comments