2012-03-15 39 views
10

我有这个简单的LINQ查询NHibernate的3.2和SQLite提供商:NHibernate的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个实体如我意。

+0

听起来像NHibernate的正在生成加入一个内连接时,它应当产生左。我会再看看属性作者的映射。 – 2012-03-15 22:53:18

+0

我想这不是问题,因为每本书至少有一位作者。当在每本书的foreach循环中提取作者时,我会得到正确的结果。 – zszep 2012-03-15 22:57:23

+0

有趣的是,我得到15行返回,但只有11个实体。两本书有两位作者,一本书有三位作者。我纠正跳过和采取应限制返回的实体数量,而不是行? – zszep 2012-03-15 23:17:15

回答

12

跳过,并采取被转换成SQL中的等价物限制对行,因为你急于获取连接有没有什么可以做的。

到预先抓取第15本书,你需要:

var all = Session.Query<Book>() 
    .Skip(15) 
    .Take(15)     
    .ToList(); 

var ids = all.Select(b => b.Id).ToList(); 

// fetch all Authors of the books, now the books in all have initialized Authors 
Session.Query<Book>() 
    .Where(b => ids.Contains(b.Id)) 
    .FetchMany(books => books.Authors) 
    .List(); 

这有2个往返,虽然

更新:一个往返与QueryOver,也许你可以翻译成Linq的

var subquery = QueryOver.Of<Book>() 
    .Skip(15) 
    .Take(15) 
    .Select(b => b.Id); 

var all = Session.QueryOver<Book>() 
    .WithSubquery.WhereProperty(b => b.Id).In(subquery) 
    .Fetch(books => books.Authors).Eager 
    .ToList(); 
+0

在思考了这个问题后,我得出了同样的结论,尽管这很可惜。在指定take(15)并将Query设置为通用类型Book时,人们希望得到15本书。我试图构建一个sql语句,这将做到这一点,但不能想到一个解决方案。那么这将是两个查询。 – zszep 2012-03-16 14:43:19

0
var data = session.QueryOver<EmployeeDetails>() 
            .Where(x => x.Salary > 2000) 
            //.Take(2) 
            .Skip(2) 
            .Take(2) 
            .List(); 
       //if take is before skip then it will skip the last (mentioned digits) rows 
       //if take is after skip then it will skip the first (mentioned digits) rows