May*_*ayo 5 nhibernate join filter
我有一个父实体,其中包含子实体列表.当使用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; }
}
Run Code Online (Sandbox Code Playgroud)
库:
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>;
Run Code Online (Sandbox Code Playgroud)
如果我为此编写SQL,我会将日期比较与左连接而不是在where子句中.我无法弄清楚如何使用NHibernate来做到这一点.
这需要进行大量研究 - 找到答案的关键是术语过滤器。我通过从 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>;
Run Code Online (Sandbox Code Playgroud)
我还必须通过添加 filter 和 filter-def 元素来修改我的 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>
Run Code Online (Sandbox Code Playgroud)
此外,对遇到此问题且不使用过滤器的任何人的警告。如果您决定在带有 where 子句的原始查询没有产生记录时返回没有填充子项的父实体,则任何命中子项集的代码都将导致 NHibernate 加载整个表。