« 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 (18)

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?
  • Response
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: google.com
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: valentino outlet
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: Lycan
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: nfl jerseys cheap
    Your trip seriously becomes unforgettable, if you get likelihood to take pleasure in your favorite sport at your holiday destination. So, if you're preparing a trip, why not program a sporting getaway in Spain
  • Response
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: Sophie Dennis
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: Saleh Stevens
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: revit architecture
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: browse this site
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: landscape design
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap
  • Response
    Response: grilling tools
    Weston Binford - Journal - Bootstrapping NHibernate with StructureMap

Reader Comments (21)

Very nice example.

One thing I have struggled with is the best way to start and end the unit of work. Your example uses the begin and end request events. I have found that when using IIS7's integrated pipeline this results in the unit of work being initialized for every request, including images, css and javascript files. Have you encountered this problem and do you know a fix? Thanks.

October 7, 2009 | Unregistered CommenterLiam McLennan

Often times I have scenario's that require a 'conversation' - where the unit of work is tracking across several request/responses - ie. storing it in the session.

I would like to see your unit of work include support for that, as well as providing a separate unit of work (ie. the ability to create another unit of work instance within the conversation unit of work)

Great example - thank you

October 7, 2009 | Unregistered CommenterSteve

This looks great Weston. I started getting my feet wet with NH using the SharpArchitecture, which handles a lot of NH stuff for you in their libraries. I've combed through the code to see how Billy was doing things and I have to say that I think this is really clean.

October 8, 2009 | Unregistered CommenterCorey Coogan

@corey

Yes, I looked at SharpArchitecture as well. One of the reasons why I believe that his implementation has complexity is that it supports multiple database connections. I don't have that requirement. That being said, I have taken a lot of inspiration from Billy McCafferty's work and I think that S#harp Architecture has a lot of good examples. If you are looking for a very comprehensive example using ASP.NET MVC and NHibernate, Sharp Architecture is a great resource.

October 8, 2009 | Registered CommenterWeston M. Binford III

@liam

That is a great catch! This example was developed using the developer web server (Cassini) that comes with Visual Studio 2008, but I believe it would create a Unit of Work for every request including image, css, and javascript in IIS7's integrated pipeline. I'll have to think about a way to exclude those requests. In the meantime, I am not that worried because an ISession is a lightweight resource and creating it for those requests should not generate too much overhead.

October 8, 2009 | Registered CommenterWeston M. Binford III

@steve

There was a discussion about long running conversations on the NHibernate Google group last summer. I have to agree with the thread that Session per HttpRequest is the preferred configuration. That has worked well for us.

-Weston

October 8, 2009 | Registered CommenterWeston M. Binford III

@liam

I haven't had a chance to try it for myself, but I think this issue on StackOverflow may address your concern.

October 8, 2009 | Unregistered CommenterWeston M. Binford III

How does the UnitofWork HttpHandler make its way into the constructor.
I can't see how the

private IUnitOfWork _unitOfWork;

in the handler links to the rest the UnitOfWork used in the application.
Thanks

October 9, 2009 | Unregistered CommenterAdam

@adam

NHibernateModule uses ServiceLocator ( ObjectFactory.GetInstance<IUnitOfWork>() ) to get the IUnitOfWork from StructureMap. In, NHibernateRegistry, the configuration for IUnitOfWork, uses CacheBy(InstanceScope.Hybrid) which means that StructureMap is storing the concrete UnitOfWork in the HttpContext. The same HttpContext object is shared between HttpModules and the request handler.

October 9, 2009 | Registered CommenterWeston M. Binford III

Weston -

I was unclear on the purpose of placing the Session into IoC container, especially when the UoW manages it's Session. Was the Session in the IoC used elsewhere?

Otherwise, this was my first time wokring with StructureMap (had been using Unity)...what a great introduction. I am going to have a hard time going back to Unity :)

Chuck

October 11, 2009 | Unregistered CommenterChuck

@chuck,

I made the ISession available directly from StructureMap prior to introducing the UnitOfWork. I left it exposed to give the developer more options. For example, you may not want to use a transaction when reading from the database.

However, I am reconsidering the use of ISession without using an ITransaction. See Alert: Use of implicit transactions are discouraged from the NHibernate Profiler site.

October 12, 2009 | Registered CommenterWeston M. Binford III

Never liked the httpmodule always forgot to add it to the web.config. I like ayende's way much better to bind it direct to the event off the httpapplication and use the CurrentSessionContext in nhibernate to handle my session. I think it fits nice with structuremap.

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

Otherwise I think your on the right track.

October 16, 2009 | Unregistered CommenterMagnus Bertilsson

Just wondering about letting StructureMap open session. Would this not render SessionFactory.GetCurrentSession() usless, since we are not binding it using CurrentSesisonContext? If we had code that did not use StructureMap there would be not way for it to get hold of the current session?

November 19, 2009 | Unregistered CommenterEdvard Pitka

Weston,

I started on a project similar to this almost a full year ago, today I just completed it that I feel I am satisfied. I also achieved this with no http modules or inclusion of postbuild weaving AOP frameworks. If you have some time I'd appreciate some feedback or to use any my ideas with your project! http://dotnetchris.wordpress.com/2009/12/18/implementing-nhibernate-long-conversation-with-no-httpmodules-or-aop-build-time-weaving/

December 18, 2009 | Unregistered CommenterChris Marisic

I didn't understand the concluding part of your article, could you please explain it more?

March 10, 2010 | Unregistered Commenterdjnaff

Why even bother with the HttpModule? As long as you use the using block in your code, Dispose will be called on the IUnitOfWork. Then you won't be opening up sessions for things like static image requests.

April 5, 2010 | Unregistered CommenterKevin Pang

Hi Weston,

Sorry for my question if you think it's not right.

I think we should not create IUnitOfWork interface because you had a ISession property in it, so we can not re-use if we use EF, linq2sql ....

In my opinion, we just need to create UnitOfWork that inherit from IDispose.

Thanks,
Zorro.

April 24, 2010 | Unregistered Commenterzorro

Thanks for the example. I found it very helpful without being overly complex.

Have you thought about how this might change using the new nested container functionality in StructureMap?

June 25, 2010 | Unregistered CommenterMike Henry

I wonder if there could be an issue with the _unitOfWork field in NHibernateModule? I believe NHibernateModule will have the lifetime of the web application, and thus _unitOfWork will span many requests. Could two concurrent requests attempt to use _unitOfWork at the same time thus causing one request to refer to the other requests unit of work?

July 1, 2010 | Unregistered CommenterMike Henry

I dont think you need NHibernateModule at all because you have already wired up UnitOfWork in the NHibernateRegistry class with InstanceScope.Hybrid, therefore Structure map will create UnitOfWork for you for each httprequest.

July 14, 2010 | Unregistered Commenterhussain

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>