« NHibernate Transactional Boundaries | Main | Code Snippets Using SyntaxHighlighter on SquareSpace »
Wednesday
Oct072009

Bootstrapping NHibernate with StructureMap

Jeremy Miller asked me to help him create a canonical example of bootstrapping NHibernate using StructureMap. This is not that example. Hopefully, it will provide a starting point of discussion and, with your feedback, we will be able to create that example together.

Many examples on configuring NHibernate depend on some library such as FluentNHibernate or include additional concepts such as Repositories. While we use FluentNHibernate and Repositories to interface with the database, I did not want to complicate the example with these concerns. I did not want to preclude their addition, either.

NHibernate Registry

I have encapsulated the NHibernate configuration in a StructureMap Registry. It makes the following available:

  • NHibernate.Configuration as a Singleton
  • ISessionFactory as a Singleton
  • ISession scoped to Hybrid (HttpContext, if available, falling back to Thread)
  • IUnitOfWork scoped to Hybrid, a light-weight container for ISession (more on this later)
  • IDatabaseBuilder, a utility class to create the database using SchemaExport and populate it with initial data.

That’s it. If you want to create your own ISession (for example, to use in an integration test), then you request the ISessionFactory and call the OpenSession() method.

Here is the NHibernateRegistry class that provides the Configuration, ISessionFactory, ISession, and IUnitOfWork:

using NHibernate;
using NHibernate.ByteCode.Castle;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernateBootstrap.Core.Domain;
using StructureMap.Attributes;
using StructureMap.Configuration.DSL;
using Environment=NHibernate.Cfg.Environment;

namespace NHibernateBootstrap.Core.Persistence
{
    public class NHibernateRegistry : Registry
    {
        public NHibernateRegistry()
        {
            var cfg = new Configuration()
                .SetProperty(Environment.ReleaseConnections, "on_close")
                .SetProperty(Environment.Dialect, typeof(SQLiteDialect).AssemblyQualifiedName)
                .SetProperty(Environment.ConnectionDriver, typeof(SQLite20Driver).AssemblyQualifiedName)
                .SetProperty(Environment.ConnectionString, "data source=bootstrap.sqlite;Version=3")
                .SetProperty(Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName)
                .AddAssembly(typeof(Blog).Assembly);

            var sessionFactory = cfg.BuildSessionFactory();

            ForRequestedType<Configuration>().AsSingletons().TheDefault.IsThis(cfg);

            ForRequestedType<ISessionFactory>().AsSingletons()
                .TheDefault.IsThis(sessionFactory);

            ForRequestedType<ISession>().CacheBy(InstanceScope.Hybrid)
                .TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<ISessionFactory>().OpenSession());

            ForRequestedType<IUnitOfWork>().CacheBy(InstanceScope.Hybrid)
                .TheDefaultIsConcreteType<UnitOfWork>();

                ForRequestedType<IDatabaseBuilder>().TheDefaultIsConcreteType<DatabaseBuilder>();
        }
    }
}

Unit Of Work

Recently, I have been in several discussions regarding what the Unit of Work’s (single) responsibility is. Per Martin Fowler’s definition, a Unit of Work “maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.” In practice, NHibernate’s ISession is a Unit of Work.

When I first created my example, I used the ISession directly, but I found myself writing the following code over and over again:

    var product = new Product {Name = "Apple", Category = "Fruits"};
    using (var session = _sessionFactory.OpenSession())
    using (var transaction = _session.BeginTransaction())
    {
        session.Save(product);
        transaction.Commit();
    }

When I really wanted to write this:

    var product = new Product {Name = "Apple", Category = "Fruits"};
    using (var unitOfWork = new UnitOfWork(_sessionFactory))
    {
        unitOfWork.CurrentSession.Save(product);
        unitOfWork.Commit();
    }

So, my Unit of Work is a simple wrapper that combines the ISession and ITransaction together.

using System;
using NHibernate;

namespace NHibernateBootstrap.Core.Persistence
{
    public interface IUnitOfWork : IDisposable
    {
        ISession CurrentSession { get; }
        void Commit();  
    }
}
using NHibernate;

namespace NHibernateBootstrap.Core.Persistence
{
    public class UnitOfWork : IUnitOfWork
    {
        private readonly ISessionFactory _sessionFactory;
        private readonly ITransaction _transaction;

        public UnitOfWork(ISessionFactory sessionFactory)
        {
            _sessionFactory = sessionFactory;
            CurrentSession = _sessionFactory.OpenSession();
            _transaction = CurrentSession.BeginTransaction();
        }

        public ISession CurrentSession { get; private set;}

        public void Dispose()
        {
            CurrentSession.Close();
            CurrentSession = null;
        }

