我尝试检索根元素及其子集合的列表,在子集合中应用子查询过滤器。这个子查询需要带来root子元素的最后一次出现。
预期的结果是一个根元素列表,其中每个元素只有子集合属性的最后一个出现。
这些元素的类表示:
public class Root {
public virtual long id { get; set; }
public virtual ISet<Child> childList { get; set; }
}
public class Child {
public virtual long id { get; set; }
public virtual DateTime occurrence { get; set; }
public virtual Root parent { get; set; }
}
我尝试使用NHibernate的 QueryOver 创建查询,遗憾的是它没有按预期工作。
这是我尝试过的代码:
Root rootAlias = null;
Child childAlias = null;
var query = QueryOver.Of(() => rootAlias)
.Left.JoinAlias(
() => rootAlias.childList,
() => childAlias,
Restrictions.Where<Child>(
cd => cd.occurrence == QueryOver.Of<Child>()
.Where(cx => cx.parent.id == rootAlias.id)
.Select(cx => cx.occurrence)
.OrderBy(cx => cx.occurrence).Desc
.Take(1)
.As<DateTime>()
)
);
如果你们能帮我解决这个问题,或者甚至指出另一种方法来达到上述结果,我会很高兴。
答案 0 :(得分:0)
在搜索并阅读了数百篇类似的帖子后,我找到了解决问题的方法。
正如我在问题中所说:“预期结果是一个根元素列表,其中每个元素只有子集合属性的最后一个出现。”
这是考虑我的类结构的解决方案:
// Aliases
Root rootAlias = null;
Child x_temp = null;
Child childAlias = null;
// Result list.
IList<Root> roots = null;
// Subquery which retrieves a list of child's id by max occurrence and grouping by
// root id.
var subquery = CurrentSession.QueryOver<Child>(() => x_temp)
.SelectList(list => list
.Select(() => x_temp.id)
.SelectMax(() => x_temp.occurrence)
.SelectGroup(() => x_temp.root.id)
)
.List<object[]>()
.Select(p => p[0]).ToArray();
// Query root elements, joining with child collection, applying
// a restriction on child's id attribute through
// JoinAlias' "With clause" parameter.
var query = QueryOver.Of(() => rootAlias).Left.JoinAlias(
() => rootAlias.childList,
() => childAlias,
Restrictions.On(() => childAlias.id).IsIn(subquery)
);
// retrieves the final result list through the query.
roots = query.GetExecutableQueryOver(CurrentSession).List();
就是这样!
我希望它对于有类似问题的其他人有用。