Castle Windsor Nhibernate 多个数据库会话

Castle Windsor Nhibernate multiple database sessions

我正在尝试在我的城堡温莎容器中为 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)

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

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

  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;
            }
        }
}

它有效 well.This 如果我正确理解你的问题,可能会对你有所帮助。

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

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

我实现的关键是让我的不同存储库位于不同的命名空间中,并让 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()

        );
}