2010-08-19 4 views
2

내가 과거에 제기 된 세션 관리의 문제를 알고 있지만 나는 내 문제를 극복하는 데 도움이 아무것도 찾을 수 없습니다 .. 캐슬 윈저를 통해 해결 한 저장소 클래스 (예 : CustomerRepository, ProductRepository 등) (참고 : here의 설명과 같이 세 가지 호출 패턴을 적용하려고합니다). 나는 내가 Presenter 당 세션을 가질 것이라고 생각한다. (제 경우에는 이것은 폼 당 하나의 세션과 동일하다.) 그러나 저장소 클래스는 현재 활성화 된 폼에 대한 세션에 액세스해야한다. 나는 이것을 어떻게 통합하는지 잘 모르겠다. 발표자는 싱글이 아니기 때문에 이러한 저장소가, 윈저 통해 해결하고 있다는 사실 .. 예를 들어NHibernate에, 윈폼, 성 윈저 : 세션 관리</p> <p>나는의 번호를 가지고

로 :

public class SomePresenter 
{ 
    private ISomeView view; 
    private ISession session; 
    private ICustomerRepository customerRepository; 
    private IOrderRepository orderRepository; 

    public SomePresenter(ISomeView view, ISessionFactory sessionFactory, ICustomerRepository customerRepository, IOrderRepository orderRepository) 
    { 
    this.view = view; 
    this.session = sessionFactory.OpenSession(); 
    this.customerRepository = customerRepository; 
    this.orderRepository = orderRepository; 
    } 
} 

레포지토리 세션에 액세스해야 ... 이걸 어떻게 사용 윈저 가야합니까 ? 속성을 통해 리포지토리에 세션을 수동으로 설정해야합니까? 아니면 익숙하지 않은 영리한 Windsor 트릭이 있습니까?

+0

레코드의 경우 현재 접근 방식 이외의 제안을 열어 두었습니다. –

답변

4

왜 당신의 저장소 대신의 ISessionFactory로의 ISession를 주입하지 ?

여기에 내가 Autofac, 다른 IoC 컨테이너로 사용하는 유사 코드 :

containerBuilder 
    .Register(c => NHibernateContext.GetSessionFactory().OpenSession()) 
    .As<ISession>() 
    .InstancePerLifetimeScope(); 

NHibernateContext 내 하나 자 NHibernate를 구성하고 ISessionFactory 싱글에 보유하고 정적 클래스입니다.

그래서 내 저장소/조회 객체는 세션을 요청 : 그냥 그런

public MyRepository(ISession session) 
{ 
    this.session = session; 
} 

내 발표자/전망 모델/Superivsing 컨트롤러/무엇이든간에 - 더 - 지옥 - 다 왔어요 - 통화 -이 -이 - 월 그것은

같은 것

public MyPresenter(IWhateverRepository repository) 
{ 
    // Look ma, the repository has an ISession and I'm none the wiser! 
} 

윈저, 나는 생각 (나는 그것의 API와 정말 익숙하지 해요, 당신이 조정할 수있다 그러나 그것은 당신에게 아이디어를 줄 것이다) : 저장소 또는 조회 오브젝트 가져

container.Register(
    Component.For<ISession> 
    .UsingFactoryMethod(
     x => x.Resolve<ISessionFactory>().OpenSession()) 
    .LifeStyle.Transient); 

즉, "누군가가 ISession을 요청하면이 작은 대리인을 실행하여 ISessionFactory을 얻은 다음 세션을 열고 그 다음에 ISession 인스턴스를 제공하십시오."

그러나 누가 ISession을 종료합니까? 귀하에게 달려 있습니다. 저장소에서 명시 적으로 ISession을 자신의 Dispose() 방법으로 닫을 수 있습니다. 또는 컨테이너를 닫고 처리하는 데 의존 할 수 있습니다. Autofac에서는 ILifetimeScopeInstancePerLifetimeScope()으로이 작업을 수행합니다. Windsor에서 하위 컨테이너를 처리 할 때 생성 된 모든 구성 요소도 삭제되도록 중첩 된 컨테이너를 검색해야한다고 생각합니다.

내 경험에 따르면 이것은 일반적으로 컨테이너가 적어도 내 응용 프로그램의 "기본 양식"으로 누출된다는 것을 의미합니다. 양식을 만들 때 새로운 수명 범위/중첩 컨테이너가 만들어지고 양식이 표시됩니다. 그러나이 수준 아래의 어떤 것도 컨테이너에 대해 안다. 단지 구성 요소 집합 주위에 올가미를 던져 양식이 닫힐 때 "이 모든 것을 제거하십시오"라고 말하면됩니다.

