¿Por qué Entity Framework no podría usar ToString () en una declaración LINQ?




 Esto **funciona** en LINQ-to-SQL: 


```
var customersTest = from c in db.Customers
                select new
                {
                    Id = c.Id,
                    Addresses = from a in db.Addresses where c.Id.ToString() == 
                        a.ReferenzId select a
                };

foreach (var item in customersTest)
{
    Console.WriteLine(item.Id);
}

```
  Pero un ejemplo similar en Entity Framework recibe un **mensaje de error** que dice básicamente que no se puede "traducir a SQL", aquí está el mensaje de error original en alemán: 


>  "'LINQ to Entities' erkennt die Methode 'System.String ToString ()' nicht, und diese Methode kann nicht in einen Speicherausdruck übersetzt werden". 
> 
> 

 **Traducción:** 


>  "'LINQ to Entities' no reconoce el método 'System.String ToString ()', este método no se puede traducir a una expresión de memoria. 
> 
> 

 **¿Alguien puede arrojar alguna luz sobre cómo podemos lograr que este tipo de declaración funcione en Entity Framework o explicar por qué se produce este error?**
En pocas palabras: LINQ to Entities no conoce la conversión de su tipo de ID a una cadena. 

 ¿Cuál es el tipo de `c.ID` ? ¿Hay alguna razón por la que sea un tipo para ID, pero otro para `ReferenzId` ? Si es posible, conviértalos en el mismo tipo, en cuyo punto ya no tendrá más problemas. No sé si hay otras formas de realizar conversiones en LINQ a Entidades (puede haber), pero la alineación de los tipos sería más clara. 

 Por cierto, esto realmente parece que es una combinación: 


```
var query = from c in db.Customers
            join a in db.Addresses on c.Id equals a.ReferenzId into addresses
            select new { Id = c.Id, Addresses = addresses };

```
  EDITAR: Para responder a su comentario: `ToString` aparece en IntelliSense porque el compilador no tiene una idea real de lo que va a significar su consulta ni de cómo se traducirá. Es perfectamente válido C #, y puede generar un árbol de expresiones válido. Es solo que EF no sabe cómo convertir ese árbol de expresiones en SQL. 

 Puede *intentar* usar `Convert.ToString(c.Id)` lugar de simplemente llamar a `c.Id.ToString()` ...
*Nota: la respuesta se proporcionó en un comentario en la pregunta original. Solo le estoy agregando un poco aquí, para hacerlo más visible y claro.* 





 Entity Framework obviamente asigna clases de C # a tablas de bases de datos a través de propiedades que representan las distintas columnas en cada tabla. Ahora, si el tipo de datos de una de estas propiedades no es compatible con el tipo de datos de su columna correspondiente en la base de datos, obtendrá una `System.InvalidCastException` cuando intente recuperar algo de esa tabla, incluso si la propiedad no coincide no está directamente involucrada en la búsqueda 

 En la pregunta, la consulta fue: 


```
User user = context.Users.First(i => i.UserId == id);

```
  No importa que tanto `id` como su propiedad correspondiente `UserId` sean válidas y compatibles entre sí aquí, porque lo que se está buscando es una instancia de toda la clase de `User` . 

 Aparentemente, el tipo de alguna otra propiedad en el `User` es incompatible con el tipo una columna con el mismo nombre en la tabla de `user` en la base de datos, por lo que el intento de mapearlo arroja la excepción anterior. Básicamente hay varias cosas que puedes hacer. 

