2012-03-15 9 views
10

Ho questa semplice query LINQ in NHibernate 3.2 e fornitore SQLite:fornitore di NHibernate Linq e prendere() salta() con il caricamento diretto

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

questa query restituisce correttamente 15 entità, ma quando provo a carico desiderosi una collezione dipendente con fetchmany come questo:

var all = (from book in Session.Query<Book>() select book) 
    .FetchMany(books => books.Authors) 
    .Skip(15) 
    .Take(15)     
    .ToList(); 

ottengo solo 11 soggetti restituiti. È un bug o qualcosa che mi manca?

Ecco query SQL risultante

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 */ 

Questo limita efficacemente il set di risultati di 15 righe e non 15 come entità ho inteso.

+0

Sembra che NHibernate stia generando un join interno quando dovrebbe generare un join sinistro. Darei un'occhiata in più ai mapping per la proprietà Autori. –

+0

Immagino, questo non è un problema perché ho almeno un autore per ogni libro. E quando raccolgo gli autori in un ciclo foreach per ogni libro, ottengo risultati corretti. – zszep

+0

La cosa interessante è che ottengo 15 righe restituite, ma solo 11 entità. Due libri hanno due autori e un libro ha tre autori. Sono corretto che saltare e prendere dovrebbe limitare il numero di entità restituite e non di righe? – zszep

risposta

12

skip e take sono convertiti agli equivalenti in sql che limitano le righe e dal momento che si sta cercando con entusiasmo i join non c'è molto che si possa fare al riguardo.

ai desiderosi recuperare i primi 15 libri è necessario:

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(); 

questo ha 2 di andata e ritorno se

Update: un'andata e ritorno con QueryOver, forse si può tradurre in 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

Dopo aver riflettuto sul problema, sono giunto alla stessa conclusione, anche se è un peccato. Ci si aspetterebbe di ottenere 15 libri quando si specifica take (15) e si imposta che la Query sia di tipo generico Book. Ho provato a costruire una dichiarazione SQL che farebbe questo, ma non potrei pensare a una soluzione. Quindi saranno due domande, quindi. – zszep

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