Dans ce cas, il est important de faire la distinction entre IQueryable<T>
et IEnumerable<T>
. En bref, il IQueryable<T>
est traité par un fournisseur LINQ pour fournir une requête optimisée. Lors de cette transformation, toutes les instructions C # ne sont pas prises en charge, car il n'est pas possible de les traduire en une requête spécifique au back-end (par exemple SQL) ou parce que l'implémenteur n'a pas prévu la nécessité de l'instruction.
En revanche IEnumerable<T>
est exécuté contre les objets concrets et, par conséquent, ne sera pas transformé. Ainsi, il est assez courant que les constructions, qui sont utilisables avec IEnumerable<T>
, ne puissent pas être utilisées avec IQueryable<T>
et que celles IQueryables<T>
soutenues par différents fournisseurs LINQ ne prennent pas en charge le même ensemble de fonctions.
Cependant, il existe quelques solutions de contournement (comme la réponse de Phil ), qui modifient la requête. De plus, comme approche plus générale, il est possible de revenir à un IEnumerable<T>
avant de continuer avec la spécification de la requête. Ceci, cependant, peut avoir un impact sur les performances - en particulier lors de son utilisation sur des restrictions (par exemple, clauses where). En revanche, lorsqu'il s'agit de transformations, l'impact sur les performances est beaucoup plus faible, parfois même inexistant, en fonction de votre requête.
Ainsi, le code ci-dessus pourrait également être réécrit comme ceci:
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
);
REMARQUE: Ce code aura un impact sur les performances supérieur à la réponse de Phil . Cependant, cela montre le principe.
List<string> my = new List<string>(); var i = from m in my where !string.IsNullOrWhiteSpace(m) select m;