In questo caso è importante distinguere tra IQueryable<T>
e IEnumerable<T>
. In breve, IQueryable<T>
viene elaborato da un provider LINQ per fornire una query ottimizzata. Durante questa trasformazione non sono supportate tutte le istruzioni C #, in quanto non è possibile tradurle in una query specifica back-end (ad esempio SQL) o perché l'implementatore non ha previsto la necessità dell'istruzione.
Al contrario, IEnumerable<T>
viene eseguito contro gli oggetti concreti e, pertanto, non verrà trasformato. Quindi, è abbastanza comune che i costrutti, che sono utilizzabili IEnumerable<T>
, non possano essere utilizzati con IQueryable<T>
e anche che IQueryables<T>
supportati da diversi provider LINQ non supportano lo stesso insieme di funzioni.
Tuttavia, esistono alcune soluzioni alternative (come la risposta di Phil ) che modificano la query. Inoltre, come approccio più generale è possibile tornare a un IEnumerable<T>
prima di continuare con la specifica della query. Questo, tuttavia, potrebbe avere un impatto sulle prestazioni, specialmente quando lo si utilizza su restrizioni (ad es. Dove clausole). Al contrario, quando si ha a che fare con le trasformazioni, l'hit di prestazioni è molto più piccolo, a volte anche inesistente, a seconda della query.
Quindi il codice sopra potrebbe anche essere riscritto in questo modo:
return this.ObjectContext.BranchCostDetails
.AsEnumerable()
.Where(
b => b.TarrifId == tariffId && b.Diameter == diameter
|| (b.TarrifId==tariffId && !string.IsNullOrWhiteSpace(b.Diameter))
||(!b.TarrifId.HasValue) && b.Diameter==diameter
);
NOTA: questo codice avrà un impatto sulle prestazioni superiore rispetto alla risposta di Phil . Tuttavia, mostra il principio.
List<string> my = new List<string>(); var i = from m in my where !string.IsNullOrWhiteSpace(m) select m;