* usando `SqlBulkCopy.WriteToServer` que no funciona muy bien junto con EF, sin embargo, existen varios intentos para crear extensiones
* utilizando un procedimiento almacenado que tomará un registro grande y lo dividirá de acuerdo con alguna lógica
* utilizando parámetros de procedimiento almacenado escritos en la tabla y realice una llamada al procedimiento almacenado (y varias `insert ... select` dentro del procedimiento almacenado)

 En general, prefiero la tercera opción. 

 Marque esta pregunta [Entity Framework Stored Procedure Tabla Valor Parámetro](https://stackoverflow.com/questions/8157345/entity-framework-stored-procedure-table-value-parameter) Permítanme comenzar replanteando la pregunta de una manera más concisa. 


>  Una expresión lambda se puede convertir a la `Expression<T>` donde `T` es un tipo de delegado compatible con la expresión lambda. `Expression<T>` se deriva de `LambdaExpression` . ¿Por qué entonces no podemos convertir una expresión lambda directamente a `LambdaExpression` ? 
> 
> 

 La razón es: porque esta es una de las situaciones raras en C # donde la información de tipo fluye desde el *tipo de objetivo de asignación* al *tipo de cosa que se asigna* . El compilador debe conocer el tipo de delegado al convertir un lambda; **el compilador de C # no deduce el tipo de delegado de la lambda, sino que verifica que la lambda es compatible con el tipo de delegado dado** . 

 Ahora, ¿podríamos haber diseñado e implementado un sistema en el que si la información de tipo no estuviera presente y el objetivo de conversión fuera `LambdaExpression` , se realizaría una estimación razonable? Por supuesto. No había nada que nos detuviera más que nadie que deseara o necesitara esa característica. 

 Pero la respuesta a la pregunta "¿por qué no existe esta característica?" Siempre es lo mismo. **No estamos obligados a dar una razón para no implementar una función** . Nadie solicitó esa característica, nadie la diseñó, la implementó, probó ni la envió a los clientes. Por lo tanto, ninguna característica. 

 Más bien, las características no existentes requieren que un defensor empiece a convertirlas en características existentes. Si esta es una función que desea o necesita, tómela en el foro de github y defienda la función. O implementarlo usted mismo; El compilador es de código abierto. El código de EF Core es exactamente el mismo. 


```
DbContext.Database.BeginTransaction(IsolationLevel.Snapshot);

```
  La única diferencia es que en EF Core el [método con nivel de aislamiento](https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.relationaldatabasefacadeextensions.begintransaction?view=efcore-2.1) (como muchos otros) es un método de *extensión* , definido en la clase [RelationalDatabaseFacadeExtensions](https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.relationaldatabasefacadeextensions?view=efcore-2.1) , y lo más importante, ubicado en [Microsoft.EntityFrameworkCore.Relational](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Relational/) ensamblado. 

 Entonces, si ha `using Microsoft.EntityFrameworkCore;` y no lo vea, agregue referencia al ensamblado / paquete `Microsoft.EntityFrameworkCore.Relational.dll` . El autor de este artículo está algo equivocado: en .NET 4.5, la propiedad [AsynchronousProcessing](http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder.asynchronousprocessing.aspx) se ignora porque ya no es necesaria. Puede comenzar a [llamar a los métodos Async](http://msdn.microsoft.com/en-us/library/hh211418.aspx) de SqlClient sin cadenas de conexión especiales. 

 Si las operaciones se ejecutarán de forma asíncrona, depende del proveedor de la base de datos. Por ejemplo, la implementación predeterminada de [DbCommand.ExecuteDbDataReaderAsync en](http://msdn.microsoft.com/en-us/library/system.data.common.dbcommand.executedbdatareaderasync.aspx) realidad se ejecuta de forma síncrona y bloquea el hilo de llamada. SqlCommand anula este método y se ejecuta de forma asíncrona. 

 Desafortunadamente, NpgsqlCommand no anula este método, por lo que solo le queda la ejecución síncrona. bueno, yo no puedo responder por qué no está disponible, pero me puede confirmar que no es un cli problema. el cli de especificaciones no lo menciona (por lo que puedo ver) y si utiliza il directamente, puede crear un atributo genérico. la parte de la c# 3 especificación de que la prohíbe sección 10.1.4 'de la clase base de la especificación de' no dar ningún tipo de justificación. anotado ecma c# 2 spec no da ninguna información útil, aunque no proporciona un ejemplo de lo que no está permitido. mi copia de la annotated c# 3 spec debería de llegar mañana... voy a ver si eso le da más información. de todos modos, es definitivamente un lenguaje de decisión en lugar de en tiempo de ejecución. edit: respuesta de eric lippert (parafraseado): sin ninguna razón en particular, excepto a evitar la complejidad en el lenguaje y compilador para un caso de uso que no agrega mucho valor. Si, si que podrás.   
ASP permite la conexión con bases de datos siempre y cuando estas tengan un driver ODBC, que access tiene en el sistema por defecto, así que podrás hacer cnsultas SQL a la base de datos, y si no me equivoco también a los ficheros Excel. Lo que te recomiendo es que te pases por [http://msdn.microsoft.com](https://msdn.microsoft.com/) y busques toda la información allí pues es donde mejor te pueden informar  
En cuanto a saber más de asp tienes   
[http://www.aspin.com](http://www.aspin.com/)  
A la base de datos puedes acceder o bien sabiendo el path o mediante un DSN que puedes asignarle a la base de datos en el sistema. Este ultimo es el método más cómodo.  
Si, puedes probarlo en un ordenador local ya sea windows ME, 9X o 2000, pues todos tienen su servidor web así como el interprete de ASP en el sistema.  
Espero haberte ayudado,  
un saludo. nada que ver. ecc (error-correcting code memory). se trata de un sistema para detectar y corregir los tipos m&aacute;s comunes de corrupci&oacute;n de datos. <br/><br/>pruebe con una memoria markvision, a ver que pasa. **Descargo de responsabilidad** : soy el propietario del proyecto [Bulk Operations](http://bulk-operations.net/) 

 En resumen, este proyecto supera las limitaciones de SqlBulkCopy al agregar características IMPRESCINDIBLES como generar un valor de identidad insertado. 

 Debajo del capó, utiliza SqlBulkCopy y un método similar como @Mr Moose answer. 


```
var bulk = new BulkOperation(connection)

// Output Identity Value
bulk.ColumnMappings.Add("CustomerID", ColumnMappingDirectionType.Output);

// Map Column
bulk.ColumnMappings.Add("Code");
bulk.ColumnMappings.Add("Name");
bulk.ColumnMappings.Add("Email");

bulk.BulkInsert(dt);

```
  **EDITAR:** Responder comentario 


>  ¿puedo simplemente obtener una lista IL o simplemente veo que está guardada en la tabla de clientes, pero no hay ninguna variable donde pueda obtenerla? ¿Pueden ayudarme con eso? Entonces, inserto en la tabla Orders.CustomerID 
> 
> 

 Depende, puede mantener una referencia a la fila de datos del cliente denominada `CustomerRef` en la `DataTable` pedido. 

 Entonces, una vez que fusionó a su cliente, puede completar fácilmente una columna `CustomerID` de la columna `CustomerRef` en su Tabla de datos de pedido. 

 Aquí hay un ejemplo de lo que estoy tratando de decir: <https://dotnetfiddle.net/Hw5rf3> **Compilacion** 

 La llamada a `Expression.Compile` pasa exactamente por el mismo proceso que cualquier otro código .NET que su aplicación contenga en el sentido de que: 

* Se genera el código IL
* El código IL está JIT-ted al código de máquina

 (se omite el paso de análisis porque ya se creó un árbol de expresión y no es necesario generarlo a partir del código de entrada) 

 Puede mirar el [código fuente](http://referencesource.microsoft.com/#System.Core/Microsoft/Scripting/Compiler/LambdaCompiler.cs) del compilador de expresiones para verificar que efectivamente se genera el código IL. 

 **Mejoramiento** 

 Tenga en cuenta que casi toda la optimización realizada por el CLR se realiza en el paso JIT, no desde la compilación del código fuente de C #. Esta optimización también se realizará al compilar el código IL de su delegado lambda a código máquina. 

 **Su ejemplo** 

 En su ejemplo, está comparando manzanas y naranjas. El primer ejemplo es una definición de método, el segundo ejemplo es código de tiempo de ejecución que crea un método, lo compila y lo ejecuta. El tiempo que lleva crear / compilar el método es mucho más largo que ejecutarlo realmente. Sin embargo, puede mantener una instancia del método compilado después de la creación. Cuando haya hecho eso, el rendimiento de su método generado debería ser idéntico al del método C # original. 

 Considere este caso: 


```
private static int AddMethod(int a, int b)
{
    return a + b;
}

Func<int, int, int> add1 = (a, b) => a + b;
Func<int, int, int> add2 = AddMethod;

var x = Expression.Parameter(typeof (int));
var y = Expression.Parameter(typeof (int));
var additionExpr = Expression.Add(x, y);
Func<int, int, int> add3 = 
              Expression.Lambda<Func<int, int, int>>(
                  additionExpr, x, y).Compile();
//the above steps cost a lot of time, relatively.

//performance of these three should be identical
add1(1, 2);
add2(1, 2);
add3(1, 2);

```
  Entonces, la conclusión que se puede sacar es: el código IL es código IL, sin importar cómo se genere, y las expresiones Linq generan código IL.