0

I have NServiceBus (3.2.2) setup with Castle Windsor as its builder and I'm also using NHibernate. THe problem I have is that within my handlers if I have multiple repositories that need the NHibernate session, they end up with different sessions!

The NServiceBus document states that any transient instances within the container will be treated as singleton instances. Also my NHibernate session is wrapped in a unit of work abstraction.

Here is the code used to setup NServiceBus with NHibernate:

IWindsorContainer container = new WindsorContainer(new XmlInterpreter());
container.Install(new ContainerInstaller());
container.Install(new UnitOfWorkInstaller(AppDomain.CurrentDomain.BaseDirectory, LifestyleType.Transient));
container.Install(new FactoryInstaller(AppDomain.CurrentDomain.BaseDirectory, LifestyleType.Transient));
container.Install(new RepositoryInstaller(AppDomain.CurrentDomain.BaseDirectory, LifestyleType.Transient));

Configure.With()
    .CastleWindsorBuilder(container)
    .FileShareDataBus(Properties.Settings.Default.DataBusFileSharePath)
    .MsmqTransport()
        .IsTransactional(true)
        .PurgeOnStartup(false)
    .UnicastBus()
         .LoadMessageHandlers()
         .ImpersonateSender(false)
     .JsonSerializer();

The UnitOfWorkInstaller is someting like:

var fromAssemblyDescriptor = AllTypes.FromAssemblyInDirectory(new AssemblyFilter(_installationPath));
container.Register(fromAssemblyDescriptor
    .IncludeNonPublicTypes()
    .Pick()
    .If(t => t.GetInterfaces().Any(i => i == typeof(IUnitOfWork)) && t.Namespace.StartsWith("Magma"))
    .WithService.AllInterfaces()
    .Configure(con => con.LifeStyle.Is(_lifeStyleType).UsingFactoryMethod(k => k.Resolve<IUnitOfWorkFactory>().Create())));

So when NHibernate session is need, it gets created with the UnitOfWorkFactory. I tried putting the 'current_session_context_class' property to 'thread_static' in the NHibernate configuration but it didn't work.

Why am I having different unit of work in my NServiceBus handlers?

Francois Joly
  • 307
  • 2
  • 11
  • I do not believe this: The NServiceBus document states that any transient instances within the container will be treated as singleton instances. – mynkow Jun 07 '12 at 12:26
  • @mynkow "NServiceBus creates a child container for each transport message that is received, remember that transport messages can contain multiple “user defined messages”. This means that all transient instances that are created during that message processing is in scoped as singletons within the child container. This allows you to easily share for example the NHibernate session between repositories without mucking around with thread static caching." you can find the relevant documentation [here](http://nservicebus.com/SupportForChildContainers.aspx) – Francois Joly Jun 07 '12 at 13:02
  • it seems it has changed since because looking at the source code you can see the new NServiceBus lifecycle enum `InstancePerUnitOfWork` meaning that "The instance will be singleton for the duration of the unit of work. In practice this means the processing of a single transport message" and this value maps to the `LifestyleType.Scoped` Windsor Castle enum... so I'll try that – Francois Joly Jun 07 '12 at 13:04
  • also, when you use 'current_session_context_class' you should get the session like sessionFactory.GetCurrentSession() – mynkow Jun 07 '12 at 13:15
  • @mynkow yes I'm thinking about refactoring this part of my code so that instead of creating the ISession using a factory method and letting the container manage its life time, I might use NHibernate's session context feature – Francois Joly Jun 07 '12 at 13:30

1 Answers1

1

I got it working by using Castle's LifestyleType.Scoped lifestyle. But then, for now apparent reasons, my handler was called again and again until the message was thrown in the error queue. I had this problem before and it was to do with rollbacking or committing the transaction within the handler. In my unit of work I was reollbacking any uncommitted changes in the Dispose method. The only thing I had to do was only dispose the session and remove the Rollback call.

Francois Joly
  • 307
  • 2
  • 11