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

Resuelto Erre Efe asked hace 13 años • 13 respuestas

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)lanza 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?

Erre Efe avatar May 05 '11 21:05 Erre Efe
Aceptado

Simplemente guarde la cadena en una variable temporal y luego úsela 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()en realidad no se ejecuta, se convierte en un MethodGroup y luego se analiza y traduce a SQL. Como no hay ToString()equivalente, la expresión falla.

Nota:

Asegúrese de consultar también la respuesta de Alex sobre la SqlFunctionsclase de ayuda que se agregó más adelante. En muchos casos, puede eliminar la necesidad de la variable temporal.

Josh avatar May 05 '2011 14:05 Josh

Como han respondido otros, esto se rompe porque .ToString no se traduce a SQL relevante en el camino hacia la base de datos.

Sin embargo, Microsoft proporciona la clase SqlFunctions , que es una colección de métodos que se pueden utilizar en situaciones como esta.

Para este caso, lo que estás 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 cualquier motivo.

De manera similar a SqlFunctions, también tiene EntityFunctions (con EF6 obsoleto por DbFunctions ) que proporciona un conjunto diferente de funciones que también son independientes del origen de datos (no limitado a, por ejemplo, SQL).

Alex avatar Jun 09 '2014 16:06 Alex

El problema es que está llamando a ToString en una consulta LINQ to Entities. Eso significa que el analizador está intentando convertir la llamada ToString en su SQL equivalente (lo cual no es posible... de ahí la excepción).

Todo lo que tienes 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;
Justin Niessner avatar May 05 '2011 14:05 Justin Niessner

Transmite la tabla a Enumerable, luego llamas a los métodos LINQ usando ToString()el método dentro:

    var example = contex.table_name.AsEnumerable()
.Select(x => new {Date = x.date.ToString("M/d/yyyy")...)

Pero tenga cuidado al llamar a métodos AsEnumerableo ToListporque solicitará todos los datos de todas las entidades antes de este método. En mi caso anterior, leo todas table_namelas filas mediante una solicitud.

kkost avatar Dec 29 '2016 13:12 kkost

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.

cynicaldoctor avatar Sep 28 '2012 13:09 cynicaldoctor