2013-01-07 3 views
-1

은의이 도메인 객체 예를 들어 보자 :개체 A는 LINQ, 어떻게 A B 적어도 하나 갖는 목록을 검색하는 데 사용 NHibernate에에서 객체 B의 소장품이있다

public class A 
{ 
    public Guid Id { get; set; } 
    public ICollection<B> CollectionOfB { get; set; } 
} 

public class B 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
} 

내가 하나를 검색해야 A 개체는 B이고이 이름은 name1, name2, NHibernate 3.x을 사용합니다.

예를 들어, B 사람이 문자열 배열 string[] names = new string[] { "name1", "name2" }으로 검색하려는 것을 얻는다고 상상해보십시오.

내가 약 .Query<A>().Where(someA => some.CollectionOfB.Any(someB => names.Contains(someB.Name))), 그리고 나는이 NHibernate LINQ 공급자에 의해 SQL 쿼리로 컴파일 될 것이라고 생각. 아마도 이것이 최적이 아닌 SQL 쿼리로 컴파일 될 수 있습니다.

NHibernate 3.x LINQ 공급자을 사용하여 이 쿼리를 작성하는 최적의 방법은 무엇입니까?

+1

왜 * 의심스러운가요? 너 해봤 어? 그것은 작동해야합니다. –

+0

@DanielHilgarth 정말요? 그건 그렇고,이 "CollectionOfB"메모리의 각 "CollectionOfB"로드 할 수 있는지 잘 모르겠습니다, 그 이유는 내가이 질문 : D –

+0

항상 생성 된 SQL 확인할 수 ... 그것은 ' 전체 쿼리가 하나의 SQL 문으로 변환되기 때문에 전체 컬렉션을 쿼리의 메모리에로드하지 마십시오. –

답변

2

당신이 생각 쿼리 :

var someAs = session.Query<A>().Where(someA => some.CollectionOfB.Any(someB => names.Contains(someB.Name))); 

잘 작동을, 나는 그것을 테스트 유사한 구조에. NHibernate는 IN 절을 포함하는 상관 된 부질의를 발행한다.

[편집] 귀하의 의견에 관해서는 쿼리의 의도가 코드에서 명확하다는 의미에서 최적입니다. 성능은 측정되어야하며 데이터베이스 엔진은보기 흉한 찾는 쿼리를 매우 효율적인 쿼리로 변환 할 수있는 쿼리 최적화 프로그램을 사용합니다. 따라서 많은 것들처럼 외관에 대한 쿼리를 판단 할 수 없습니다.

내 샘플 쿼리가 내부 조인을 사용하도록 변경되었으며 더 나은 실행 계획 (정렬 작업이 제거됨)이 있습니다. LINQ 쿼리 구문을 사용하여 쿼리를 다시 작성하면 더 나은 실행 계획을 사용하지만 쿼리에 내부 조인이 포함되지 않습니다. 대신 where 절에서 이전 스타일 조인을 사용합니다.

var someAs = (from someA in session.Query<A>() 
       join someB in session.Query<B>() on someA.Id equals someB.A_Id 
       where names.Contains(someB.Name) 
       select someA).ToArray(); 
+0

니스, 테스트 해줘서 고마워. 때때로 NHibernate는 그런 것들을 번역하기에는 영리하지 못하다. 순수한 .NET 객체에 관해서는 더 많이 이야기한다. 하나의 "하위 쿼리": 이러한 데이터를 쿼리하는 최적의 방법입니까? 수정 된 객체 그래프를 사용해도 동일한 결과를 얻는 다른 방법이 있을까요? 좋은 기본 SQL 쿼리는'SELECT * FROM A INNER JOIN B, A.Id = B.A_Id WHERE B.Name = 'value1'또는 B.Name = 'value2 '' 일 것이기 때문에 그렇게 믿습니다. 분명히 B에 A에 대한 연결을 추가해야합니다. LINQ 공급자를 사용하여이 쿼리를 수행하는 방법을 알고 있습니까? –

+0

니스 (업데이트) –

0

당신은에 대한 참조를 가지고 클래스 B를 확장 할 경우 : 얻기 위해의 쿼리에서()

var aObjectsToRetrieve = Query<B>().Where(x=>x.Name.StartsWith("name1")).Select(x=>x.A.Id); 

을 그리고 적용은 존재 :

public class B 
{ 
    public A A {get;set;} 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
} 

을 그리고 다음과 같이 하위 쿼리를 할 필요한 A 오브젝트. 당신이 이름 배열이있는 경우, 당신이 (당신의 시나리오에 따라 또는 결합) 이런 식으로 뭔가를 시도 할 수 :

var disjunction = new Disjunction(); 
    var names = new[] {"name1", "name2"}; 
    foreach (string name in names) 
      disjunction.Add(Restrictions.InsensitiveLike(PropName<User>(x => x.Name), name)); 
+0

시간을내어 주셔서 감사합니다. Jaime Ide의 대답은 단순히 내 쿼리가 제대로 작동하는지 확인하는 것입니다. 제대로 작동해야합니다. 그건 그렇고, 가능한 경우 LINQ 공급자를 사용하여 쿼리 자체를 향상시켜달라고 요청했습니다. –