2011-11-24 2 views
3

와 sesions 컨트롤러 및 관리와 같은 저장소에 다른 NHibernate에 세션 (멀티 DB)를 주입 : 나는이 데이터베이스가 ASP.NET MVC3 Ninject에 2 유창함 nHibernate 수어떻게 사용 Ninject에

을 (DB1 & DB2) . 하나의 기본 저장소 클래스 (저장소)와 많은 컨트롤러 (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<>)); 

누구가 어떤 생각을 가지고?


편집 :

가장 오른쪽 세션이 모델에 따라 저장소에 주입되는 것이다. 일부 모델은 DB2에서 DB1 및 다른 모델로부터 왔기 때문에 선택 사항은 DB2에서 종속적이어야합니다. 컨트롤러/뷰 개발자가 (저장소 앞에 [Named]가있는 것과 같은) 무엇인가를 신경 쓰지 않아도되지만 그것이 필요한 경우라면 좋을 것입니다. [Named]라고하더라도 컨트롤러의 [Named] 저장소를 기반으로 저장소에 적절한 세션을 삽입하는 방법을 알 수 없습니다 ...

+1

이 기준에 크게 의존한다. 이 정보가 없으면이 문제를 해결할 수있는 많은 방법이 있으므로 좋은 답변을 제공하는 것은 거의 불가능합니다. –

+0

궁극적으로 모델에 따라 다릅니다. 일부 모델은 하나의 DB에 있고 다른 모델은 다른 DB에 있습니다. 그 논리가 컨트롤러/뷰 개발자에게 숨겨져 있지만 작동하도록하는 방법을 찾을 수 없다면 더 좋을 것입니다. 내가 SomeModelDB1Repository와 SomeOtherModelDB2Repository를 가지고있는 컨트롤러 생성자에서 적절한 세션이 주입 된 저장소를 갖기를 바랍니다. 감사. – Nick

답변

2

우선 세션 범위를 싱글 톤 범위로 정의해야합니다 요청 범위의 세션을 가져야합니다.

은 다음과 같이 구성을 수행하는 DB를 취할 때

.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

웹 요청 (동일한 DB에 대해 다른 리포지토리에서 동일한 세션)에서 동일한 세션을 다시 사용하고 싶습니다. Session이 "InRequestScope"로 선언되었으므로 세션을 SessionProvider 내에 저장해야합니까? – Nick