0
votes

I am using NserviceBus 2.5 and was facing the problem NSB caching the Nhibernate Sessions. I spent sometime on internet and found that class implementing IMessageModule interface is the way to solve this. I also saw the implementation of such at https://github.com/NServiceBus/NServiceBus/blob/v2.5/src/impl/SagaPersisters/NHibernateSagaPersister/NServiceBus.SagaPersisters.NHibernate/NHibernateMessageModule.cs

MyEndPoint is defined like

public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomLogging, IWantCustomInitialization
{
    public void Init()
    {
        var location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);

        var windsorContainer = IoCBootstrapper.InitializeForSession(Path.Combine(location, "MyDll.config")); //This line creates Windsor container without Nhibernate Session I have not written real dll.config name  but my code contains


        ISessionFactory sessionFactory = MessageSessionFactory.ConfigureSessionFactory();
        windsorContainer.Kernel.AddComponentInstance<ISessionFactory>(sessionFactory);
        windsorContainer.Register(Component.For(typeof(NHibernateMessageModule)).LifeStyle.Singleton);
        windsorContainer.Register(Component.For(typeof(MessageHandler)).LifeStyle.Transient);


        NServiceBus.Configure.With(AllAssemblies.Except("XYZ.dll"))
            .CastleWindsorBuilder(windsorContainer)
            .XmlSerializer()
            .MsmqTransport()
            .UnicastBus()
            .LoadMessageHandlers();

        SetLoggingLibrary.Log4Net(log4net.Config.XmlConfigurator.Configure);
    }


}

I have defined following class to create SessionFactory public class MessageSessionFactory { protected static ISessionFactory sessionFactory; private static ILog log = LogManager.GetLogger(typeof(MessageSessionFactory));

    public static ISessionFactory ConfigureSessionFactory()
    {
        try
        {
            if (sessionFactory != null) return sessionFactory;

            string connectionString = System.Configuration.ConfigurationManager
                              .ConnectionStrings["SessionFactoryCS"].ToString();
            NHibernate.Cfg.Configuration nHibernateConfiguration =
                                                  new NHibernate.Cfg.Configuration();
            nHibernateConfiguration.SetProperty(
              NHibernate.Cfg.Environment.ProxyFactoryFactoryClass,
              typeof(NHibernate.ByteCode.Castle.ProxyFactoryFactory).AssemblyQualifiedName);
            nHibernateConfiguration.SetProperty(
              NHibernate.Cfg.Environment.Dialect,
              typeof(NHibernate.Dialect.MsSql2005Dialect).AssemblyQualifiedName);
            nHibernateConfiguration.SetProperty(
              NHibernate.Cfg.Environment.ConnectionString, connectionString);
            nHibernateConfiguration.SetProperty(
              NHibernate.Cfg.Environment.FormatSql, "true");
            nHibernateConfiguration.SetProperty(NHibernate.Cfg.Environment.CurrentSessionContextClass,
                                              typeof(NHibernate.Context.ThreadStaticSessionContext).AssemblyQualifiedName);
            nHibernateConfiguration.AddAssembly(Assembly.GetCallingAssembly());

            sessionFactory = nHibernateConfiguration
                                                    .BuildSessionFactory();
            return sessionFactory;
        }
        catch (TypeInitializationException ex)
        {
            throw new Exception("TO DO :Enter message");
        }
    }




}

Whenever I try to start the service I see messages like at HandleEndMessage NHibernate.HibernateException: No current session context configured. at NHibernate.Context.CurrentSessionContext.GetCurrentSessionContext(ISessionFactory factory) at NHibernate.Context.CurrentSessionContext.HasBind(ISessionFactory factory)

If I catch the exception here then this error shifts to HandleError

Could you anybody tell me where I could be wrong?

1

1 Answers

0
votes

that message means that you haven't configured nhibernate to tell it how to use contextual sessions. the nhibernate contextual sessions feature means that nhibernate will manage keeping track of the current session for you and you only need to worry about binding and unbinding the current session to/from the context and any time you ask the session factory for the current session within that context, you will get the same one. the message module andreas wrote makes use of this feature (and you should too in your handlers if that is how you are managing your sessions - meaning that if you have a dependency in your handler classes on ISessionFactory and get sessions from there, you should use ISessionFactory.GetCurrentSession() instead of ISessionFactory.OpenSesion()).

to fix the problem you are seeing, you need to tell NHibernate how to manage the session context. there are several built in options. the one andreas recommends in his blog post is ThreadStatic. this is fine in your case, as it seems you are only connecting to one database and using one session factory. note that this context class only supports one session factory, so it wouldn't work if you are dealing with more than one. thread static means each thread will have its own session context - you will get the same session as long as you are on the same thread. this works nicely with nservicebus as the handler will execute entirely on a thread and the message module will make sure you are getting a new session with each message and not using the same one from the previous message handled by that thread.

to configure nhibernate for this, you need to set the current_session_context_class property to thread_static. if you are configuring nhibernate directly, you know how you are doing it. if you are using fluent nhibernate, you will need to use the FluentConfiguration.ExposeConfiguration method to do this:

Fluently.Configure()
  // whatever else you are doing
  .ExposeConfiguration(
     c => c.SetProperty("current_session_context_class", "thread_static")
    );

here is andreas's post about it: http://andreasohlund.net/2010/02/03/nhibernate-session-management-in-nservicebus/