2012-08-31 3 views
1

항목이 있습니다. 각 항목은 그룹에 속합니다. 그리고 각 항목은 텍스트 검색을 높이는 데 유용한 태그 (문자열) 목록을 소유합니다 (비어있을 수도 있음). 검색은 설명과 일치하는 항목, 해당 항목이 속한 그룹의 설명 또는 하나 이상의 태그 (모두 OR 조건)를 찾습니다.문자열 컬렉션에서 QueryOver 필터링 : NullReferenceException

다음 QueryOver를 통해 검색 키를 사용하여 항목을 선택하려고합니다.

<class name="Item" table="Items"> 
<id name="Id"> 
    <generator class="guid.comb" /> 
</id> 

    <natural-id> 
     <property name="Code" not-null="true" /> 
    </natural-id> 
    <property name="Description" not-null="true" /> 
    <many-to-one name="Group" column="ID_Group" not-null="true" fetch="join" /> 
    <property name="ExpiryDate" /> 
    <list name="Tags" table="Items_Tags"> 
     <key column="ID_Item" /> 
     <index column="Idx" /> 
     <element column="Tag" /> 
    </list> 
</class> 

쿼리 실행이 NullReferenceException이 예외 : 다음과 같이

Item i = null; 
ItemGroup g = null; 
String tag = null; 

session 
    .QueryOver<Item>(() => i) 
    .JoinAlias(x => x.Group,() => g, JoinType.InnerJoin) 
    .JoinAlias(x => x.Tags,() => tag, JoinType.LeftOuterJoin) //left outher join because it is possible for an item to have no tags at all. 
    .Where(
     new Disjunction() 
      .Add(Restrictions.On(() => p.Description).IsInsensitiveLike(searchKey, MatchMode.Anywhere)) 
      .Add(Restrictions.On(() => g.Description).IsInsensitiveLike(searchKey, MatchMode.Start)) 
      .Add(Restrictions.On(() => tag).IsInsensitiveLike(searchKey, MatchMode.Start)) //this condition throws an exception 
    ) 
    .Take(maxResults) 
    .Future(); 

항목 클래스는 매핑됩니다. 분리에서 마지막 조건을 제거하면 예외가 발생하지 않습니다.

나는 마법의 문자열을 사용하지 않고 이것을 제거하지 못했습니다.

+0

.Add (Restrictions.On (() => 태그) .IsInsensitiveLike (searchKey, MatchMode.Start))이 줄에 태그 태그로 태그 테이블의 별칭을 정의했기 때문에 태그를 사용해야합니다. 검색에 언급 된 필드가 없습니다. – Deepesh

+0

태그는 일반 String 객체입니다. 태그 속성이 없습니다. – Marcello

답변

1

오해 경우에 저를 해결하지만, 제발 지금까지 내가 NHibernate에 직접 QueryOver 또는 기준 API를 사용하여 값의 컬렉션을 통해 쿼리를 지원하지 않습니다 알고 .

나는 당신의 가장 좋은 해결 방법은 사용하기 SQLCriteria 것을 제안 :

 var tagCriteria = new SQLCriterion(
      new SqlString("{alias}.Id IN (SELECT ID_Item FROM Items_Tags WHERE Tag LIKE ?)"), 
      new[] {searchKey + "%"}, 
      new[] {NHibernateUtil.String} 
      ); 

     session 
      .QueryOver<Item>(() => i) 
      .JoinAlias(x => x.Group,() => g, JoinType.InnerJoin) 
      .Where(
       new Disjunction() 
        .Add(Restrictions.On(() => p.Description).IsInsensitiveLike(searchKey, MatchMode.Anywhere)) 
        .Add(Restrictions.On(() => g.Description).IsInsensitiveLike(searchKey, MatchMode.Start)) 
        .Add(tagCriteria) 
      ) 
      .Take(maxResults) 
      .Future(); 
+0

감사합니다. 나는 이유를 모른다. 그러나 논리적 구분에 criterium을 추가하자마자, 쿼리는 예외없이 전혀 실행되지 않는다. 새 SQLCriterion (새 SqlString ("(별칭) .Id =?"), 새 [] {searchKey + "%"}, 새 [SqlCriterion은 다음과 같이 정의 되더라도 의미가 있지만 작동하지 않아도됩니다. ] {NHibernateUtil.String}); – Marcello

+0

@Marcello 새 SqlString 대신 SqlString.Parse를 사용해보십시오. – xanatos

+0

@Marcello "new SqlString"은 "SqlString.Parse"매개 변수를 검색 할 때 문자열을 구문 분석하지 않습니다. – xanatos

1

사용이, 내가 최근에 확인하지 않은

session 
    .QueryOver<Item>(() => i) 
    .JoinAlias(x => x.Group,() => g, JoinType.InnerJoin) 
    .JoinAlias(x => x.Tags,() => tag, JoinType.LeftOuterJoin) //left outher join because it is possible for an item to have no tags at all. 
    .Where(
     new Disjunction() 
      .Add(Restrictions.On(() => p.Description).IsInsensitiveLike(searchKey, MatchMode.Anywhere)) 
      .Add(Restrictions.On(() => g.Description).IsInsensitiveLike(searchKey, MatchMode.Start)) 
      .Add(Restrictions.On(() => tag.Tag).IsInsensitiveLike(searchKey, MatchMode.Start)) //this condition throws an exception 
    ) 
    .Take(maxResults) 
    .Future(); 
+0

사실, tag는 문자열입니다. Tag 속성이 없습니다. – Marcello

+0

태그를 태그로 참조 했으므로 태그를 검색하려면 태그 속성을 사용해야합니다. 코드를 사용해 보셨습니까? – VIRA

+0

코드를 시도했습니다. 컴파일되지 않습니다. 태그는 단순한 String 객체입니다. 나는 또한 "() => i.Tags"로 "() => 태그"를 대체하려고 시도했다. 이 마지막 경우에는 DB에 대한 쿼리가 전혀 실행되지 않으며 예외없이 빈 결과 집합이 반환됩니다. 내가 너의 제안을 이해하지 못해서 미안해. 더 정확하게하려고하십시오. – Marcello