2010-10-25 13 views
3

我有一個包含子實體列表的父項實體。當使用NHibernate從SQL中檢索給定的父級子項時,如果沒有子項或者子項的日期與where條件匹配,則它工作正常。NHibernate - 使用僅適用於子項的條件檢索父項/子項

如果有子項與where子句不匹配,則父項爲空。我想讓父母用空的兒童列表進行初始化。

有關如何修改下面的代碼以實現此目的的任何想法?

實體:

public class Parent 
{ 
    public int ParentId; 
    public IList<Child> Children { get; set; } 

    public Parent() 
    { 
     Children = new List<Child>(); 
    } 
} 

public class Child 
{ 
    public int ChildId; 
    public DateTime ChildDate; 
    public Parent Parent { get; set; } 
} 

庫:

IList<Parent> foundParents = new List<Parent>(); 

var criteria1 = DetachedCriteria.For<Parent>() 
    .Add(Restrictions.Eq("ParentId", parentId)) 
    .CreateCriteria("Children", JoinType.LeftOuterJoin) 
     .Add(Restrictions.Or(
      Restrictions.IsNull("ChildDate"), // no children at all 
      Restrictions.And(
       Restrictions.Ge("ChildDate", startDate), 
       Restrictions.Le("ChildDate", endDate) 
      ) 
     )); 

foundParents = Session 
    .CreateMultiCriteria() 
    .Add<Parent>(criteria1) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List()[0] as List<Parent>; 

如果我這個寫SQL,我會把在左邊的日期比較加入,而不是在哪裏條款。我無法弄清楚如何用NHibernate做到這一點。

回答

3

這花了很多研究 - 尋找答案的關鍵是術語過濾器。我通過從ANSIJoinFragment.cs中的AddJoin開始挖掘NHibernate源代碼來找到術語 - 代碼支持連接上的附加條件,所以我認爲這是可能的。

無論如何,這裏是使用過濾器的修改代碼(實體類保持不變)。

庫:

IList<Parent> foundParents = new List<Parent>(); 

var criteria1 = DetachedCriteria.For<Parent>() 
    .Add(Restrictions.Eq("ParentId", parentId)) 
    .CreateCriteria("Children", JoinType.LeftOuterJoin); 

Session.EnableFilter("dateFilter") 
    .SetParameter("startDate", startDate) 
    .SetParameter("endDate", endDate); 

foundParents = Session 
    .CreateMultiCriteria() 
    .Add<Parent>(criteria1) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List()[0] as List<Parent>; 

我也不得不加入過濾器和過濾器的高清內容修改我的父映射。

<class name="Parent" table="Parents"> 

    ... 
    <bag name="Children" table="Children"> 
    ... 
    <filter name="dateFilter" 
     condition="ChildDate BETWEEN :startDate and :endDate" /> 
    </bag> 
</class> 

<filter-def name="dateFilter"> 
    <filter-param name="startDate" type="System.DateTime" /> 
    <filter-param name="endDate" type="System.DateTime" /> 
</filter-def> 

而且,對於任何一個字的警告,運行到這個問題,並且不使用過濾器。如果您決定在使用where子句的原始查詢不產生任何記錄時返回沒有填充子項的Parent實體,則任何碰到子組的子代碼都會導致NHibernate加載整個表。

相關問題