I'm starting a new project with NHibernate 3 and I'm trying to use the CurrentSessionContext API with WebSessionContext to manage my ISession object.
In previous projects I always managed that myself so whenever I needed a ISession object I would create it and store in HttpContext.Items collection. Pretty straightforward, but using a native solution (CurrentSessionContext) seems like a best option for this new project.
When I managed the object I was able to do a lazy initialization on it, meaning that I would only open a Session when I needed it and not in every request because I may not need it and would be wasting resource/time by opening it all the time.
Is there a simple way to do that with the CurrentSessionContext API?
Here is the code I'm using in the HttpModule responsible for this:
public class ContextualSessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
public void Dispose()
{
}
private static void context_BeginRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
BindSession(context);
}
private static void BindSession(HttpContext context)
{
// Create a new session (it's the beginning of the request)
var session = SessionBuilderFactory.CurrentSessionFactory.OpenSession();
// Tell NH session context to use it
CurrentSessionContext.Bind(session);
}
private static void context_EndRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
UnbindSession(context);
}
private static void UnbindSession(HttpContext context)
{
// Get the default NH session factory
var factory = SessionBuilderFactory.CurrentSessionFactory;
// Give it to NH so it can pull the right session
var session = CurrentSessionContext.Unbind(factory);
if (session == null) return;
session.Flush();
session.Close();
}
}
Edit
Diego pretty much nailed it, but I thought a little bit more about this and I remembered the main reason why I implemented that control myself: transactions.
I'm a Onion Architecture guy so my domain objects (who are the ones who know when to start a transaction) does not have access to infrastructure so they cannot start transactions.
In order to solve this, I use lazy initialization and always start a transaction when opening a Session. Committing happens when the request ends and no exceptions were caught. Besides this, there is Ayende's advice to always use transactions, even when querying. Any thoughts?