Nesse caso, é importante distinguir entre IQueryable<T>
e IEnumerable<T>
. Em resumo, IQueryable<T>
é processado por um provedor LINQ para fornecer uma consulta otimizada. Durante essa transformação, nem todas as instruções C # são suportadas, pois não é possível convertê-las em uma consulta específica de back-end (por exemplo, SQL) ou porque o implementador não previu a necessidade da instrução.
Por outro lado, IEnumerable<T>
é executado contra objetos concretos e, portanto, não será transformado. Portanto, é bastante comum que construções, que são utilizáveis IEnumerable<T>
, não possam ser usadas IQueryable<T>
e também que IQueryables<T>
suportadas por diferentes provedores LINQ não suportem o mesmo conjunto de funções.
No entanto, existem algumas soluções alternativas (como a resposta de Phil ), que modificam a consulta. Além disso, como uma abordagem mais geral, é possível retornar a um IEnumerable<T>
antes de continuar com a especificação da consulta. Isso, no entanto, pode ter um impacto no desempenho - especialmente quando usado em restrições (por exemplo, cláusulas where). Por outro lado, ao lidar com transformações, o impacto no desempenho é muito menor, às vezes até inexistente - dependendo da sua consulta.
Portanto, o código acima também pode ser reescrito assim:
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: Esse código terá um impacto no desempenho superior à resposta de Phil . No entanto, mostra o princípio.
List<string> my = new List<string>(); var i = from m in my where !string.IsNullOrWhiteSpace(m) select m;