如何将不同的NHibernate会话(multi-db)注入到同一个存储库中,控制器控制使用Ninject的会话



使用:ASP.NET MVC39项目2Fluent nHibernate

我有两个数据库(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(时,以下是我对NINEJECT:的了解

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

编辑:

最好的方法是根据模型在存储库中注入正确的会话。由于一些模型来自DB1,而另一些来自DB2,因此选择应该取决于它。如果控制器/视图开发人员不必为任何事情(比如在存储库前面有[Named](而烦恼,但前提是这是需要的,那也会很好。即使使用了[Named],我也不知道如何基于控制器中的[Named]repository在存储库中注入正确的会话。。。

首先,您应该在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();

最新更新