Question

i'm working in a new project and i'm trying to implement nhibernate with ninject in asp.net mvc. I'm having the error:

NHibernate.HibernateException: No session bound to the current context

Below is the code i'm using:

using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Conventions.Helpers;
using NHibernate;
using NHibernate.Context;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TestNhibernateSessions
{
    public class SessionFactory : IHttpModule
    {
        private static readonly ISessionFactory _SessionFactory;
        static SessionFactory()
        {
            _SessionFactory = CreateSessionFactory();
        }
        public void Init(HttpApplication context)
        {
            context.BeginRequest += BeginRequest;
            context.EndRequest += EndRequest;
        }
        public void Dispose()
        {
        }
        public static ISession GetCurrentSession()
        {
            return _SessionFactory.GetCurrentSession();
        }

        private static void BeginRequest(object sender, EventArgs e)
        {
            ISession session = _SessionFactory.OpenSession();
            session.BeginTransaction();
            CurrentSessionContext.Bind(session);
        }

        private static void EndRequest(object sender, EventArgs e)
        {
            ISession session = CurrentSessionContext.Unbind(_SessionFactory);
            if (session == null) return;
            try
            {
                session.Transaction.Commit();
            }
            catch (Exception)
            {
                session.Transaction.Rollback();
            }
            finally
            {
                session.Close();
                session.Dispose();
            }
        }

        private static ISessionFactory CreateSessionFactory()
        {
            return Fluently.Configure()
                           .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("DefaultConnection")))
                           .Mappings(m => m.AutoMappings.Add(CreateMappings()))
                           .CurrentSessionContext<WebSessionContext>()
                           .BuildSessionFactory();
        }

        private static AutoPersistenceModel CreateMappings()
        {
            return AutoMap
                .Assembly(System.Reflection.Assembly.GetCallingAssembly())
                .Where(t => t.Namespace != null && t.Namespace.EndsWith("Domain"))
                .Conventions.Setup(c => c.Add(DefaultCascade.SaveUpdate()));
        }
    }
}

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(TestNhibernateSessions.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(TestNhibernateSessions.App_Start.NinjectWebCommon), "Stop")]

namespace TestNhibernateSessions.App_Start
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;
    using TestNhibernateSessions.Repository;
    using TestNhibernateSessions.Service;
    using NHibernate;


    public static class NinjectWebCommon
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        /// <summary>
        /// Stops the application.
        /// </summary>
        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            try
            {
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

                RegisterServices(kernel);
                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {



            kernel.Bind<IProductRepository>().To<ProductRepository>();
            kernel.Bind<IProductService>().To<ProductService>();


        }
    }
}
Was it helpful?

Solution

Since you're using Ninject, my recommendation is to use it to inject the session factory rather than an IHttpModule. To do so, create Ninject Provider classes as shown below. Note that this requires transaction management in code, I dislike the idea of blindly holding a transaction open during a request.

public class SessionFactoryProvider : Provider<ISessionFactory>
{
    protected override ISessionFactory CreateInstance(IContext context)
    {
        return Fluently.Configure()
                       .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("DefaultConnection")))
                       .Mappings(m => m.AutoMappings.Add(CreateMappings()))
                       .CurrentSessionContext<WebSessionContext>()
                       .BuildSessionFactory();
    }
}

public class SessionProvider : Provider<ISession>
{
    protected override ISession CreateInstance(IContext context)
    {
        var sessionFactory = context.Kernel.Get<ISessionFactory>();
        var session = sessionFactory.OpenSession();
        session.FlushMode = FlushMode.Commit;
        return session;
    }
}

Then in NinjectWebCommon:

private static void RegisterServices(IKernel kernel)
{
    // session factory instances are singletons
    kernel.Bind<ISessionFactory>().ToProvider<SessionFactoryProvider>().InSingletonScope();
    // session-per-request
    kernel.Bind<ISession>().ToProvider<SessionProvider>().InRequestScope();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top