NHibernate-检索仅应用于子项的父项/子项

NHibernate-检索仅应用于子项的父项/子项,nhibernate,join,filter,Nhibernate,Join,Filter,我有一个带有子实体列表的父实体。当使用NHibernate从SQL检索具有子级的给定父级时,如果没有子级,或者如果有日期与where条件匹配的子级,则可以正常工作 如果存在与where子句不匹配的子级,则父级为null。我想用一个空的子项列表初始化父项 关于如何修改下面的代码以实现这一点,有什么想法吗 实体: public class Parent { public int ParentId; public IList<Child> Children { get; s

我有一个带有子实体列表的父实体。当使用NHibernate从SQL检索具有子级的给定父级时,如果没有子级,或者如果有日期与where条件匹配的子级,则可以正常工作

如果存在与where子句不匹配的子级,则父级为null。我想用一个空的子项列表初始化父项

关于如何修改下面的代码以实现这一点,有什么想法吗

实体:

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>;
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>;
公共类父类
{
公共int-ParentId;
公共IList子项{get;set;}
公共家长()
{
Children=新列表();
}
}
公营儿童
{
公共智力儿童;
公共日期时间ChildDate;
公共父级{get;set;}
}
存储库:

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>;
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>;
IList foundParents=new List();
var criteria1=DetachedCriteria.For()
.Add(Restrictions.Eq(“ParentId”,ParentId))
.CreateCriteria(“子项”,JoinType.LeftOuterJoin)
.添加(限制)或(
Restrictions.IsNull(“ChildDate”),//完全没有子项
限制。及(
限制。Ge(“儿童日期”,起始日期),
限制。Le(“儿童日期”,结束日期)
)
));
foundParents=会话
.CreateMultiCriteria()
.Add(标准1)
.SetResultTransformer(新DistincTrotentyResultTransformer())
.List()[0]作为列表;

如果我为此编写SQL,我会将日期比较放在左连接中,而不是放在where子句中。我不知道如何使用NHibernate来实现这一点。

这需要大量的研究——找到答案的关键是术语过滤器。我是在ANSIJoinFragment.cs中从AddJoin开始的NHibernate源代码中找到这个术语的——该代码支持连接上的附加条件,因此我认为这是可能的

无论如何,下面是使用过滤器的修订代码(实体类保持不变)

存储库:

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>;
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>;
IList foundParents=new List();
var criteria1=DetachedCriteria.For()
.Add(Restrictions.Eq(“ParentId”,ParentId))
.CreateCriteria(“子项”,JoinType.LeftOuterJoin);
会话.启用筛选器(“日期筛选器”)
.SetParameter(“开始日期”,开始日期)
.SetParameter(“endDate”,endDate);
foundParents=会话
.CreateMultiCriteria()
.Add(标准1)
.SetResultTransformer(新DistincTrotentyResultTransformer())
.List()[0]作为列表;
我还必须通过添加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加载整个表