2012-09-05 13 views
5

Questo non mi ha causato problemi di oggi. Ho questa semplice queryEntity Framework: impossibile creare un valore costante di tipo '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))) 
); 

L'ultima riga di questa query mi sta causando problemi

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

L'errore che dà è

Impossibile creare un valore costante di tipo ' System.Collections.Generic.IList`1' . Solo i tipi primitivi ('come Int32, String e Guid') sono supportati in questo contesto.

Non sto nemmeno cercando di creare un elenco. Tutto quello che sto cercando di fare qui è riportare le strutture ricettive associate a un luogo (dove il nome del luogo nella tabella dei luoghi che è collegato alla tabella degli alloggi tramite la tabella AccommodationPlaceJoin) è uguale a uno qualsiasi dei nomi dei luoghi nei criteri .Locations (che è di tipo IList).

Ho provato a modificare questa linea, ma non ha funzionato.

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

risposta

29

Il valore EF costante non può creare è null per il confronto criteria.Locations == null. È necessario dividere la query in due casi e fare il controllo per la lista vuota di fuori della query, ad esempio in questo modo:

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

Modifica

BTW: Comporre l'intera query renderebbe meglio leggibile secondo me e semplificherà l'SQL che deve essere inviato al database:

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, che bella risposta. Grazie mille. Sono andato così tante righe sbagliate di inchiesta. Grazie +1 e risposta accettata e domanda preferita. Non c'è da stupirsi che tu abbia quasi 29K punti. Perché succede comunque? –

+0

Sono un refactoring in linea con il tuo suggerimento di leggibilità. Grazie. –

+1

@SachinKainth: l'eccezione si verifica perché in LINQ alle entità ogni espressione e frammento di espressione in una query deve essere traducibile in SQL. Il confronto 'criteria.Locations == null' non viene eseguito sul lato client (= .NET) ma EF vuole tradurlo in SQL e quindi il database dovrebbe eseguire il confronto. Ma il database non sa come confrontare i riferimenti a oggetti .NET/CLR, può solo controllare tipi primitivi come string, int, ecc. Per 'NULL'. Nessuna traduzione in SQL possibile o supportata -> Eccezione. – Slauma

Problemi correlati