2013-01-03 19 views
8

Mam dwa podobne zapytania powracających teoretycznie takie same wyniki:Nieoczekiwany LINQ Zachowanie - ToList()

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

To żądanie zwraca 0 pozycji, mimo że ma powrócić jeden. Poniżej znajduje się przeróbka tego ostatniego, ale z wywołaniem metody ToList(). To żądanie działa i zwraca element oczekiwany w pierwszym zapytaniu!

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

Uwaga: SessionManagement.Db.Linq<Item>(false) to ogólna metoda LINQ do NHibernate z atrybut Boolean określające, czy wniosek musi być wykonywane w pamięci podręcznej (prawda) lub bazy danych (fałsz). Podobno w tej metodzie nie ma nic złego, ponieważ działa on normalnie w wielu innych częściach rozwiązania. Mapowanie elementu nie jest niczym wyjątkowym: brak torebek i następujących parametrów: lazy="false" schema="dbo" mutable="false" polymorphism="explicit"

Dlaczego tak się dzieje?

Edit:

Wygenerowany zapytanie SQL requestNoWorking kończy:

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

Wygenerowany zapytanie SQL requestWorking jest grubsza select * from dbo.Items

+1

Jeśli używasz serwera Sql, czy próbowałeś uruchomić program SQL Profiler podczas uruchamiania obu tych zapytań? – nerdybeardo

+0

i.Group różni się między tymi dwoma. Identycznie nazwane, ale różne w ogóle w przypadku różnych typów kolekcji. –

+1

Proszę napisać wygenerowany SQL. Istnieje różnica semantyczna między tym, co robi SQL, a tym, co dyktuje semantyka C#. LINQ nie obiecywa identycznej semantyki. – usr

Odpowiedz

1

Byłem bardzo zainteresowany twoją teorią na temat c.Group.Id != null, którą uznałem za logiczną, mimo że zaprzeczała innym fragmentom kodu w moim rozwiązaniu. Jednak usunięcie go nie zmieniło niczego. Odkryłem, że usunięcie właściwości mutable="false" rozwiązało problem. Wydaje się nieco magiczne, ale zadziałało.

Wnioski, które wysłałem, faktycznie miały miejsce w metodach sprawdzających możliwość aktualizacji/usunięcia. Moją konkluzją jest to, że w jakiś sposób sprawienie, że przedmiot niezmiennie wpływa na wyniki. Ale nie rozumiem, dlaczego requestWorking działał!

0

Wszystko, co mogę zobaczyć, że w drugiej wersji Twój Where jest wykonywany przez LINQ do obiektów, a nie LINQ do NHibernate. Tak więc pierwsza wersja musi zrobić coś, co LINQ do NHibernate nie trawi zbyt dobrze.

jestem myślenia Jest to i.Group != null że LINQ do NHibernate ma problem z widząc, że stosowanie null CLR jest specyficzny. Być może trzeba będzie użyć innej konstrukcji w LINQ do NHibernate, aby przetestować puste wartości pól.

4

Zakładam, że sesja nhibernate, o której tu mowa, zwraca zapytanie. jeśli tak, ocena pierwszego zapytania jest opóźniona do wywołania .ToList(), a całe zapytanie jest uruchamiane na serwerze. Sugerowałbym, aby w miarę możliwości uruchomić śledzenie na serwerze sql lub pobrać NHProf, aby zobaczyć, jakie jest rzeczywiste wykonywane zapytanie.

Druga kwerenda jest oceniana, gdy tylko trafisz na pierwszą .ToList(), więc wyciągasz całą tabelę z powrotem z bazy danych, a następnie filtrowanie za pomocą .net. Szczerze mówiąc nie mogę powiedzieć, dlaczego mieliby oni oceniać inaczej, ale zakładam, że jest coś z mapowaniem/konfiguracją, która powoduje, że zapytanie db jest napisane nieco błędnie.

+3

Moje przypuszczenie byłoby czymś w porównaniu z zerowym porównaniem, SQL NULL porównania są zawsze PITA. – anydot

Powiązane problemy