(이것은 대부분의 응용 프로그램에서 사용되는 하나의 큰 호킹을 방지하기위한 것입니다. ASP.NET에서 요청 당 하나의 세션이 제대로 작동하지만 Windows Forms에서는 똑딱 거리는 것처럼 보입니다. 각 작업 단위 (일반적으로 각 양식 또는 서비스)가 자신의 ISession이되도록하는 것이 더 좋습니다.

각 방법마다 ISession이 통과하도록 저장소를 디자인 할 수 있습니다 그게 지겨운 것처럼 보입니다.

희망은 당신에게 몇 가지 아이디어를 제공합니다. 행운을 빕니다!

+1

사운드 접근법처럼 보입니다 ...하지만, 한 가지 문제가 있습니다. (의도를 잘못 해석하지 않는 한);) Mypresenter에 CustomerRepository와 OrderRepository가 필요한 경우에는 어떻게해야합니까? 그들은 동일한 세션을 공유해야합니다. 내가 틀렸다면 올바른 코드를 기반으로, 새로운 세션이 각 저장소에 대해 열릴 것입니까? –

+0

Autofac에는 평생 범위의 개념이 있습니다. 따라서 동일한 발표자의 종속성이 동일한 수명 범위에서 해결되어 동일한 ISession을 공유하도록해야합니다. 윈저에서는 중첩 된/하위 컨테이너를 검색해야합니다. 나는 Windsor가 그것을지지한다고 확신하지만, 나는 그 용어에 어렴풋이다. 사용 (VAR childScope this.container.BeginLifeTimeScope =()) {// 하나 ISession) (이 범위 VAR 표현 = this.childScope.Resolve 이내; // 할 일 } // 여기에 처리 된 Session –

1

각 발표자/컨트롤러에 대해 에 개별 Data Access Objects (DAO)이 하나만있는 것은 아닙니까? 모델은 Data Access Object을 통해 액세스 할 수 있습니다.

public sealed class SessionProvider 
{ 
     static readonly SessionProvider provider = new SessionProvider(); 
     private static NHibernate.Cfg.Configuration config; 
     private static ISessionFactory factory; 
     static ISession session = null; 

     /// <summary> 
     /// Initializes the <see cref="SessionProvider"/> class. 
     /// </summary> 
     static SessionProvider() { } 

     /// <summary> 
     /// Gets the session. 
     /// </summary> 
     /// <value>The session.</value> 
     public static ISession Session 
     { 
      get 
      { 
       if (factory == null) 
       { 
        config = new NHibernate.Cfg.Configuration(); 
        config.Configure(); 

        factory = config.BuildSessionFactory(); 
       } 

       if (session == null) 
       {     
        if (config.Interceptor != null) 
         session = factory.OpenSession(config.Interceptor); 
        else 
         session = factory.OpenSession(); 
       } 

       return session; 
      } 
     } 
    } 

public sealed class OrderDataControl 
{ 

     private static ILog log = LogManager.GetLogger(typeof(OrderDataControl)); 

     private static OrderDataControl orderDataControl; 
     private static object lockOrderDataControl = new object(); 
     /// <summary> 
     /// Gets the thread-safe instance 
     /// </summary> 
     /// <value>The instance.</value> 
     public static OrderDataControl Instance 
     { 
      get 
      { 
       lock (lockOrderDataControl) 
       { 
        if (orderDataControl == null) 
         orderDataControl = new OrderDataControl(); 
       } 
       return orderDataControl; 
      }   
     } 

     /// <summary> 
     /// Gets the session. 
     /// </summary> 
     /// <value>The session.</value> 
     private ISession Session 
     { 
      get 
      { 
       return SessionProvider.Session;     
      } 
     } 


     /// <summary> 
     /// Saves the specified contact. 
     /// </summary> 
     /// <param name="contact">The contact.</param> 
     /// <returns></returns> 
     public int? Save(OrderItems contact) 
     { 
      int? retVal = null; 
      ITransaction transaction = null; 

      try 
      { 
       transaction = Session.BeginTransaction(); 
       Session.SaveOrUpdate(contact); 

       if (transaction != null && transaction.IsActive) 
        transaction.Commit(); 
       else 
        Session.Flush(); 

       retVal = contact.Id; 
      } 
      catch (Exception ex) 
      { 
       log.Error(ex); 
       if (transaction != null && transaction.IsActive) 
        transaction.Rollback(); 
       throw; 
      } 

      return retVal; 
     } 
+0

코드가 덜 테스트 가능하도록 만들었 기 때문에 저는이 접근 방법에 대한 큰 팬이 아닙니다. 나는 깨끗한 방법을 전파하려고합니다. 리파지토리에 적절한 세션 객체 .. –