c# - studio - LINQ to Entities no reconoce el método ''System.String ToString()'', y este método no se puede traducir a una expresión de tienda
linq mysql visual studio 2012 (11)
Cambiarlo así y debería funcionar:
var key = item.Key.ToString();
IQueryable<entity> pages = from p in context.pages
where p.Serial == key
select p;
La razón por la cual no se lanza la excepción en la línea de la consulta LINQ se declara, pero en la línea de foreach
está la característica de ejecución diferida, es decir, la consulta LINQ no se ejecuta hasta que intente acceder al resultado. Y esto sucede en el foreach
y no antes.
Estoy migrando algunas cosas de un servidor mysql a un servidor sql pero no puedo entender cómo hacer que este código funcione:
using (var context = new Context())
{
...
foreach (var item in collection)
{
IQueryable<entity> pages = from p in context.pages
where p.Serial == item.Key.ToString()
select p;
foreach (var page in pages)
{
DataManager.AddPageToDocument(page, item.Value);
}
}
Console.WriteLine("Done!");
Console.Read();
}
Cuando entra en el segundo foreach (var page in pages)
arroja una excepción que dice:
LINQ to Entities no reconoce el método ''System.String ToString ()'', y este método no se puede traducir a una expresión de tienda.
Alguien sabe por qué pasa esto?
Como otros han respondido, esto se rompe porque .ToString no puede traducir al SQL relevante en el camino a la base de datos.
Sin embargo, Microsoft proporciona la clase SqlFunctions que es una colección de métodos que se pueden usar en situaciones como esta.
Para este caso, lo que está buscando aquí es SqlFunctions.StringConvert :
from p in context.pages
where p.Serial == SqlFunctions.StringConvert((double)item.Key.Id)
select p;
Bueno cuando la solución con variables temporales no es deseable por las razones que sean.
Similar a SqlFunctions también tiene EntityFunctions (con EF6 obsoleta por DbFunctions ) que proporciona un conjunto diferente de funciones que también son DbFunctions origen de datos (no limitado a, por ejemplo, SQL).
El problema es que llama a ToString en una consulta LINQ to Entities. Eso significa que el analizador intenta convertir la llamada ToString en su SQL equivalente (que no es posible ... de ahí la excepción).
Todo lo que tiene que hacer es mover la llamada ToString a una línea separada:
var keyString = item.Key.ToString();
var pages = from p in context.entities
where p.Serial == keyString
select p;
En MVC, suponga que está buscando registro (s) en función de sus requisitos o información. Está funcionando correctamente.
[HttpPost]
[ActionName("Index")]
public ActionResult SearchRecord(FormCollection formcollection)
{
EmployeeContext employeeContext = new EmployeeContext();
string searchby=formcollection["SearchBy"];
string value=formcollection["Value"];
if (formcollection["SearchBy"] == "Gender")
{
List<MvcApplication1.Models.Employee> emplist = employeeContext.Employees.Where(x => x.Gender == value).ToList();
return View("Index", emplist);
}
else
{
List<MvcApplication1.Models.Employee> emplist = employeeContext.Employees.Where(x => x.Name == value).ToList();
return View("Index", emplist);
}
}
La actualización a Entity Framework versión 6.2.0 funcionó para mí.
Anteriormente estaba en la versión 6.0.0.
Espero que esto ayude,
Si realmente desea escribir ToString
dentro de su consulta, puede escribir un visitante del árbol de expresiones que reescribe la llamada a ToString
con una share :
using System.Linq;
using System.Data.Entity.SqlServer;
using System.Linq.Expressions;
using static System.Linq.Expressions.Expression;
using System;
namespace ToStringRewriting {
class ToStringRewriter : ExpressionVisitor {
static MethodInfo stringConvertMethodInfo = typeof(SqlFunctions).GetMethods()
.Single(x => x.Name == "StringConvert" && x.GetParameters()[0].ParameterType == typeof(decimal?));
protected override Expression VisitMethodCall(MethodCallExpression node) {
var method = node.Method;
if (method.Name=="ToString") {
if (node.Object.GetType() == typeof(string)) { return node.Object; }
node = Call(stringConvertMethodInfo, Convert(node.Object, typeof(decimal?));
}
return base.VisitMethodCall(node);
}
}
class Person {
string Name { get; set; }
long SocialSecurityNumber { get; set; }
}
class Program {
void Main() {
Expression<Func<Person, Boolean>> expr = x => x.ToString().Length > 1;
var rewriter = new ToStringRewriter();
var finalExpression = rewriter.Visit(expr);
var dcx = new MyDataContext();
var query = dcx.Persons.Where(finalExpression);
}
}
}
Simplemente convierta la consulta de LINQ a Entity en una consulta de LINQ to Objects (por ejemplo, llame a ToArray) cada vez que necesite usar una llamada de método en su consulta LINQ.
Simplemente guarde la cadena en una variable de temperatura y luego use eso en su expresión:
var strItem = item.Key.ToString();
IQueryable<entity> pages = from p in context.pages
where p.Serial == strItem
select p;
El problema surge porque ToString()
no se ejecuta realmente, se convierte en un MethodGroup y luego se analiza y se convierte a SQL. Como no hay equivalente ToString()
, la expresión falla.
Nota:
Asegúrate también de verificar la respuesta de Alex con respecto a la clase de ayuda SqlFunctions
que se agregó más tarde. En muchos casos puede eliminar la necesidad de la variable temporal.
Tengo el mismo error en este caso:
var result = Db.SystemLog
.Where(log =>
eventTypeValues.Contains(log.EventType)
&& (
search.Contains(log.Id.ToString())
|| log.Message.Contains(search)
|| log.PayLoad.Contains(search)
|| log.Timestamp.ToString(CultureInfo.CurrentUICulture).Contains(search)
)
)
.OrderByDescending(log => log.Id)
.Select(r => r);
Después de pasar demasiado tiempo depurando, descubrí que el error apareció en la expresión lógica.
La primera línea search.Contains(log.Id.ToString())
funciona bien, pero la última línea que trata con un objeto DateTime lo hace fallar miserablemente:
|| log.Timestamp.ToString(CultureInfo.CurrentUICulture).Contains(search)
Elimine la línea problemática y el problema resuelto.
No entiendo completamente por qué, pero parece que ToString () es una expresión LINQ para cadenas, pero no para Entidades. LINQ for Entities trata con consultas de bases de datos como SQL, y SQL no tiene ninguna noción de ToString (). Como tal, no podemos lanzar ToString () en una cláusula .Where ().
¿Pero cómo funciona la primera línea? En lugar de ToString (), SQL tiene CAST
y CONVERT
, así que mi mejor estimación hasta ahora es que linq para entidades lo usa en algunos casos simples. Los objetos DateTime no siempre son tan simples ...
Transmitir tabla a Enumerable
, luego llama a los métodos LINQ con el uso del método ToString()
dentro de:
var example = contex.table_name.AsEnumerable()
.Select(x => new {Date = x.date.ToString("M/d/yyyy")...)
Pero tenga cuidado al llamar a los métodos AsEnumerable
o ToList
porque solicitará todos los datos de todas las entidades antes de este método. En mi caso anterior, leí todas las filas de table_name
en una solicitud.
Tuve un problema similar. Lo resolvió llamando a ToList () en la colección de entidades y consultando la lista. Si la colección es pequeña, esta es una opción.
IQueryable<entity> pages = context.pages.ToList().Where(p=>p.serial == item.Key.ToString())
Espero que esto ayude.