        public void Commit()
        {
            _transaction.Commit();
        }
    }
}

I have heard the argument that this is not a real Unit of Work because it does not track the changes per Martin Fowler's definition. While I agree, I also believe that ISession is not just a Unit of Work either because it includes Get methods that have nothing to do with the Unit of Work. Also, best practices dictate that NHibernate not use implicit transactions. ISession can not be a Unit of Work without requiring the developer to interact with ITransaction. So, my compromise is to create a simple interface that melds NHibernate’s ISession with its ITransaction. I have heard other names for this class such as TransactionBoundary, but that doesn’t sound right to me. I am open to other suggestions. However, please don’t get caught up in the naming or I’ll be forced to change it to an unpronounceable symbol called “The class formerly known as Unit of Work”.

NHibernateModule

Finally, in order to manage the Unit of Work for web applications, I created an HttpModule called NHibernateModule that creates a Unit of Work in the Begin_Request event handler and disposes of it in the End_Request event handler.

using System;
using System.Web;
using NHibernateBootstrap.Core.Persistence;
using StructureMap;

namespace NHibernateBootstrap.Web
{
    public class NHibernateModule : IHttpModule
    {
        private IUnitOfWork _unitOfWork;

        public void Init(HttpApplication context)
        {
            context.BeginRequest += ContextBeginRequest;
            context.EndRequest += ContextEndRequest;
        }

        private void ContextBeginRequest(object sender, EventArgs e)
        {
            _unitOfWork = ObjectFactory.GetInstance<IUnitOfWork>();

        }

        private void ContextEndRequest(object sender, EventArgs e)
        {
            Dispose();
        }

        public void Dispose()
        {
            _unitOfWork.Dispose();
        }
    }
}

NHibernateBootstrap Source Code and Tests

I have created a Google Code project called mvbalaw-commons with the code for NHibernateBootstrap among other things. You can browse the code here or check it out from here.

The sample application uses SQLite. So, the only external requirement is that you have installed ASP.NET MVC in order to run the web application. You will need Ruby and Rake to run the build file. See the README.TXT in the root of the NHibernateBootstrap file for more information getting it up and running.

Note: This example requires a build of StructureMap 2.5.4 after revision 262 which changes “the concrete class behavior so that it can still build a concrete class that is not specified, but it doesn’t get into the GetAllInstances()” per the check-in comment. Hopefully, there will be a new release of StructureMap soon. Until then, feel free to use the StructureMap dll in this project which was built from trunk (revision 263).

NHibernateBootstrap includes four projects:

  • NHibernateBootstrap.Core – fully functional domain and persistence classes to demonstrate NHibernate.
  • NHibernateBootstrap.Tests – integration tests around CRUD operations for a Product class.
  • NHibernateBootstrap.Tests.Environment – a single test that calls ObjectFactory.AssertConfigurationIsValid() to ensure that StructureMap is configured correctly.
  • NHibernateBootstrap.Web – an ASP.NET MVC 1.0 application with a Product CRUD controller.

The sample application bootstraps NHibernate, tests a ProductController, and provides full CRUD operations for a Product through an ASP.NET MVC web application.

In order to improve accessibility, I based my sample application on the one in the Getting Started Guide on NHibernate Forge which originally came from Gabriel Schenker’s excellent NHibernateFAQ series of blog posts.

Also, I started with Ayende’s NHibernate Unit Testing example to get familiar with interacting with SQLite. I left his example in the BlogTestFixture class in the NHibernateBootstrap.Tests project.

So what do you think? You can leave comments here or it might be better to move the discussion over to a discussion thread that I started in the StructureMap Google group to get more people involved.

Tags: ,

kick it on DotNetKicks.com

PrintView Printer Friendly Version

EmailEmail Article to Friend

References (2)

References allow you to track sources for this article, as well as articles that were written in response to this article.
  • Response
    You've been kicked (a good thing) - Trackback from DotNetKicks.com
  • Response
    In NHibernate Bootstrapping with StructureMap, I did not address the issue of transactional boundaries in NHibernate. The example had very simple controller actions that managed their own commits. However, this question on StackOverflow left me wondering who should be responsible for the commit?

Reader Comments (21)

I like your solution. But when I use it in my project, lazy loading becomes a hassle. In requesting lazy loading properties after retrieving a product for example, I get a lazy load exception: "NHibernate.LazyInitializationException: Initializing[<classname> -Could not initialize proxy - no Session." The solution is to eager load these properties on retrieval, but that sort of defeats the purpose of lazy loading. Is there any way to solve this?

January 3, 2011 | Unregistered CommenterJeroen K

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>