O LINQ to Entities não reconhece o método 'System.String ToString ()' e esse método não pode ser convertido em uma expressão de armazenamento
Estou migrando algumas coisas de um servidor mysql para um servidor sql, mas não consigo descobrir como fazer esse código funcionar:
Quando entra no segundo foreach (var page in pages), lança uma exceção dizendo:
O LINQ to Entities não reconhece o método 'System.String ToString ()' e esse método não pode ser convertido em uma expressão de armazenamento.
— Erre Efe
Post relacionado - O LINQ to Entities não reconhece o método & Implementação do padrão de especificação de estrutura de entidades
Apenas salve a string em uma variável temporária e use-a na sua expressão:
O problema surge porque, na ToString()verdade, não é executado, ele é transformado em um MethodGroup e, em seguida, analisado e traduzido para SQL. Como não há ToString()equivalente, a expressão falha.
Verifique também a resposta de Alex sobre a SqlFunctionsclasse auxiliar que foi adicionada mais tarde. Em muitos casos, pode eliminar a necessidade da variável temporária.
E se meu ToString () estiver sendo aplicado no lado esquerdo da igualdade? egpSerial.ToString () = item.
— dotNET 26/03
@dotNet Isso ainda falhará porque a coisa toda se transformou em uma Expressão, que o Entity Framework tenta transformar em SQL válido. Existem alguns métodos que ele sabe manipular, mas ToString()não é um deles.
— 27413 Josh
@ Josh: Eu entendo que isso irá falhar. O que eu estava pedindo é uma solução para esse cenário, porque a solução acima obviamente não pode ser aplicada lá.
— dotNET 27/03
@ Josh: Estou lutando com um desses cenários. Diga que minha coluna OrderNumber é int, mas meu usuário deseja filtrar a lista de OrderNumbers enquanto digita. Se ele digitou 143 na caixa de pesquisa, ele quer apenas os registros que possuem um OrderNumber LIKE '% 143%' . Não preciso fazer ToString () na coluna OrderNumber para alcançá-lo?
@dotNET este é um daqueles cenários em que um ORM cai sobre ele. Eu acho que é ok nessas situações a cair para baixo em qualquer SQL reta via ExecuteQueryou usando Entity SQL comObjectQuery<T>
Como outros responderam, isso é interrompido porque .ToString falha ao converter para SQL relevante no caminho para o banco de dados.
No entanto, a Microsoft fornece a classe SqlFunctions que é uma coleção de métodos que podem ser usados ​​em situações como essa.
Para este caso, o que você está procurando aqui é SqlFunctions.StringConvert :
Bom quando a solução com variáveis ​​temporárias não é desejável por qualquer motivo.
Semelhante ao SqlFunctions, você também tem o EntityFunctions (com EF6 obsoleto pelo DbFunctions ) que fornece um conjunto diferente de funções que também são independentes de fonte de dados (não limitadas a, por exemplo, SQL).
Eles adicionaram a classe SqlFunctions novamente no .NET 4 e eu estou apenas aprendendo sobre isso? Excelente localização.
O problema é que você está chamando o ToString em uma consulta LINQ to Entities. Isso significa que o analisador está tentando converter a chamada ToString em seu SQL equivalente (o que não é possível ... daí a exceção).
Tudo o que você precisa fazer é mover a chamada ToString para uma linha separada:
Teve um problema semelhante. Resolvido, chamando ToList () na coleção de entidades e consultando a lista. Se a coleção for pequena, essa é uma opção.
— médico cínico
Observe que isso recuperará todas as entidades da página do banco de dados e fará a filtragem no lado do cliente em vez do banco de dados. Geralmente não é uma coisa boa.
— lambinator
É verdade que esse método seria ineficiente para qualquer tabela que contenha mais de um registro, significando todas as tabelas existentes :-). No entanto, essa resposta me ajudou hoje porque eu estava fazendo uma projeção .Select que incluía toString (), portanto, chamar .ToList () antes não tinha nenhuma penalidade de desempenho para mim e chamar .ToList () me permitiu usar o .ToString () formatação e minha declaração .Select ...
Altere assim e deve funcionar:
O motivo pelo qual a exceção não é lançada na linha em que a consulta LINQ é declarada, mas na linha do foreaché o recurso de execução adiada, ou seja, a consulta LINQ não é executada até que você tente acessar o resultado. E isso acontece no foreache não antes.
Transmitir tabela para Enumerable, então você chama métodos LINQ usando o ToString()método dentro:
Mas tenha cuidado ao chamar métodos AsEnumerableou ToListporque você solicitará todos os dados de todas as entidades antes desse método. No meu caso acima, li todas as table_namelinhas por uma solicitação.
normalmente não é uma boa escolha, .AsEnumerable () colocar todos os dados na memória, você pode ver mais sobre ele aqui: stackoverflow.com/questions/3311244/...
— kavain
A atualização para o Entity Framework Versão 6.2.0 funcionou para mim.
Eu estava anteriormente na versão 6.0.0.
— 93Ramadan
No MVC, suponha que você esteja pesquisando registros com base em seus requisitos ou informações. Está funcionando corretamente.
Para uma prática melhor, ou nos tipos de código de produção, você sempre deve ter os eventos do banco de dados em uma camada de serviço ou camada de dados e não diretamente na ação.
— TREPRODUZINDO #
Se você realmente deseja digitar ToStringdentro de sua consulta, pode escrever um visitante da árvore de expressão que reescreva a chamada ToStringcom uma chamada para a StringConvertfunção apropriada :
— Zev Spitz
Deve estar usando FirstOrDefault e não apenas First ... Se for uma chave primária, use Find, pois isso tem um desempenho melhor.
— TREVETT4
@TGarrett O único uso Firstaqui é nos resultados dos GetMethods()quais retorna MethodInfo[]. AFAIK, MethodInfo[]não possui um Findmétodo, nem existe um método de extensão. Mas eu realmente devo usar Singleporque esse método está sendo encontrado via reflexão e não haverá um erro em tempo de compilação se o método apropriado não puder ser resolvido.
— Zev Spitz 04/10
Eu recebi o mesmo erro neste caso:
Depois de passar muito tempo depurando, descobri que o erro aparecia na expressão lógica.
A primeira linha search.Contains(log.Id.ToString())funciona bem, mas a última linha que lida com um objeto DateTime fez com que falhasse miseravelmente:
Remova a linha problemática e o problema resolvido.
Eu não entendo completamente o porquê, mas parece que ToString () é uma expressão LINQ para strings, mas não para Entidades. O LINQ for Entities lida com consultas de banco de dados como SQL e SQL não tem noção de ToString (). Como tal, não podemos lançar ToString () em uma cláusula .Where ().
Mas como funciona a primeira linha? Em vez de ToString (), o SQL tem CASTe CONVERT, portanto, o meu melhor palpite até agora é que o linq for entity use isso em alguns casos simples. Os objetos DateTime nem sempre são tão simples ...
— pekaaw
Basta transformar a consulta LINQ to Entity em uma consulta LINQ to Objects (por exemplo, chamar ToArray) sempre que precisar usar uma chamada de método na sua consulta LINQ.
"sempre que você precisar usar uma chamada de método" é um péssimo conselho - com muitos registros, isso pode ser um grande problema. A resposta aceita é muito melhor para esse cenário.