2011-11-24 25 views
3

sesions使用同一個版本庫: ASP.NET MVC3 Ninject 2 功能NHibernate如何注入不同的NHibernate會話(多分貝)與控制器controling與Ninject

我有2個數據庫(DB1 & DB2) 。我有一個基礎知識庫類(Repository)和許多控制器(Controller1,Controller2)。

public MyController(IRepository<SomeModelFromDB1> someModelFromDB1Repository, IRepository<SomeModelFromDB2> someModelFromDB2Repository) 
{ 
    [...] 
} 

public class Repository<T> : IRepository<T> where T : Entity 
{ 
    private readonly ISession _session; 

    public Repository(ISessionFactory sessionFactory) 
    { 
     _session = sessionFactory.OpenSession(); 
    } 
} 

public class DB1SessionFactory : ISessionFactory 
{ 
    private readonly NHibernate.ISessionFactory _sessionFactory; 

    private ISession _session; 

    public DB1SessionFactory() 
    { 
     [...] 
    } 
} 

public class DB2SessionFactory : ISessionFactory 
{ 
    private readonly NHibernate.ISessionFactory _sessionFactory; 

    private ISession _session; 

    public DB2SessionFactory() 
    { 
     [...] 
    } 
} 

現在,當我創建MyController。我想注入我的存儲庫,但該存儲庫應該使用DB1(或DB2,取決於模型)SessionFactory。

我想不出如何正確注入這一切......當我只有一個單一的SessionFactory(DB1),在這裏我曾與NINJECT:

kernel.Bind<ISessionFactory>().To<DB1SessionFactory>() 
      .InRequestScope(); 

kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)); 

任何人有什麼想法?


編輯:

最好的將是正確的會話是取決於模型庫注入。由於某些模型來自DB1,而其他模型來自DB2,所以選擇應該依賴於它。如果控制器/視圖開發人員不必擔心任何事情(比如在存儲庫中有[Named]),但是如果這是需要的,這也會很棒。即使使用[Named],我也無法知道如何根據控制器中的[Named]存儲庫在存儲庫中注入正確的會話...

+1

這很大程度上取決於標準時要採取的DB。沒有這些信息,幾乎不可能給你一個很好的答案,因爲有很多方法可以解決這個問題。 –

+0

它最終取決於模型。一些模型在一個數據庫中,而另一些模型在另一箇中。如果邏輯對控制器/視圖開發者隱藏起來會更好,但是我找不到使其工作的方法。當我在控制器構造函數中使用SomeModelDB1Repository和SomeOtherModelDB2Repository時,我希望他們爲每個注入了正確會話的存儲庫。謝謝。 – Nick

回答

2

首先,您應該在singelton作用域中定義會話工廠並在請求範圍內具有會話。

執行配置是這樣的:

.Bind<ISessionFactory>().To<DB1SessionFactory>().Named("DB1") 
    .InSingletonScope(); 

.Bind<ISessionFactory>().To<DB2SessionFactory>().Named("DB2") 
    .InSingletonScope(); 

private bool IsOnDB(IRequest request, string dbName) 
{ 
    var repositoryType = request.ParentRequest.Service; 
    var modelType = repositoryType.GetGenericArguments()[0]; 
    var databaseName = this.GetDatabaseForModel(modelType); 

    return databaseName == dbName; 
} 

.Bind<ISession>() 
    .ToMethod(ctx => ctx.Kernel.Get<ISessionProvider>("DB1").OpenSession()) 
    .When(r => this.IsOnDb(r, "DB1")) 
    .InRequestScope(); 
.Bind<ISession>() 
    .ToMethod(ctx => ctx.Kernel.Get<ISessionProvider>("DB2").OpenSession()) 
    .When(r => this.IsOnDb(r, "DB2")) 
    .InRequestScope(); 
+0

Brillant!它效果很好。我得到的唯一問題是我的會話在我的存儲庫有機會在我將其設置爲InRequestScope時大部分時間使用它之前被關閉...... – Nick

+1

然後,您應該考慮一下您的構架。在網絡請求結束時,所有的數據庫請求都應該完成。不要長時間使用會話,例如網絡會話。 –

+0

如果我想在Web請求中重複使用同一個會話(針對同一個數據庫跨不同存儲庫的同一會話)。會話需要存儲在SessionProvider內部,因爲它被聲明爲「InRequestScope」? – Nick