2012-09-05 23 views
5

To nie sprawiło mi dzisiaj żadnych problemów. Mam to proste zapytanieEntity Framework: Nie można utworzyć stałej wartości typu "System.Collections.Generic.IList`1 '

var result = 
    DataContext.Accommodations.Where(a => 
     (criteria.MinPrice == null || a.AccommodationRates.Any(r => r.From >= criteria.MinPrice)) && 
     (criteria.MaxPrice == null || a.AccommodationRates.Any(r => r.To <= criteria.MaxPrice)) && 
     (criteria.Locations == null || criteria.Locations.Count == 0 || a.AccommodationPlaceJoins.Any(j => criteria.Locations.Contains(j.Place.PlaceName))) 
); 

Ostatni wiersz tego zapytania jest przyczyną mnie problemów

(criteria.Locations == null || 
criteria.Locations.Count == 0 || 
a.AccommodationPlaceJoins.Any(j => criteria.Locations.Contains(j.Place.PlaceName))) 

Błąd daje się

Nie można utworzyć stałą wartość typu ' System.Collections.Generic.IList`1 '. W tym kontekście obsługiwane są tylko typy podstawowe (takie jak Int32, String i Guid).

Nie próbuję nawet tworzyć listy. Wszystko, co próbuję tutaj zrobić, to przynieść z powrotem noclegi, które są powiązane z miejscem (gdzie nazwa miejsca w tabeli miejsca, która jest powiązana z tabelą zakwaterowania za pośrednictwem tabeli AccommodationPlaceJoin) jest równa jednej z nazw miejsc w kryteriach .Locations (który jest typu IList).

Próbowałem zmienić tę linię, ale to nie zadziałało.

(criteria.Locations == null || 
criteria.Locations.Count == 0 || 
a.AccommodationPlaceJoins.Any(j => criteria.Locations.Any(l => l == j.Place.PlaceName))) 

Odpowiedz

29

Stała wartość EF nie można utworzyć jest null do porównywania criteria.Locations == null. Trzeba podzielić zapytanie na dwie sprawy i zrobić czek na pustej liście poza zapytania, na przykład tak:

var result = DataContext.Accommodations.Where(a => 
    (criteria.MinPrice == null || 
     a.AccommodationRates.Any(r => r.From >= criteria.MinPrice)) && 
    (criteria.MaxPrice == null || 
     a.AccommodationRates.Any(r => r.To <= criteria.MaxPrice))); 

if (criteria.Locations != null && criteria.Locations.Count > 0) 
{ 
    result = result.Where(a => a.AccommodationPlaceJoins 
     .Any(j => criteria.Locations.Contains(j.Place.PlaceName))); 
} 

Edycja

BTW: Komponowanie cały zapytanie uczyniłoby go lepiej czytelne moim zdaniem i uprości SQL, który ma być wysłany do bazy danych:

IQueryable<Accommodation> result = DataContext.Accommodations; 

if (criteria.MinPrice != null) 
    result = result.Where(a => a.AccommodationRates 
     .Any(r => r.From >= criteria.MinPrice)); 

if (criteria.MaxPrice != null) 
    result = result.Where(a => a.AccommodationRates 
     .Any(r => r.To <= criteria.MaxPrice)); 

if (criteria.Locations != null && criteria.Locations.Count > 0) 
    result = result.Where(a => a.AccommodationPlaceJoins 
     .Any(j => criteria.Locations.Contains(j.Place.PlaceName))); 
+0

Wow, co za wspaniała odpowiedź. Stukrotne dzięki. Złożyłem tak wiele błędnych pytań. Dziękujemy +1 i zaakceptowana odpowiedź i ulubione pytanie. Nic dziwnego, że masz prawie 29 punktów. Dlaczego tak się dzieje? –

+0

Jestem refactoring zgodnie z Twoją sugestią czytelności. Dziękuję Ci. –

+1

@SachinKainth: Wyjątek ma miejsce, ponieważ w LINQ do encji każdy fragment wyrażenia i wyrażenia w zapytaniu musi być przetłumaczony na SQL. Porównanie "criteria.Locations == null" nie jest wykonywane po stronie klienta (= .NET), ale EF chce je przetłumaczyć również na SQL, a następnie baza danych ma przeprowadzić porównanie. Ale baza danych nie wie, jak porównać odwołania do obiektów .NET/CLR, może tylko sprawdzić typy pierwotne, takie jak string, int itp. Dla 'NULL'. Brak tłumaczenia na język SQL możliwe lub obsługiwane -> Wyjątek. – Slauma

Powiązane problemy