2009-06-16 3 views
2

나는 N + 1이 Hibernate/NHibernate에서 문제를 선택하는 것을 피하는 기본적인 방법을 알고 있지만, 좋은 해결책을 찾을 수없는 문제의 변형을 실행했다. .NHibernate에서 비즈니스 규칙을 사용하여 N + 1을 선택 함.

다음 세 엔티티가 매핑되었습니다. 항목, 범주 및 고객. 아이템은 카테고리에 many-to-many와 연관되어 있고 카테고리는 고객에게 many-to-one으로 매핑됩니다. 지금까지 아무것도 특별하지 않았습니다.

내 응용 프로그램의 표준 쿼리는 주어진 고객에 대한 모든 항목을 가져 오는 것입니다. 내가 카테고리 속성 '항목을 검사 할 때 N + 1 선택을 방지하기 위해, 열심히 카테고리'이 항목을 가져 오기 위해 노력하고, 다음과 같은 기준을 사용하여 수행

ICriteria criteria = mySession.CreateCriteria(typeof(Item)); 
    .CreateCriteria("Categories", NHibernate.SqlCommand.JoinType.InnerJoin) 
     .Add(Expression.Eq("Customer", c)); 
criteria.SetFetchMode("Categories", FetchMode.Eager); 

return criteria.List(); 

그러나,이 작동하지 않습니다, NHibernate에 여전히 페치 나중에 항목 당 하나의 선택 항목이있는 카테고리.

내가 믿는 것은 NHibernate가 첫 번째 쿼리의 결과가 필터링되어 (고객), 쿼리에 의해 반환 된 범주가 완전하지 않을 수 있으므로 나중에 별도의 쿼리를 수행해야한다는 것을 알고있다. 카테고리를 얻으려면. (이 가정은 맞습니까? NHibernate는 올바른 결과를 보장하기 위해이 방법으로 작동해야합니다.)

그러나 비즈니스 규칙에 따라 (또는 호출 할 항목에 따라) 항목을 속일 수 없습니다 둘 이상의 고객이 제공하는 카테고리로 분류되므로 실제로는 첫 번째 쿼리의 결과가 실제로 완료되었음을 알 수 있습니다.

내 질문은 : 어떤 방식 으로든이 비즈니스 규칙에 대해 NHibernate에 알릴 수 있습니까? 이런 상황에서 N + 1을 선택하는 것을 피할 수있는 또 다른 방법이 있습니까 (꽤 일반적으로 보입니다)?

답변

2

지금까지 답변이 없으므로 내 자신의 질문에 답하려고합니다. 첫 번째 질문에 고객에 속하는 항목의 ID를 얻을 :

내 솔루션은 두 개의 쿼리에 문제를 분할하는 것입니다

IQuery query = mySession.CreateQuery("select item.Id from Item as item " 
    + "join item.Categories as category " 
    + "join category.Customer customer " 
    + "where customer.id=:id") 
    .SetInt32("id", c.Id); 
IList itemIds = query.List(); 

그때 고객에 어떤 제한을 포함하지 않고 실제 아이템을 취득 해, ID 만 사용하면됩니다. 이 방법은 NHibernate에 그것은 질문에서 언급 한 N + 1 개 선택 방지, 가입 한 모든 범주를 얻을 수 있습니다 알고 : 나는 작업이 감소 어떤 솔루션을 가지고 올 수없는

ICriteria criteria = mySession.CreateCriteria(typeof(MapItem)) 
    .SetFetchMode("Categories", FetchMode.Eager) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .Add(Expression.In("Id", itemIds)); 
IList items = criteria.List(); 

를 단일 쿼리 . 또한,이 접근법은 프로그래머가 NHibernate의 내부 동작에 대해 너무 많이 알도록 강제하며, 새로운 쿼리 나 조건을 작성할 때 그리워하기 쉽다. 보다 일반적인 해결책이 바람직합니다.

관련 문제