2012-03-15 38 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