2010-04-12 11 views
5

I'am przy użyciu opakowanie, aby uzyskać pewne dane z tabeli użytkownikaLINQ do NHibernate owijarki emisji przy użyciu WHERE

IQueryable<StarGuestWrapper> WhereQuery =  
session.Linq<User>().Where(u => u.HomeClub.Id == clubId && u.IsActive).Select(
        u => 
        new StarGuestWrapper() 
         { 
          FullName = u.Name + " " + u.LastName, 
          LoginTime = u.SomeDateTime, 
          MonthsAsMember = u.SomeIntergerValue, 
          StarRating = u.SomeOtherInteregValue, 
          UserPicture = u.Photo.PhotoData, 
          InstructorFullName = u.SomeInstructorName, 
          TalkInteractionDuringSession = u.SomeBoolValue, 
          GoalInteractionDuringSession = u.SomeOtherBoolValue 
         }); 

Używam tego bez problemu jako IQueryable więc mogę robić pożyteczne rzeczy, zanim faktycznie działa zapytania . Podobnych:

WhereQuery.Skip(startRowIndex).Take(maximumRows).ToList(); 

i tak dalej.

Problem występuje przy użyciu wyrażenia "where" w zapytaniu. Na przykład:

WhereQuery.Where(s => s.StarRating == 1) 

rzuci wyjątek w czasie wykonywania, że ​​„StarRating” nie istnieje w tabeli użytkownika - oczywiście nie jest to nieruchomość owijarki. Będzie działać, jeśli zmaterializować zapytanie przez

WhereQuery.AsEnumerable().Where(s => s.StarRating == 1) 

ale potem traci wszystkie sens korzystania IQueryable i nie chcę tego robić.

Co jest dziwne i interesujące, że nie wszystkie właściwości z powodu błędu rzutowania, wszystkie wartości bool mogą być użyte w instrukcji where. Przykład:

WhereQuery.Where(s => s.TalkInteractionDuringSession) 

Działa w EntityFramework, dlaczego ten błąd w NHibernate i jak się to działa tak, jak chcesz go?

+0

W jaki sposób zamierzasz wysłać zapytanie (które wykorzystuje magazyn danych) do czegoś, czego nie ma w magazynie danych? Jedynym sposobem na znalezienie wszystkich z StarRating = 1 jest wyliczenie wszystkiego. –

+0

@Lasse wydaje się nie rozumieć, jak działa ORM, to zapytanie, a nie kolekcja, nie zawiera danych, które wysyła do bazy danych dla tych danych. Nie przejmuj się wartościami zakodowanymi w tym opakowaniu, to tylko przykład, zamiast tego napisałem u.SomeValue. – Jacob

+0

To * było * zapytaniem przed utworzeniem nowego typu wyniku, w tym miejscu przerwano połączenie z powrotem do magazynu danych, wynik instrukcji select nie jest już kwerendą, do której można nadal dodawać klauzule .Where. Jest to taki sam kod tego typu: SELECT * FROM (kod magic C# tutaj z (SELECT * FROM yourtable)) –

Odpowiedz

2

Należy pamiętać, że starszy dostawca nHibernate Linq jest tylko częściową implementacją i nie jest już aktywnie rozwijany. Nowy i bardziej kompletny dostawca linq jest obecnie rozwijany i będzie częścią NH3.0 (możesz sprawdzić bagażnik i zbudować go, aby sprawdzić, czy rozwiązuje ten problem).

Moja rekomendacja to zmienić kod, aby wywołać ToList() w momencie, kiedy wyraźnie chcesz uderzyć w bazę danych. Przekazujesz przyszłe, cenne zapytanie z repozytorium, w którym to momencie może się zdarzyć, że coś się stanie z zapytaniem. Nawet EF i LINQ2SQL nie mogą przetłumaczyć żadnego możliwego zapytania linq na SQL.

Zdaję sobie sprawę, że nie jest to coś, co chcesz robić, ale myślę, że próbujesz zgiąć ramy, aby zrobić coś w sposób, który nie jest w ogóle naturalny.

+0

Chris, jaka jest wersja ostatniej Linq dll? 2.0? – NetSide

+0

Nie wiedziałbym, prawdopodobnie musiałbyś zapytać na liście NHUsers: –

+0

Powinien prawdopodobnie wspomnieć o NH3.0 po prostu naciśnij alfa i prawdopodobnie jest dość stabilny, jeśli chcesz go wypróbować. –