我有一个包含子实体列表的父实体。当使用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>;
如果我为此编写SQL,我会将日期比较与左连接而不是在where子句中。我无法弄清楚如何用NHibernate做到这一点。
答案 0 :(得分:4)
这需要大量研究 - 找到答案的关键是术语过滤器。我通过在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>;
我还必须通过添加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>
此外,对于遇到此问题但未使用过滤器的任何人,请提出警告。如果您决定在没有填充子项的情况下返回Parent实体,而带有where子句的原始查询不会生成任何记录,则任何命中子集的代码都将导致NHibernate加载整个表。