2010-06-04 134 views
4

目前我的存储库有2个构造函数。当我从我的mvc网站打电话给我时,我一直在呼叫第一个构造函数,因此打开一个新的会话。我应该通过会议吗?我应该如何做到这一点。nhibernate:存储库会话管理

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>(); 
      } 
     } 

回答

3

您应该使用“每个请求一个会话”的图案,由存储在所述的HttpContext所述的Isession对象和相同的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; 
     } 
    } 
} 

代码尚未既不编译,也不测试......但应该工作。

0

使用控制容器的反转

1

您的代码或,优选地,依赖注入应该总是传递的Isession到存储库的构造。这允许多个存储库参与单个事务。

我第二个Paco的建议,让依赖注入框架为您处理这个。这种方法面临的挑战是非HTTP应用程序,它们没有像HTTP请求 - 响应循环那样的干净工作单元边界。我们有Windows窗体和ASP.NET应用程序共享的存储库,并且我们手动管理Windows窗体应用程序中新建的存储库。

+0

我认为,我正在使用ninject(上面添加的代码)。我如何将会话绑定到CompanyRepository。对不起,这一切还没有点击。 – frosty 2010-06-04 12:08:57

+1

'绑定()。到()。WithConstructorArgument(“session”,NHibernateHelper.OpenSession());'可能有其他方法来做到这一点。 – 2010-06-04 12:34:59

0

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

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