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?
While not directly answering your question, I think: why?
A session is a lightweight object. If you don't use it, it just initializes some internal structures, but it doesn't open a DB connection or anything.
There are some examples around (just Google) to avoid opening sessions for static objects in order to save a little time/memory. Other than that, it might not be worth it, unless your profiling shows it's hurting your performance.
Update: for transaction needs, have a look at the CpBT implementation in uNhAddIns.