The McDev Blog

Kevin McKelvin's perspective of the Ruby world.

The NH3 Music Store Part 4 – Session Per Request

I started looking at the controllers in the Music Store application and pretty quickly realised that before I could really do much there, I needed to have my IMusicStoreContext available. This meant I need an ISession from NHibernate.

The accepted way of using NHibernate is to use a pattern known as “Session per request” – where at the beginning of a request we bind a session to the CurrentSessionContext – then unbind it at the end of the request.

Before we can do that however, we need an ISessionFactory. This is the single entry point to NHibernate. It’s an expensive operation to create an ISessionFactory, but you only do it once.

In keeping with NHibernate 3, I’m going to use the new Loquacious API to configure my ISessionFactory. This goes in the MvcApplication class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static ISessionFactory SessionFactory = CreateSessionFactory();

private static ISessionFactory CreateSessionFactory()
{
    var config = new Configuration();

    config.DataBaseIntegration(
        db =>
            {
                db.ConnectionStringName = "MusicStoreConnection",
                db.Dialect<MsSql2005Dialect>();
            })
        .Proxy(p => p.ProxyFactoryFactory<ProxyFactoryFactory>())
        .AddAssembly(typeof (Album).Assembly);

    return config.BuildSessionFactory();
}

I won’t be using the ISession directly in my code, I’ll now implement my IMusicStoreContext and use one of those per session / per request.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class MusicStoreContext : IMusicStoreContext
{
    private readonly ISession _currentSession;

    public MusicStoreContext(ISession currentSession)
    {
        _currentSession = currentSession;
    }

    public ISession Session
    {
        get { return _currentSession; }
    }

    public IQueryable<Album> Albums
    {
        get { return _currentSession.Query<Album>(); }
    }

    public IQueryable<Artist> Artists
    {
        get { return _currentSession.Query<Artist>(); }
    }

    public IQueryable<Cart> Carts
    {
        get { return _currentSession.Query<Cart>(); }
    }

    public IQueryable<Genre> Genres
    {
        get { return _currentSession.Query<Genre>(); }
    }

    public IQueryable<Order> Orders
    {
        get { return _currentSession.Query<Order>(); }
    }
}

To create one of these per request, I simply create a new MusicStoreContext object that wraps the session for the request and expose it as a public static method on MvcApplication.

1
2
3
4
5
6
7
8
9
10
public static IMusicStoreContext GetCurrentRequestContext()
{
    // get the ISession bound to the current request
    var currentSession = SessionFactory.GetCurrentSession();

    // build a context object to wrap it
    var context = new MusicStoreContext(currentSession);

    return context;
}

And from here I have an NHibernate session available to my controllers, per request! I’m still deciding whether I should change things around to do some IoC or not, StructureMap really makes this kind of stuff easy without referring to a static method and tightly coupling a controller to the MvcApplication. The other way might be to use a custom controller loader – but that’s a discussion for another post.