【发布时间】:2012-03-15 22:40:55
【问题描述】:
我在 NHibernate 3.2 和 SQLite 提供程序中有这个简单的 linq 查询:
var all = (from book in Session.Query<Book>() select book)
.Skip(15)
.Take(15)
.ToList();
此查询正确返回 15 个实体,但是当我尝试像这样使用 FetchMany 急切加载依赖集合时:
var all = (from book in Session.Query<Book>() select book)
.FetchMany(books => books.Authors)
.Skip(15)
.Take(15)
.ToList();
我只返回了 11 个实体。这是一个错误还是我遗漏了什么?
这是生成的 SQL 查询
select
book0_.Id as Id2_0_,
author2_.Id as Id0_1_,
book0_.Title as Title2_0_,
book0_.Sort as Sort2_0_,
book0_.TimeStamp as TimeStamp2_0_,
book0_.PubDate as PubDate2_0_,
book0_.Series_Index as Series6_2_0_,
book0_.Author_Sort as Author7_2_0_,
book0_.Isbn as Isbn2_0_,
book0_.Lccn as Lccn2_0_,
book0_.Path as Path2_0_,
book0_.Flags as Flags2_0_,
book0_.Uuid as Uuid2_0_,
book0_.Has_Cover as Has13_2_0_,
book0_.Last_Modified as Last14_2_0_,
author2_.Name as Name0_1_,
author2_.Sort as Sort0_1_,
author2_.Link as Link0_1_,
authors1_.book as book0__,
authors1_.author as author0__
from
books book0_
left outer join
books_authors_link authors1_ on book0_.Id=authors1_.book left outer join authors author2_
on authors1_.author=author2_.Id
order by book0_.Id asc
limit 15 /* @p0 */ offset 0 /* @p1 */
这有效地将结果集限制为 15 行,而不是我想要的 15 个实体。
【问题讨论】:
-
听起来像 NHibernate 正在生成内连接,而它应该生成左连接。我会多看一下属性 Authors 的映射。
-
我想,这不是问题,因为我每本书至少有一个作者。在每本书的 foreach 循环中获取作者时,我得到了正确的结果。
-
有趣的是,我确实返回了 15 行,但只有 11 个实体。两本书有两位作者,一本书有三位作者。我是否更正了 skip 和 take 应该限制返回实体的数量而不是行数?
-
这种行为确实看起来有点奇怪。人们会从 Linq 查询中假设该限制应该适用于书籍,但该查询限制了组合的数量,从而导致书籍数量减少。我能看到的唯一解决方法是将 AsEnumerable() 放在 FetchMany() 之后和 Skip() 之前,但很难估计这会对性能产生什么影响。
-
谢谢约阿希姆。这确实有效,但它会加载所有书籍并将结果过滤到内存中。这是我打算通过首先引入分页来防止的。我不知道这种奇怪的行为是否是由于 nHibernate Sqlite 驱动程序或其他问题引起的。我会尝试另一个数据库并发布结果。
标签: linq nhibernate