2013-01-03 9 views
8

Ho due query simili teoricamente ritornano gli stessi risultati:imprevisto Linq Behavior - ToList()

var requestNotWorking = SessionManagement.Db.Linq<Item>(false).Where(i => 
         i.Group != null && i.Group.Id == methodParameter) 
         .ToList(); 

Questa richiesta restituisce 0 prodotti, anche se si deve restituire uno. Quanto segue è una riscrittura di quest'ultimo, ma con una chiamata al metodo ToList(). Questa richiesta funziona e restituisce l'oggetto previsto nella prima query!

var requestWorking = SessionManagement.Db.Linq<Item>(false).ToList().Where(i => 
        i.Group != null && i.Group.Id == methodParameter).ToList(); 

Nota: SessionManagement.Db.Linq<Item>(false) è un generico LINQ to NHibernate metodo con l'attributo booleano che determina se la richiesta deve essere eseguito nella cache (true) o il database (false). In questo metodo non c'è nulla di sbagliato in quanto funziona normalmente in molte altre parti della soluzione. La mappatura dell'articolo non è niente di speciale: niente borse e i seguenti parametri: lazy="false" schema="dbo" mutable="false" polymorphism="explicit"

Perché è così?

Edit:

La richiesta SQL generato di requestNoWorking termina con:

(Item.Group_ID is not null) and [email protected]',N'@p0 int',@p0=11768

La richiesta SQL generato di requestWorking è circa un select * from dbo.Items

+1

Se stai utilizzando SQL Server, hai provato a eseguire SQL Profiler mentre esegui entrambe queste query? – nerdybeardo

+0

i.Group differisce tra i due. Identificato con nome, ma completamente diverso quando su diversi tipi di collezioni. –

+1

Si prega di inviare l'SQL generato. C'è una differenza semantica tra ciò che l'SQL fa e ciò che detta la semantica C#. LINQ non promette la semantica identica. – usr

risposta

1

Ero molto interessato alla tua teoria su c.Group.Id != null, che ho trovato logico anche se contraddiceva altri pezzi di codice nella mia soluzione. Tuttavia, rimuoverlo non ha cambiato nulla. Ho scoperto che la rimozione della proprietà mutable="false" ha risolto il problema. Sembra un po 'magico ma ha funzionato.

Le richieste che ho inviato stavano infatti accadendo in metodi che verificano la possibilità di aggiornamento/cancellazione. La mia conclusione è che in qualche modo rendere l'oggetto immutabile ha annullato i risultati. Ma quello che non capisco è il motivo per cui requestWorking ha funzionato allora!

0

Tutto quello che posso vedere è che nella seconda versione, il tuo Where viene eseguito da LINQ su Oggetti anziché da LINQ a NHibernate. Quindi la prima versione deve fare qualcosa che LINQ a NHibernate non digerisca molto bene.

Sono pensando è il i.Group != null che LINQ Per NHibernate ha un problema con, visto che l'uso di null è specifica CLR. Potrebbe essere necessario utilizzare un altro costrutto in LINQ su NHibernate per verificare i valori dei campi vuoti.

4

presumo che la sessione di sessione non interattiva in corso abbia restituito un'interrogazione. in tal caso, la valutazione della prima query viene posticipata fino alla chiamata e l'intera query viene eseguita sul server. Suggerirei di eseguire una traccia sul server sql se possibile, o forse di scaricare NHProf per vedere quale sia la query effettiva che viene eseguita.

la seconda query viene valutata non appena si preme il primo .ToList(), in modo da recuperare l'intera tabella dal db e quindi filtrare utilizzando .net. onestamente non posso dirti perché dovrebbero valutare in modo diverso, ma presumo che ci sia qualcosa con la mappatura/configurazione che sta facendo sì che la query db sia scritta leggermente errata.

+3

La mia ipotesi sarebbe qualcosa intorno al confronto nullo, i confronti NULL SQL sono sempre PITA. – anydot