2012-08-31 94 views
1

我有項目。每個項目都屬於一個組。並且每個項目都擁有一個(可能爲空)的標籤列表(字符串),用於增強文本搜索。搜索應找到與其描述相匹配的項目,他們所屬組的描述或一個或多個標籤(全部在或條件下)。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(); 

Item類如下映射。不會拋出異常中的最後一個條件。

我沒有擺脫這種不使用魔術字符串。

+0

。新增(Restrictions.On(()=>標記).IsInsensitiveLike(searchKey,MatchMode.Start))這條線上的標籤應該是tag.Tag,因爲您已將標記表的別名定義爲標記,但在搜索中未提及字段 – Deepesh

+0

標記是純String對象。它沒有Tag屬性。 – 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

謝謝。我不知道爲什麼,但只要我在分解中添加一個標準,查詢就根本不會執行,沒有例外。即使SqlCriterium定義如下(沒有意義,但它應該可以工作),會發生這種情況:新的SQLCriterion(新的SqlString(「{別名} .Id =?」),new [] {searchKey +「%」},new [ ] {NHibernateUtil.String}); – Marcello

+0

@Marcello而不是新的SqlString嘗試SqlString.Parse。 – xanatos

+0

@Marcello「新的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屬性。 – Marcello

+0

你已經提到標籤作爲標籤,你應該使用Tags.Tag屬性來搜索它。你有沒有嘗試過的代碼? – VIRA

+0

我試過你的代碼。它不會編譯。標記只是一個普通的String對象。我試着用「()=> i.Tags」替換我的「()=>標籤」。在最後一種情況下,針對數據庫的查詢不會被觸發,並且空的結果集也不例外地返回。對不起,如果我不明白你的建議。嘗試更精確。 – Marcello