代码之家  ›  专栏  ›  技术社区  ›  Mayo

NHibernate-使用仅应用于子级的条件检索父级/子级

  •  5
  • Mayo  · 技术社区  · 14 年前

    如果有子项与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>;
    

    1 回复  |  直到 14 年前
        1
  •  4
  •   Charles    7 年前

    这需要大量的研究——找到答案的关键是术语筛选。在ANSIJoinFragment.cs中,我通过从AddJoin开始的NHibernate源代码发现了这个术语——代码支持join上的附加条件,所以我认为这是可能的。

    存储库:

    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>;
    

    我还必须通过添加filter和filter def元素来修改父级的映射。

    <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子句的原始查询未生成记录时决定返回父实体而不返回填充的子实体,则任何命中子实体集的代码都将导致NHibernate加载整个表。