La consulta de Entity Framework Core linq devuelve InvalidCastException




 Actualmente estoy creando una api web en .net CORE con Entity Framework. 

 Cada vez que intento seleccionar un único registro por ID con linq, aparece el siguiente error: 


>  Se produjo una excepción de tipo 'System.InvalidCastException' en Microsoft.EntityFrameworkCore.dll pero no se manejó en el código de usuario. 
> 
>  Información adicional: No se puede convertir el objeto de tipo 'System.Int32' para escribir 'System.Char'. 
> 
> 

 Este error ocurre cuando ejecuto la siguiente consulta de linq: 


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

```
  Ya lo he comprobado, y tanto el `UserId` como el `id` variable son enteros. También la tabla contiene suficientes elementos y existe una fila con un `id` de 1. 

 ¿Alguien puede decirme qué estoy haciendo mal aquí? 

 EDITAR: Aquí es una parte del modelo de `User` : 


```
public class User
{
    public int UserId { get; set; }
    (...)
}

```
*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.
Los ejemplos que otros han dado no funcionarán en Entity Framework hoy, porque no se pueden combinar enumeración de clientes y servidores en las entidades LINQ 2. 

 En su lugar, necesita construir una expresión OR, manualmente. 

 Ejecuto una serie de [consejos](http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx) de [EF](http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx) y [este consejo](http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx) te muestra cómo construir una expresión OR. 

 Espero que esto ayude 

 Alex 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()` ... **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. El equipo de EF, junto con P&P, se encuentra actualmente en el proceso de desarrollar una implementación de referencia de acceso a datos de EF (versión 4) que utiliza ASP.NET MVC como la interfaz. 

 El proyecto estará disponible de forma iterativa en CodePlex aquí: 

 <http://dataguidance.codeplex.com/> 

 Aún no hemos hecho nuestra primera fuente, pero ocurrirá en las próximas semanas. 

 ACTUALIZACIÓN: ahora hemos eliminado el código; tenga en cuenta que debe considerarse de calidad alfa y está sujeto a cambios. pues solo la plantilla ojdt. revisa bien la plantilla csv o txt que parece que tiene o detecta más columnas de las que estás pasando…

configura la plantilla de nuevo partiendo de cero o elimina todas las columnas y filas que te sobren… deberías verificar inicialmente si la condición del error es la siguiente:  
<http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q236/2/86.asp&nowebcontent=1>  
  
suerte! 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) hola quiero que me corrigan ese error desde internet en linea estando concectado OK. De movida te comento que no será sencillo, pero podemos resolvvero por aproximaciones sucesivas.  
Como me están faltando datos respecto al diseño de tu hoja. Supongo que la base de datos tiene cantidades irregulares de registros para cada persona, pero seguramente puedes saber cuantos tiene el de mayor cantidad de líneas. Asumo, además, que la base está ordenada por ID.  
Una combinación de las funciones INDICE y COINCIDIR funcionan en forma similar al BUSCARV. Pero en el caso que planteas -creo- sería la solución a tu problema.   
Vale decir que, si la función COINCIDIR encuentra el valor buscado (ID) en la primer columna traerá los datos en cada línea de acuerdo a la fila donde la fórmula se encuentre.   
Tal fórmula sería como esta:   
=INDICE(Hoja2!$C$5:$G$20;COINCIDIR($I$5;Hoja2!$C$5:$C$20;0)+FILA()-FILA($I$5);COLUMNA()-COLUMNA($I$5)+1)   
[Considera si sueles usar comas o punto y coma para separar argumentos de las funciones. Yo usé ";"]  
Está fórmula copiada en las celdas inferiores traerá los datos como quieres, pero adolece de un problema, necesitas saber de antemano cuántos registros tienes para el que estas buscando y contar con una cantidad igual de líneas de fórmulas de búsqueda.   
Para evitar ese problema, la siguiente fórmula agrega un control:   
=SI($I$5=INDICE(Hoja2!$C$5:$G$20;COINCIDIR($I$5;Hoja2!$C$5:$C$20;0)+FILA()-FILA($I$5);1);INDICE(Hoja2!$C$5:$G$20;COINCIDIR($I$5;Hoja2!$C$5:$C$20;0)+FILA()-FILA($I$5);COLUMNA()-COLUMNA($I$5)+1);"")   
INDICE muestra un dato de una matriz (C5:G20 de la hoja2) de acuerdo a las coordenadas de fila y columna que se le indique como argumentos.   
Para obtener la coordenada Fila usamos la función COINCIDIR en un rango (C5:C20 de Hoja2) de la misma altura (misma cantidad y ubicación de las líneas) que la base de búsqueda. Al número de fila así obtenido le agregará tantas líneas como diferencia halla entre la fila donde está la fórmula y la fila donde está el dato a buscar. Así, si la fórmula estuviera en la misma fila que el dato, tal diferencia será cero y, por lo tanto, traerá el dato de la misma fila.   
Al copiar esta celda y pegarla en la fila inferior, la diferencia será 1, por lo tanto traerá el valor de la fila siguiente de la base original. Y así sucesivamente.   
De igual modo, para identificar de qué columna traer el dato, restará la columna actual menos la primera.   
De esta manera, la misma fórmula copiada al resto del rango donde debe traer los valores servirá al propósito sin tener que modificarla.   
Aquí vale aclarar que, si no quieres todas las columnas, puedes especificarle exactamente qué columna necesitas, reemplazando la expresión COLUMNA()-COLUMNA($I$5)+1) por el número de la columna a mostrar  
El control que le agregué, verifica que en cualquier fila que se esté buscando se trate de la misma persona que se buscó originalmente.   
Lo único que tendrás que tener en cuenta es tener una cantidad de lineas de esta fórmula de búsqueda igual al mayor número de registros que pueda tener una persona.   
Por ejemplo, supongamos que buscar los datos de los hijos de cada empleado. Si hubiera un fecundo con 10 hijos, tendrás que tener 10 filas con aquella fórmula que te sugerí. Para los que tengan menos de 10, las celdas excedentes no mostrarán nada. Pero si hubiera uno con once o doce, sólo mostrará hasta el décimo.   
Por último, si -eventualmente- necesitaras otro set de estas fórmulas para buscar otro código en otro rango de la hoja "Datos" necesitarás, primero quitarle la referencia absoluta a la celda donde está e primer código (I5).   
Nota que, apropósitamente, todas las referencias a la linea del código dicen $I$5 de forma tal que siempre lean esa celda a cada uno de sus efectos.   
Lo que suelo hacer, entonces, es seleccionar todo el rango de fórmulas (4 columnas por 8 filas) y hago "Edición" | "Reemplazar..." En la casilla Buscar: coloco $I$5 y en la de reemplazar con escribo I5. Finalmente presiono "Reemplazar todo"   
Si bien todas las fórmulas modificadas siguen "apuntando" a la celda I5, esta es ahora una referencia relativa a tal celda. Esto permite que al copiarlas a otro rango lean una posición distinta a I5.   
Por ejemplo, si tu otro código a buscar estuviera en la celda I14 y copias este set de fórmulas a partir de esa misma fila, todas leerán los datos de la celda I14.   
Lo dicho: No es una tarea simple, pero si sigues cuidadosamente las instrucciones, llegarás al objetivo.  
- Ingresa al sitio www.porloschicos.com y, si quieres,   
presiona el botón de donación (es gratis).   
Confío en que lo harás. **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>