Castle Windsor Nhibernate多个数据库会话

时间:2015-09-29 14:32:44

标签: asp.net-mvc-4 nhibernate fluent-nhibernate castle-windsor

我正在尝试在我的城堡windsor容器中为2个不同的NHibernate会话注册多个命名组件,并根据不同的接口(IRepository,IReadOnlyRepository)注入适当的NHibernate会话。

我正在使用AbstractFacility注册我的ISession和ISessionFactory:

public class PersistenceFacility : AbstractFacility
{
    private const string DBCONNECTFACTORY = "dbconnectfactory";
    private const string ODSCONNECTFACTORY = "odsconnectfactory";
    private const string DBCONNECT = "dbconnect";
    private const string ODSCONNECT = "odsconnect";

    protected override void Init()
    {
        Kernel.Register(
            Component.For<ISessionFactory>()
                .UsingFactoryMethod(CreateDBConnectSessionFactory)
                .LifeStyle
                .Singleton
                .Named(DBCONNECTFACTORY),

            Component.For<ISessionFactory>()
                .UsingFactoryMethod(CreateODSConnectSessionFactory)
                .LifeStyle
                .Singleton
                .Named(ODSCONNECTFACTORY)
        );

        Kernel.Register(
            //Nhibernate session
            Component.For<ISession>()
                .UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>(DBCONNECTFACTORY).OpenSession())
                .LifeStyle
                .PerWebRequest
                .Named(DBCONNECT),

            Component.For<ISession>()
                .UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>(ODSCONNECTFACTORY).OpenSession())
                .LifeStyle
                .PerWebRequest
                .Named(ODSCONNECT)
        );
    }

    private static ISessionFactory CreateDBConnectSessionFactory()
    {
        return Fluently.Configure()
            .Database(NhOracleConfiguration.Dialect.ConnectionString(x => x.FromConnectionStringWithKey("DBConnect")))
            .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetAssembly(typeof(StudentMapping))))
            .BuildSessionFactory();
    }

    private static ISessionFactory CreateODSConnectSessionFactory()
    {
        return Fluently.Configure()
            .Database(NhOracleConfiguration.Dialect.ConnectionString(x => x.FromConnectionStringWithKey("ODSConnect")))
            .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetAssembly(typeof(ReadOnlyStudentMapping))))
            .BuildSessionFactory();
    }
}

以上内容适用于单个ISession,但我现在需要多个,这是我的尝试。

我正在注册我的存储库,如下所示:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;

    container.AddFacility(new PersistenceFacility());

    // Register all controllers
    container.Register(
        // Unitofwork interceptor
        Component.For<NhUnitOfWorkInterceptor>().LifeStyle.PerWebRequest,

        // All validators
        Classes.FromAssembly(Assembly.GetAssembly(typeof(StudentValidator))).BasedOn(typeof(IValidator<>)).WithService.Base().LifestyleTransient(),

        // All repositories
        Classes.FromAssembly(Assembly.GetAssembly(typeof(NhStudentRepository)))
            .InSameNamespaceAs<NhStudentRepository>()
            .WithService.DefaultInterfaces()
            .LifestyleTransient(),

        // All services
        Classes.FromAssembly(Assembly.GetAssembly(typeof(StudentService))).InSameNamespaceAs<StudentService>().WithService.DefaultInterfaces().LifestyleTransient()

        );
}

上面的代码正在注册所有存储库(IRepository和IReadOnlyRepository),因为它们位于同一名称空间中。

如何确保将适当的ISession注入正确的存储库? (IRepository,IReadOnlyRepository)

我的方法是否正朝着正确的方向前进?我当然愿意完全改变我注册组件和依赖项的方式。

2 个答案:

答案 0 :(得分:2)

我使用以下配置尝试了您的代码;

  public class Repository<T>:IRepository<T> where T:class 
  {


    public T GetById(string id)
    {

        return UnitOfWork.CurrentDBSession.Get<T>(id);

    }   


    }

public class UnitOfWork
{
      public static ISession CurrentDBSession
        {
            get
            {
                var session = IoC.Container.Resolve<ISession>("dbconnect");
                return session;
            }
        }
}

它运作良好。如果我理解你的问题,这可能对你有所帮助。

答案 1 :(得分:1)

我在注册两个不同的存储库类(IRepository,IReadOnlyRepository)时使用ServiceOverride解决了这个问题。

我很想看到更新的解决方案,因为在Castle Windsor 3.0之后,ServiceOverride似乎已被弃用。

我的实现的关键是让我的不同存储库存在于不同的命名空间中,让Castle Windsor为每个存储库注册一个不同的命名ISession组件:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;

    container.AddFacility(new PersistenceFacility());

    // Register all controllers
    container.Register(
        // Unitofwork interceptor
        Component.For<NhUnitOfWorkInterceptor>().LifeStyle.PerWebRequest,

        // All validators
        Classes.FromAssembly(Assembly.GetAssembly(typeof(StudentValidator))).BasedOn(typeof(IValidator<>)).WithService.Base().LifestyleTransient(),

        // All repositories
        Classes.FromAssembly(Assembly.GetAssembly(typeof(NhStudentRepository)))
            .InSameNamespaceAs<NhStudentRepository>()
            .WithService.DefaultInterfaces()
            .Configure(c =>
            {
                c.DependsOn(
                    ServiceOverride
                        .ForKey<ISession>()
                        .Eq(DBCONNECT)
                    );
            })
            .LifestyleTransient(),

        // All read only repositories
        Classes.FromAssembly(Assembly.GetAssembly(typeof(NhCourseRepository)))
            .InSameNamespaceAs<NhCourseRepository>()
            .WithService.DefaultInterfaces()
            .Configure(c => 
                {
                    c.DependsOn(
                        ServiceOverride
                            .ForKey<ISession>()
                            .Eq(ODSCONNECT)
                        );
                })
            .LifestyleTransient(),

        // All services
        Classes.FromAssembly(Assembly.GetAssembly(typeof(StudentService))).InSameNamespaceAs<StudentService>().WithService.DefaultInterfaces().LifestyleTransient()

        );
}