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: NHibernate, 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.
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
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.
@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.
@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.
@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
@liam
I haven't had a chance to try it for myself, but I think this issue on StackOverflow may address your concern.
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
@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.
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
@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.
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.
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?
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/
I didn't understand the concluding part of your article, could you please explain it more?
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.
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.
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?
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?
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.