Eu tenho o seguinte código:
return this.ObjectContext.BranchCostDetails.Where(
b => b.TarrifId == tariffId && b.Diameter == diameter
|| (b.TarrifId==tariffId && !string.IsNullOrWhiteSpace(b.Diameter))
|| (!b.TarrifId.HasValue) && b.Diameter==diameter);
E eu recebo esse erro quando tento executar o código:
O LINQ to Entities não reconhece o método 'Boolean IsNullOrWhiteSpace (System.String)' e esse método não pode ser convertido em uma expressão de armazenamento. "
Como posso resolver esse problema e escrever código melhor que isso?
List<string> my = new List<string>(); var i = from m in my where !string.IsNullOrWhiteSpace(m) select m;
Nesse caso, é importante distinguir entre
IQueryable<T>
eIEnumerable<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áveisIEnumerable<T>
, não possam ser usadasIQueryable<T>
e também queIQueryables<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:
NOTA: Esse código terá um impacto no desempenho superior à resposta de Phil . No entanto, mostra o princípio.
fonte
Use um visitante de expressão para detectar referências a string.IsNullOrWhiteSpace e divida-as em uma expressão mais simples
(x == null || x.Trim() == string.Empty)
.Então, abaixo, há um visitante estendido e um método de extensão para usá-lo. Não requer nenhuma configuração especial para usar, basta chamar WhereEx em vez de Where.
Portanto, se você executá-
myqueryable.WhereEx(c=> !c.Name.IsNullOrWhiteSpace())
lo, ele será convertido em!(c.Name == null || x.Trim() == "")
antes de ser passado para o que for (linq to sql / entity) e convertido em sql.fonte
Você também pode usar isso para verificar se há espaço em branco:
fonte
lançará exceção se
b.Diameter
fornull
.Se você ainda deseja usar sua declaração, use melhor esta verificação
fonte