休眠。 QueryOver Take(n) - 使用 Left.Join

Posted

技术标签:

【中文标题】休眠。 QueryOver Take(n) - 使用 Left.Join【英文标题】:NHibernate. QueryOver Take(n) - with Left.Join 【发布时间】:2015-07-29 00:03:20 【问题描述】:

Take() 与连接一起使用时出现一些奇怪的行为。假设如下示例:

Comment comment = null;
var persons = _repository
        .QueryOver()
        .Left.JoinAlias(x => x.Comments, () => comment)
        .Where(x => x.Age > 20)
        .Take(5)
        .Future()
        .ToList();

我希望5 人出现在数组中,并且每个人都有一个N comments 列表。

但是,结果给出5 人,最多5 cmets。

为什么.Take(5)也限制了cmets的数量?

如何达到预期的效果?

【问题讨论】:

这是一个经典的笛卡尔积问题。 NH 不会分页根,而是分页根 + 子级。就像 Radim 已经通过分页和延迟加载来回答 fetch parents 与批处理孩子一样 【参考方案1】:

这里的重点是我们对分页的需求及其实现的不同。

虽然我们希望返回 5 个 root 元素,但 结果被转换成5行,5行被选中:

在这个问答中可以找到一些线索:NHibernate QueryOver with Fetch resulting multiple sql queries and db hits

如果使用SQL Server 2012 dialect 进行分页,我们会看到如下 SQL:

SELECT ...
FROM root
JOIN collection
WHERE....
OFFSET 0 ROWS -- skip 0 or 10 or 20 rows
FETCH NEXT 5 ROWS ONLY; -- take 5 rows

所以它最终可能只返回一个根实体,如果孩子(cmets)的数量是 5+

解决方案?我建议这样做:

只选择root实体 使用批量提取加载子项

只选择根,也可能意味着选择任何多对一/引用。这将最终形成一个星型模式结构,左连接将再次正确地在根实体上分页。

文档中描述了批量获取:

19.1.5. Using batch fetching

一些类似的问题:

NHibernate: Select one to Many Left Join - Take X latest from Parent How to Eager Load Associations without duplication in NHibernate?

【讨论】:

感谢您的详细解答。感谢您的帮助++ 很高兴看到这一点,先生!享受很棒的 NHibernate ;)

以上是关于休眠。 QueryOver Take(n) - 使用 Left.Join的主要内容,如果未能解决你的问题,请参考以下文章

休眠和窗口函数

信号量不会使进程休眠

LINQ 查询添加 orderby 使 Skip 和 Take 不起作用 Linqpad

在 QueryOver 中

NHibernate 3.0:没有使用QueryOver的FirstOrDefault()?

NHibernate QueryOver 两次加入一个集合