Asp.net mvc 如何将不同的NHibernate会话(多数据库)注入到同一个存储库中,控制器通过Ninject控制哪些会话
使用: ASP.NET MVC3 Ninject 2 流畅的纤维酸盐 我有两个数据库(DB1和DB2)。我有一个基本存储库类(repository)和许多控制器(Controller1、Controller2)Asp.net mvc 如何将不同的NHibernate会话(多数据库)注入到同一个存储库中,控制器通过Ninject控制哪些会话,asp.net-mvc,nhibernate,ninject,Asp.net Mvc,Nhibernate,Ninject,使用: ASP.NET MVC3 Ninject 2 流畅的纤维酸盐 我有两个数据库(DB1和DB2)。我有一个基本存储库类(repository)和许多控制器(Controller1、Controller2) 公共MyController(IRepository someModelFromDB1Repository,IRepository someModelFromDB2Repository) { [...] } 公共类存储库:IRepository,其中T:Entity { 专用只读会话;
公共MyController(IRepository someModelFromDB1Repository,IRepository someModelFromDB2Repository)
{
[...]
}
公共类存储库:IRepository,其中T:Entity
{
专用只读会话;
公共存储库(ISessionFactory sessionFactory)
{
_session=sessionFactory.OpenSession();
}
}
公共类DB1会话工厂:ISessionFactory
{
私有只读NHibernate.ISessionFactory\u sessionFactory;
非公开会议;
公共DB1SessionFactory()
{
[...]
}
}
公共类DB2SessionFactory:ISessionFactory
{
私有只读NHibernate.ISessionFactory\u sessionFactory;
非公开会议;
公共DB2SessionFactory()
{
[...]
}
}
现在,当我创建MyController时。我希望注入我的存储库,但该存储库应该使用DB1(或DB2,取决于模型)SessionFactory
我想不出如何正确地将其全部注入。。。当我只有一个SessionFactory(DB1)时,这里是我与NINJECT的关系:
kernel.Bind<ISessionFactory>().To<DB1SessionFactory>()
.InRequestScope();
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
kernel.Bind()到()
.InRequestScope();
Bind(typeof(IRepository)).To(typeof(Repository));
编辑:
最好是根据模型在存储库中注入正确的会话。由于一些模型来自DB1,而另一些来自DB2,因此选择应该依赖于它。如果控制器/视图开发人员不必为任何事情操心(比如在存储库前面有[Named]),但如果这是必要的,那也太好了。即使使用了[Named],我也不知道如何根据控制器中的[Named]存储库在存储库中注入正确的会话…首先,您应该在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();
.Bind().To().Named(“DB1”)
.InSingletonScope();
.Bind().To().Named(“DB2”)
.InSingletonScope();
私有bool IsOnDB(IRequest请求,字符串dbName)
{
var repositoryType=request.ParentRequest.Service;
var modelType=repositoryType.GetGenericArguments()[0];
var databaseName=this.GetDatabaseForModel(modelType);
返回databaseName==dbName;
}
.Bind()
.ToMethod(ctx=>ctx.Kernel.Get(“DB1”).OpenSession())
.When(r=>this.IsOnDb(r,“DB1”))
.InRequestScope();
.Bind()
.ToMethod(ctx=>ctx.Kernel.Get(“DB2”).OpenSession())
.When(r=>this.IsOnDb(r,“DB2”))
.InRequestScope();
这在很大程度上取决于何时采用哪个DB的标准。如果没有这些信息,几乎不可能给你一个好的答案,因为有很多方法可以解决这个问题。这最终取决于模型。一些模型在一个数据库中,其他模型在另一个数据库中。如果对控制器/视图开发人员隐藏该逻辑会更好,但我找不到使其工作的方法。在控制器构造函数中,我有一些ModelDB1Repository和一些其他ModelDB2Repository,我希望它们都有一个带有正确会话的存储库。谢谢,聪明人!它工作得很好。我遇到的唯一问题是,当我将会话设置为InRequestScope时,在我的存储库有机会大部分时间使用它之前,会话就被关闭了……那么你应该考虑一下你的架构。在web请求结束时,应完成所有数据库请求。不要长时间使用会话,例如web会话。如果我想在web请求中重用同一会话(同一数据库的不同存储库中的同一会话)。会话是否需要存储在SessionProvider中,因为它声明为“InRequestScope”?否。这将导致错误的结果,因为会话提供程序是单例的,并且您将为不同的web请求重用会话。在这种情况下,你会有非常奇怪的行为。让Ninject决定谁获得哪个会话,而不是会话提供程序。您甚至不需要实现自己的会话工厂,只需使用两个正确配置的NHibernate会话工厂实例即可。
.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();