2016-09-15 2 views
1

그것은 나의 이해이다. First and Second Level caching in NHibernate 같은 곳에서 - NHibernate의 ISession.get<T>(object id)은 "default"setup - session 등을 사용할 때 동일한 id으로 두 번 호출되면 같은 인스턴스를 반환해야합니다. 그러나 두 개의 인스턴스가 분리되어 있습니다.NHibernate ISession.get을 호출하는 것은 동일한 id를 가진 두번 객체 ID가 두 개의 다른 인스턴스를 반환 함

나는 막연하게 비슷한 질문을 보았지만 thisthis과 같은 검색에서는 유용한 결과를 얻지 못했습니다. 당신이 그것을보고 할 경우에

var repo = (IEntityRepository) new SqliteEntityRepository(); 
var bi1 = repo.GetBillingItemByID(26); 
var bi2 = repo.GetBillingItemByID(26); 
Assert.AreSame(bi1, bi2); // fails 

여기 NHibernateHelper : 여기

BillingItem IEntityRepository.GetBillingItemByID(int id) 
{ 
    var session = Helpers.NHibernateHelper.OpenSession(); 

    using (ITransaction tran = session.BeginTransaction()) 
    { 
     var ret = session.Get<BillingItem>(id); 
     tran.Commit(); 
     return ret; 
    } 
} 

이 실패 내 테스트입니다 :

여기 내 get 방법이다

internal static class NHibernateHelper 
{ 
    private static ISessionFactory _sessionFactory; 

    internal static ISession OpenSession() 
    { 
     return SessionFactory.OpenSession(); 
    } 

    private static ISessionFactory SessionFactory 
    { 
     get 
     { 
      if (_sessionFactory == null) 
      { 
       var configuration = new Configuration(); 
       configuration.Configure(); 
       configuration.AddAssembly(typeof(BillingItem).Assembly); 
       configuration.AddAssembly(typeof(PaymentItem).Assembly); 
       var mapper = new ModelMapper(); 
       mapper.AddMappings(typeof(Mappings.BillingItemMapping).Assembly.GetExportedTypes()); 
       mapper.AddMappings(typeof(Mappings.PaymentItemMapping).Assembly.GetExportedTypes()); 
       var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities(); 
       configuration.AddDeserializedMapping(mapping, null); 
       SchemaMetadataUpdater.QuoteTableAndColumns(configuration); 
       _sessionFactory = configuration.BuildSessionFactory(); 
      } 

      return _sessionFactory; 
     } 
    } 
} 

무엇 내가 여기서 누락 된거야?

+1

어떻게 Assert.AreSame()을 비교합니까? 'Equals()'또는'CompareTo()'를 오버로드 했습니까? –

+0

나는 무엇이든 과대 적재하지 않았다. NUnit입니다. 참조를 비교하는 것입니다. –

답변

1

저장소는 거래 처리에 대한 책임을지지 않습니다. 같은 세션/트랜잭션에서 여러 개의 조회를 실행할 수있는 단일 작업 단위 인스턴스가 있어야합니다.

OpenSession() 메서드는 매번 새로운 세션을 생성합니다. 그것을위한 코드를 게시 할 수 있습니까?

+0

'NHibernateHelper'에 대한 코드를 포함하도록 업데이트했습니다. 제프리 팔레르모 (Jeffrey Palermo)가 [Onion Architecture] (http://jeffreypalermo.com/blog/onion-architecture-part-4-after-four-years/) 샘플 코드에서 사용한 방법을 복사하고있었습니다. –

+0

그래서 세션이 응용 프로그램이 종료되기 직전까지 닫히지 않기 때문에 동일한 세션에서 모든 쿼리를 수행하고 있음을 알 수 있습니다. –

+0

알다시피, 나는이 기사를 잘못 읽은 것을 깨달았다. 나는'ISessionFactory.OpenSession()'이 ISessionFactory의 주어진 인스턴스에 대해 항상 같은 세션을 반환한다고 말한 것으로 해석했다. (당시에는 메소드 대신 속성이어야했기 때문에 이상하게 생각했다. 그건 사실이었습니다). 그러나 그럴 수는 없습니다. –

2

이것은 우리가 ... 거의 안티 패턴 ... 아주 짧은 세션을 사용하는 이상 때문에 코드에서, 참이어야합니다 : 우리가 일반적으로 필요하지 않습니다

using (ISession session = Helpers.NHibernateHelper.OpenSession()) 
{ ... } 

. Unit of Work 세션이 필요합니다. 웹 응용 프로그램에서는 일반적으로 전체 요청을 통해 지속됩니다 ... (바탕 화면 ... 몇 가지 UoW 해결 방법이 있어야합니다).

두 개의 서로 다른 세션이있는 경우 두 인스턴스가 모두 다른 런타임 인스턴스를 생성합니다.

+0

좋은 지적. 방금 코드를 수정하여 (내 업데이트 참조) 'using'문에서 세션을 제거했지만 동일한 결과를 얻습니다. –

+0

음 .. 그게 더 나빠요;) 세션은 ** 처리되지 않았습니다 !! ** (사용하지 않고 있습니다) ...하지만 그 메소드를 호출 할 때마다 ** 아직 새 세션이 만들어집니다 **;) 그래서 .. 그냥 세션을 감싸기 만하면됩니다. 둘 다 호출 - 여기에 대해 읽어보십시오 http://nhibernate.info/doc/nh/en/index.html#architecture-current-session –

+0

하지만 내 세션에서 인스턴스를 쿼리 할 수 ​​있기를 원합니다. 응용 프로그램. 그것은'ISessionFactory.OpenSession()'에서 동일한 세션 인스턴스를 사용하고 있습니다, 맞습니까? 그것은 똑같은 것이어야합니다. 분명히 세션을 닫지는 않습니다. 어플이 종료 될 때 닫을 수도 있지만, 세션이 여전히'Get' 호출을 위해 열려 있기 때문에 요점을 벗어나는 것입니다. 내가 이해하는 것과 일치해야합니다. –