2012-08-24 52 views
4

我是新的stackoverflow,我希望這個問題將不勝感激。NHibernate預測(QueryOver.SelectList)限制

簡單地說:我選擇從表x x左外連接表y中的所有東西。表x有太多的列,所以我讓新的對象x。該對象用於投影。我可以投影表格x的每一列我想要的。但是當我嘗試投影/選擇一個集合(表y的集合),然後我得到同樣的錯誤:'索引超出數組的界限'。

我的問題:NHibernate是否支持選擇/項目集合呢?因爲我通過搜索谷歌(和stackoverflow)多次看到這個問題,但沒有任何問題得到解答。

代碼示例:

public class X 
{ 
    public virtual int ID { get; set; } 
    public virtual int IDontNeedMoreInfoAboutClassXItTakesToMuchTimeToRetrieve { get; set; } 
    public virtual IList<Y> YCollection { get; set; } 
} 

public class Y 
{ 
    public virtual int YID { get; set; } 
} 

public class XRepository{ 
    public ISession Session {get; set;} 
    public IList<X> Get() 
    { 

     X xAlias = null; 
     Y yAlias = null; 
     X resultAlias = null; 
     return Session.QueryOver<X>() 
      .JoinAlias(() => xAlias.YCollection,() => yAlias, JoinType.LeftOuterJoin) 
      .SelectList(list => list 
       .SelectGroup(() => xAlias.ID).WithAlias(() => resultAlias.ID) 
       .SelectGroup(() => xAlias.YCollection).WithAlias(() => resultAlias.YCollection)) // Index was outside the bounds of the array 
       .TransformUsing(Transformers.AliasToBean<X>()).List<X>(); 
    } 
} 
+0

那麼'X'是DTO還是映射類? –

+0

好問題:X是一個映射類。我知道我也使用一個映射類作爲結果(resultAlias),但是如果我使用dto或映射類作爲返回對象,它並沒有太大區別。它只關於忽略select語句中的某些列。 – PcPulsar

+0

我不認爲你必須自己進行連接。如果'Y'集合被正確映射,那麼你所要做的就是'Session.QueryOver ().Fetch(x => x.YCollection).Eager'。 nHib會爲你生成左外連接。任何你不想要的'X'屬性都可以設置爲'Fetch()。懶惰' –

回答

3

結果返回已與內容進行分組完整的(所以SQL是掉,因爲它只能聚集在分組的項目),但NHibernate的唯一能做到這一點的男,apped實體,因爲它知道要分組的身份。手動操作很簡單

Y yAlias = null; 
var tempResults = Session.QueryOver<X>() 
    .JoinAlias(x => x.YCollection,() => yAlias, JoinType.LeftOuterJoin) 
    .SelectList(list => list 
     .Select(() => xAlias.Id) 
     .Select(() => xAlias.Name) 
     ... 
     .Select(() => yAlias.Id) 
     ... 
    .ToList<object[]>() 

List<X> results = new List<X>(100); // switch to Hashset if too slow and order does not matter 
foreach(var row in tempResults) 
{ 
    Y y = new Y { Id = (long)row[4], ... }; 
    X x = results.FirstOrDefault(x => x.Id == (long)row[0])); 
    if (x != null) 
     x.YCollection.Add(y); 
    else 
     results.Add(new X { Id = (long)row[0], ..., YCollection = { y } }; 
} 

return results; 
+0

如果我理解正確:我必須檢索'tmpResults'中的扁平化結果,然後我必須重新創建正確的對象。我想我明白爲什麼它應該以這種方式實施。 Thx,儘快嘗試這個解決方案! – PcPulsar

+0

Thx爲解決方案。我使用的最大區別是使用臨時(拼合)的dto來存儲數據,而不是object []。現在我可以指出運行時更好的拳擊表現錯誤。 – PcPulsar