nhibernate:存储库会话管理

时间:2010-06-04 09:51:32

标签: nhibernate

目前我的存储库有2个构造函数。当我从我的mvc网站上调用这些时,我总是调用第一个构造函数,从而打开一个新的会话。我应该在会议上通过吗?我该怎么做呢

    public CompanyRepository()
    {
        _session = NHibernateHelper.OpenSession();
    }

    public CompanyRepository(ISession session)
    {
        _session = session;
    }




public class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;

        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                    var configuration = new Configuration();
                    configuration.Configure();
                    configuration.AddAssembly(typeof(UserProfile).Assembly);
                    configuration.SetProperty(NHibernate.Cfg.Environment.ConnectionStringName,
                                              System.Environment.MachineName);
                    _sessionFactory = configuration.BuildSessionFactory();
                }
                return _sessionFactory;
            }
        }

        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }
    }

我正在使用Ninject IOC容器(对我来说很新)。我有以下容器。我如何将ISession绑定到CompanyRepository。

 private class EStoreDependencies : NinjectModule
        {
            public override void Load()
            {
                Bind<ICompanyRepository>().To<CompanyRepository>();
                Bind<IUserProfileRepository>().To<UserProfileRepository>();
                Bind<IAddressRepository>().To<AddressRepository>();
                Bind<IRolesService>().To<AspNetRoleProviderWrapper>();
                Bind<IUserService>().To<AspNetMembershipProviderWrapper>();
                Bind<ICurrentUserSerivce>().To<DefaultCurrentUserSerivce>();
                Bind<IPasswordService>().To<AspNetMembershipProviderWrapper>();
                Bind<IStatusResponseRepository>().To<StatusResponseRepository>();
                Bind<ICategoryRepository>().To<CategoryRepository>();
                Bind<IProductRepository>().To<ProductRepository>();
            }
        }

4 个答案:

答案 0 :(得分:3)

您应该使用“每个请求一个会话”模式,方法是将ISession对象存储在HttpContext中,并在存储库和同一HTTP请求期间进行的查询之间共享。

这是一个implementation using MVC action attributes

通过简单地改变你的NHibernateHelper类也可以实现简单/基本的实现:

public class NHibernateHelper {
    //...

    const string SessionKey = "NhibernateSessionPerRequest";

    public static ISession OpenSession(){
        var context = HttpContext.Current;

        if(context != null && context.Items.ContainsKey(SessionKey)){
            //Return already open ISession
            return (ISession)context.Items[SessionKey];
        }
        else{
            //Create new ISession and store in HttpContext
            var newSession = SessionFactory.OpenSession();
            if(context != null)
                context.Items[SessionKey] = newSession;

            return newSession;
        }
    }
}

代码既没有编译也没有经过测试......但是应该可以工作。

答案 1 :(得分:1)

您的代码或最好是依赖注入应始终将ISession传递到存储库的构造函数中。这允许多个存储库参与单个事务。

我第二次推荐Paco让依赖注入框架为你处理这个问题。这种方法面临的挑战是非Web应用程序没有像HTTP请求 - 响应周期那样的干净的工作单元边界。我们拥有Windows窗体和ASP.NET应用程序共享的存储库,我们手动管理Windows窗体应用程序中的新增存储库。

答案 2 :(得分:0)

使用控制容器的反转

答案 3 :(得分:0)

尝试使用sessionFactory.GetCurrentSession(),它允许您访问contextual session

这基本上允许您使用另一个答案中描述的'每个请求的会话'模型,而无需自己编写代码。 您甚至可以选择您的上下文:Http(如您的示例所示)或其他一些(我使用CallSessionContext进行单元测试)。

相关问题