2011-03-28 3 views
2

나는 Future<T> 방법을 완전히 잘못 사용하고 있을지 모르지만 나는 그 사용법을 최적화하는 방법에 대해 많은 어려움을 겪고 있습니다. 여기 간단한 예제가 있습니다.nHibernate Future <T>, 로딩 순서에 대한 혼란

세 개체, Member, Player, Character

Member { 
    Player Player { get; set; } 

Player { 
    IList<Character> Characters { get; set; } 
} 

그래서 기본적으로, 한 멤버는 한 선수, 한 선수가 많은 문자가 있습니다. 충분히 간단합니다. (이 추상화의 이유는 Member을 가볍게 유지하여 인증 및 역할에만 사용할 수 있도록하기 위해 더 많은 데이터가 Player 클래스에 첨부되어야 함)

그렇다면 나는 Player에있는 모든 Character을 쿼리하려고합니다. 그래서 나는 다음과 같은 쿼리 여기

 session.QueryOver<Player>() 
      .Fetch(context => context.Characters).Eager 
      .Take(1) 
      .Future<Player>(); 

     session.QueryOver<Character>() 
      .Future<Character>() 
      .Take(10); 

     return session.QueryOver<Member>() 
      .Where(model) 
      .Fetch(context => context.Player).Eager 
      .List() 
      .Take(1) 
      .SingleOrDefault() 
      .Player; 

내 생각은 ... 설정 한, 그 나는 (길 Future<T> 작품에 대해 이해하고 어떤 방법으로 해제 할 수있는 것입니다에서 그것이 것입니다 열망로드 Player (1 : 1)는 동일한 데이터베이스 트립에서 IList<Character>에 대한 쿼리를 수행하며 제한은 10 개이며 제한된 여행 당 1 명의 플레이어와 여행 당 1 명의 회원, 여행 당 최대 10 개의 문자를 사용합니다.

그러나 nhProf은 제한없는 요청을 사용하고 있다고 나에게 말하고 있습니다. 누군가가 여기에서 무슨 일이 일어나는지 설명 할 수 있습니까? 나는 단지 이러한 방법이 어떻게 작동하는지 오해하고 있습니까? 좀 더 실용적인가요? HQL을 이해할 수 없어서 CreateCriteria 메소드를 사용할 수 없습니다. 언제 어디 조건없이,

쿼리 하나가 데이터베이스에서 찾을 수있는 첫 번째 플레이어를 취할 것입니다 : 귀하의 질문에

답변

10

세 쿼리는 다음 할 것입니다.

쿼리 2는 다시 조건을 찾을 필요없이 처음 10자를 가져옵니다.

쿼리 3은 세 가지 쿼리를 실행하고 관련 조건과 일치하는 첫 번째 멤버와 연결된 플레이어를 가져 와서 멤버 플레이어를 반환합니다.

플레이어의 캐릭터를 반복하고 싶다면 NHibernate는 아직 캐릭터가로드되지 않았으므로 DB를 다시 쳤을 것이다.

귀하의 예는 다음과 같이 선물없이 단일 쿼리에서 수행 할 수 있습니다 :

여기
System.Linq.Expressions.Expression<Func<Member, bool>> model = m => m.Id == 1; 
Member mAlias = null; 
Player pAlias = null; 
Character cAlias = null; 

Member member = session.QueryOver<Member>(() => mAlias) 
    .JoinAlias(m => m.Player,() => pAlias) 
    .Left.JoinAlias(() => pAlias.Characters,() => cAlias) 
    .Where(model) 
    .List().FirstOrDefault(); 

더 나은 선물이 무엇을 할 수 있는지 보여줄 수있는 예이다. 쿼리의 목적은 id = 1 인 고객 및 모든 주문과 주문 세부 정보 및 예약을받는 것입니다. 우리가 함께 자신의 세부 사항 및 예약과 주문을로드 할 경우

Class diagram

이제 결과 쿼리가 우리에게 카티 제품을 얻을 것입니다 :

내 모든 매핑 count(Details) * count(Bookings)

int id = 1; 
// define Aliases to use in query and be able to reference joined entities 
Customer cAlias = null; 
Order oAlias = null; 
OrderDetails odAlias = null; 
Booking bAlias = null; 

// get the Customer and his Orders 
var customers = session.QueryOver<Customer>(() => cAlias) 
    .Left.JoinAlias(o => o.Orders,() => oAlias) 
    .Where(c => c.Id == id) 
    .Future<Customer>(); 

// get the Orders and their Details 
var orders = session.QueryOver<Order>(() => oAlias) 
    .JoinAlias(o => o.Customer,() => cAlias) 
    .Left.JoinAlias(() => oAlias.Details,() => odAlias) 
    .Where(() => cAlias.Id == id) 
    .Future<Order>(); 

// get the Orders and their Bookings 
var orders2 = session.QueryOver<Order>(() => oAlias) 
    .JoinAlias(o => o.Customer,() => cAlias) 
    .Left.JoinAlias(() => oAlias.Bookings,() => bAlias) 
    .Where(() => cAlias.Id == id) 
    .Future<Order>(); 

var list = customers.ToList(); 
Customer customer = list.FirstOrDefault(); 

Order o1 = customer.Orders.FirstOrDefault(); 
// iterate through the Details 
// normally this would cause N+1 selects, here it doesn't, because we already loaded 
foreach (OrderDetails od1 in o1.Details) 
{ 
    decimal d = od1.Quantity; 
} 
게으른 로딩 작업을하고 나는 그 쿼리에서 열망하는 로딩을 지정하지 않았다.그래도 코드를 실행하면 데카르트 제품없이 단 한 번의 왕복으로 정확히 3 개의 SQL 쿼리를 얻을 수 있습니다. 그것은 선물의 아름다움입니다.

+1

이것은 정말 유용하고 유용합니다. 나는 선물이 어떻게 작동 하는지를 설명하기가 많이 어려웠다. 내가 찾던 모든 자원은 네가 원래 무엇을 '이해'했다고 가정했다. Ayende의 블로그는 매우 좋은 게시물 이었지만, 많은 HQL을 사용했으며 예제는 내 경험이 부족한 사람이 완전히 끌어 내지 못하도록 장황하지 않았습니다. – Ciel

+0

이 코드를 사용하더라도 "Unbound Result Set"을 사용하고 있다고 계속 말하고 있습니다. 나는 왜 그런지 이해하지 못한다. – Ciel

+0

@Ciel 정확히 어떤 코드입니까? 선물이없는 검색어 또는 세 가지 검색어가있는 예? .SetMaxResults()를 위의 쿼리에 추가 했습니까? 죄송합니다. NHProf를 아직 사용하지 않아서 실험 할 수 없습니다. –