Using Nhibernate with NServiceBus

Written By : Lam Chan

There is a recent gig where I've been entrenced in NHibernate and NServiceBus.  The current team have been using NHibernate successfully for years, but still new to NServiceBus.  They tried to adopt the same IoC bootstrapping paradigm from the web world which isn't suited to the same task.  Specifically, binding a NHibernate ISession/IUnitofWork interface to a HttpThreadHybrid lifetime scope.  The reason this does not work is because you don't want an NHibernate session to live longer than it needs to.  A Nhibernate session contains a handle to all object for all entities that have been queried.  Everytime a session flush happens, it needs to check all objects in that session for dirtiness.  So even if you queried objects back for lookup only, it will still do a cascade inspection of that object to see if it needs to be updated or removed from the database depending on what your NH mappings dictate.  

With NServiceBus and windows service hosting, these application live on for an indefinite period of time bar exceptions causing the application to need a reboot at the process level.  So if you bootstrap IoC with a thread lifescope of an NHibernate session, the memory will just keep increasing until the application domain crashes.

Here is a simple way to avoid that scenario.

Create a new Lifecycle model.  Since I've been using Structure Map, here is an example of that.  Utilizing the NSB UoW interface, I can then control when to tell Structure Map to release an object from memory.  You can also think of this as a HttpModule equivalent from the MVC/ASP.Net world.

    public class NServiceBusUnitOfWork : ThreadLocalStorageLifecycle, IManageUnitsOfWork
    {
        public void Begin()
        {
            
        }

        public void End(Exception ex = null)
        {
            EjectAll();
        }
    }

Then now in your IoC interface binding syntax, and again in this case using Structure Map as an example.  Use the new life cycle for anything that needs to be dropped for each message transaction in NserviceBus.

For<IUnitOfWork>().LifecycleIs(new NServiceBusUnitOfWork()).Use(x => x.GetInstance<UnitOfWork>());

So this will effectively kill a session off and bring up a new one everytime a message is processed.  This way, there is no memory bleed from objects retrained from previous processing.

Tags: , ,

No comments yet.

Post your comment