2010-06-04 100 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進行單元測試)。