2013-01-13 1 views
6

질의 캐싱으로 NHibernate (NHibernate.LinqFluent NHibernate)를 설정했다. session.Save(new Widget()) (예 : INSERT)을 수행 할 때까지 모든 것이 올바르게 작동합니다. 이 시점 이후에 해당 유형의 모든 쿼리 Widget은 쿼리 캐시를 잃어 버립니다. 다른 엔티티 유형에 대한 쿼리는 잘 캐시됩니다. 나는 새로운 Transaction를 시작하면NHibernate - 질의는 새로운 엔티티를 저장 한 후에 질의 캐시를 잃어 버린다.

using (ISession session = MySessionFactory.OpenSession()) 
{ 
    using (var transaction = session.BeginTransaction()) 
    { 
     // this INSERT screws things up 
     var widget = new Widget {Name = "Foo"}; 
     session.Save(widget); 

     var query = (from w in session.Query<Widget>().Cacheable() 
        where w.Name == "Bar" 
        select w); 

     var fetched1 = query.FirstOrDefault(); 
     var fetched2 = query.FirstOrDefault(); // miss?! 

     transaction.Commit(); 
    } 
} 

문제가 지속됩니다. 새로운 Session을 시작하면 문제가 해결됩니다. 내 이해가 SessionFactory (Session 아님) 당 재설정 된 두 번째 레벨 캐시 였기 때문에 이상하게 보입니다.

저는이 문제가 중요하다고 생각하지 않지만, 지금은 테스트 중이기 때문에 HashtableCacheProvider을 사용하고 있습니다.

+0

어떤 오류가 발생 했습니까? – spajce

+0

예외가 발생했다는 의미에서 오류가 아닙니다. 오히려, 두 번째 쿼리 ('var fetched2 = query.FirstOrDefault();')는 쿼리 캐시를 건너 뛰고 예상되는 동작이 아닌 데이터베이스를 직접 방문합니다. –

+0

쿼리 캐시를 활성화 했습니까? 엔티티 캐시와 별도로 처리해야한다고 생각합니다. –

답변

6

설명한 동작은 올바른 (more here)입니다.

트랜잭션을 커밋 할 때까지 업데이트 타임 스탬프 캐시가 업데이트되지 않습니다! 이는 캐시에서 "커밋되지 않은 값"을 읽지 않도록하기위한 것입니다. 우리가 캐시에 야해 type에 변화가있을 때마다

- 전체 트랜잭션이 커밋 될 때까지 캐시 된 데이터는 ... 부실 있습니다.

는이 필터의 결과를 캐시 한 것을 상상해

var query = (from w in session.Query<Widget>().Cacheable() 
    where w.Name == "B*" // all names starting with B 
    select w); 

그리고 나중에 새로운 위젯을 추가 할 것입니다 : 쿼리가 여전히 캐시 될 경우

var widget = new Widget {Name = "Brigitte"}; 
session.Save(widget); 
// explicit Flush is not needed, 
// but then, until Commit(), query will never return Brigitte 
session.Flush(); // to immediately execute INSERT 

는 브리짓이 표시되지 않습니다 ..

트랜잭션에서 FirstOrDefault()가 포함 된 쿼리가 즉시 실행됩니다. 쓰기 작업은 커밋 할 때까지 대기 할 수 있습니다.

트랜잭션 때문에 모든 포함 된 작업 (insert, udpate, select)은 일괄 처리로만 트랜잭션이 적합하기 때문에 캐싱으로 인해 이익을 얻을 수 없습니다. 그래서 commit이 호출 될 때까지, 어떤 캐시도 사용될 수 없다.

많은 상세하고 매우 유용한 정보는 여기에서 볼 수 있습니다 : First and Second Level caching in NHibernate

타임 스탬프 캐시가 테이블에 기록 될 때마다 업데이트하지만, 방법의 까다로운 일종의되어

  • 우리를 실제 쓰기를 수행 할 때, 우리는 미래의 어딘가에있는 값을 캐시에 씁니다. 따라서 캐시가 캐시에 도달하면 쿼리를 찾지 못하고 DB를 방문하여 새 데이터를 가져옵니다. 거래가 진행되는 중이므로 거래가 완료 될 때까지 기다릴 것입니다. 낮은 격리 수준을 사용하고 있고 다른 스레드/시스템이 캐시에 이전 결과를 되돌리려 고 시도하면 업데이트 타임 스탬프가 이후이므로 캐시가 유지되지 않습니다.
  • 트랜잭션에서 커밋을 수행 할 때 타임 스탬프 캐시를 현재 값으로 업데이트합니다.
관련 문제