Dapper 'Caracteres encontrados después del final de la declaración de SQL.' - Stop Dapper devuelve el valor de identidad




 Estoy usando Dapper con Microsoft Access (no te lo aseguro, por elección propia) y también estoy usando las extensiones Dapper.Contrib para permitirme hacer la `connection.Insert(address)` . Insertar `connection.Insert(address)` . Desafortunadamente eso arroja un error `'Characters found after end of SQL statement.'` porque, supongo, el dapper SQL genera está haciendo la inserción y luego pregunta por `SCOPE_IDENTITY` y Access no quiere que varias declaraciones SQL separadas por a `;` . 

 ¿Hay alguna manera de decirle a Dapper que no intente devolver el valor de identidad? 

 He [echado](https://github.com/StackExchange/Dapper/blob/master/Dapper.Contrib/SqlMapperExtensions.cs) un vistazo al [código fuente de Dapper.Contrib](https://github.com/StackExchange/Dapper/blob/master/Dapper.Contrib/SqlMapperExtensions.cs) y parece que no tengo suerte.
Así que como una actualización sobre esto: no pude hacer que Dapper.Contrib funcionara bien con Access, así que al final [cambié](http://www.toptensoftware.com/petapoco/) de Dapper a [PetaPoco](http://www.toptensoftware.com/petapoco/) . Eso ha estado vivo en el sistema de producción desde hace un tiempo y se ha comportado muy bien con Access. 

 Un aspecto muy útil de PetaPoco es que en lugar de ser una DLL compilada, simplemente agrega un solo archivo PetaPoco.cs a su proyecto, lo que hace que la depuración sea mucho más fácil. 

 Otros micro-ORM están disponibles, etc., pero PetaPoco ha sido una buena solución para usar con Microsoft Access hasta el momento.
*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. 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. **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> 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()` ... 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. Recibí una respuesta de Brice Lambson que trabaja en el equipo central de EF: 


>  Vas en la dirección correcta: abre las conexiones menos. Recuerde, las conexiones SQLite son esencialmente secuencias de archivos, por lo que mantenerlas abiertas por más tiempo no es realmente un problema. 
> 
>  **Si solo hay una instancia de DbContext por conexión, DbContext aún puede ser propietario de la conexión, incluso si se crea externamente. Simplemente disponga la conexión dentro de DbContext.Dispose ().** 
> 
>  Si eso no es suficiente, puede intentar crear un grupo de conexiones. La gestión de la vida puede ser difícil. Lo importante es que una conexión no se usa fuera del hilo en el que se creó. 
> 
>  El uso de Cache = Shared (es decir, [Shared-Cache Mode](https://www.sqlite.org/sharedcache.html) ) también puede ayudar al rendimiento. 
> 
> Se puede extraer información de archivos, utilizando un DTP (Data Transformation Package), en el Enterprise Manager, selecciona tu servidor, y después la opción: Data Transformation Services, sobre la opción Local Package, oprime el botón derecho y luego la opción New Package. Un DTP, se crea en forma gráfica, solo necesitas seleccionar el icono de archivo de texto fuente y el icono Microsoft Ole DB Provider for SQL Server. Posteriormente seleccionas oprimiendo la tecla Control, el icono de archivo de texto fuente y después sin soltarla el icono de Microsoft Ole DB provider for SQL Server. En la parte de arriba oprime la opción: Transform Data Task, aparecerá una flecha entre ambas conexiones. Le debes de dar doble click sobre esta flecha y especificar las opciones de Origen y destino. Así como que campos corresponden con las columnas del archivo de texto. Por ultimo para ejecutarlo oprime la flecha verde. los conectores (también llamados nexos o relaciones) son frases o palabras que se utilizan para conectar o vincular una idea con otra en un texto (oral u escrito). los conectores permiten que el texto tenga una estructura lógica y coherente, y su ausencia o su mala utilización vuelven difícil la comprensión de las ideas.

tipos de conectores con ejemplos:

conectores de causa. determinan causalidad, por ejemplo: dado que, debido a, gracias a, por culpa de, porque, puesto que.

conectores copulativo. unen expresiones, por ejemplo: y, e, ni.

conectores disyuntivos. unen expresiones que plantean dos opciones contrapuestas, por ejemplo: o, u.

conectores de argumentación. se utilizan para explicar un argumento, por ejemplo: a saber, de lo contrario, por otra parte, sobre todo, por último.

conectores de cronología. determinan el orden de las acciones, por ejemplo: en primer lugar, ante todo, finalmente, luego, más tarde.

conectores de consecuencia. determinan consecuencia, por ejemplo: a fin de, de manera que, entonces, por consiguiente, por eso.

conectores de referencia. se utilizan para establecer las relaciones entre conceptos, por ejemplo: de esta manera, en cuanto a, en lo que respecta, respecto de, según.

conectores de resumen. introducen la síntesis de la información, por ejemplo: en pocas palabras, en resumen, resumiendo, para resumir, en concreto.

conectores de temporalidad. indican la temporalidad de la acción, por ejemplo: ahora, antes, apenas, en aquel tiempo, hoy en día, hasta.

conectores de oposición o adversativos. unen partes contrapuestas, por ejemplo: al contrario, aunque, a pesar de, no obstante, pero, sin embargo.

conectores de ilustración o explicativos. introducen la explicación de lo anteriormente dicho, por ejemplo: en otras palabras, por ejemplo, o sea, es decir, así.

conectores de condición. expresan condición, por ejemplo: en caso de que, siempre que, suponiendo que, si, con tal que.

conectores de comparación. introducen una comparación entre los elementos o entre dos oraciones, por ejemplo: más que, menos que, a diferencia de.

conectores concesivos. introducen un condicionamiento que puede ser sorteado o superado, por ejemplo: aunque, a pesar de, pese a.

conectores de lugar. introducen el escenario en el que se desarrolla la acción, por ejemplo: donde, en donde, adonde.

conectores de modo. introducen la manera en la que se lleva a cabo la acción, por ejemplo: según, tal como, así como.

ejemplos de conectores:

a fin de

entonces

a saber

para terminar

por otra parte

en seguida

en concreto

de tal manera que

en cambio

al principio

con la condición de que

por último

con el objeto de

además

primeramente

en cuanto a esto

brevemente

al mismo tiempo

gracias a

una vez

en caso de que

en lo que respecta

por más que

antes

siempre que

en conclusión

de esta manera

ahora

en aquel tiempo

con tal que

acto seguido

en primer lugar

respecto a

finalmente

en nuestros días

a consecuencia de

cuando

sobre todo

desde entonces

érase una vez

primero

en cuanto a

en este caso

por eso

en pocas palabras

aunque

para resumir

a pesar de

resumiendo

por lo tanto

respecto de

segundo

de lo contrario

en aquellos días

hasta

más tarde

es decir

actualmente

una vez que

puesto que

en segundo lugar

desde

suponiendo que

mientras tanto

en otras palabras

tan pronto como

hoy en día

tercero

sin embargo

si

al respecto

pero

al contrario

según

antes que nada

por culpa de

en tercer lugar

de manera que

para

por ejemplo

ya que

como

cuarto

mientras que

de esa manera

o sea

por consiguiente

no obstante

debido a

mientras

en cuarto lugar

así

porque

dado que

por una parte

visto que

ahora que

ejemplos de oraciones con conectores:

pienso, luego existo.

fueron a la fiesta después del examen.

viajaron a méxico durante el receso de vacaciones.

en pocas palabras, es el hombre más afortunado del mundo.

quisieron ayudarlo, aunque no había nada que hacer.

para resumir, todo salió como lo esperaban.

en resumen, nos prohibieron el acceso por dos semanas.

ante todo, pedimos disculpas a los afectados.

apenas consiga un trabajo, comenzaré a ahorrar.

para empezar, quisiera agradecer a los aquí presentes. Ok te ayudo pero no me aclaro.  
Voy a corregir algunas de tus palabras  
y me dices si he acertado o no.En caso  
Negativo corrígeme. Gracias.   
Buenas tardes. Tengo una MDB que importa DE un txt QUE CONTIENE los albaranes introducidos en diferentes terminales de venta:CAMPOS o COLUMNAS... Proveedor, nº\_albarán, Fecha\_albarán, cod\_artic, deno\_artic, unidades, p\_costo y Total . El problema es que solo se rellena EN EL TXT el campo nº\_albarán (campo texto) y Fecha\_albarán (campo Fecha/hora) en la primera FILA de cada uno, el resto de LOS REGISTROS O FILAS del mismo albarán NO muestran estos dos datos por lo que no puedo agruparlos UNA VEZ OBTENIDA LA TABLA por albarán, fecha y total (el txt muestra los mismos datos que la tabla, por lo que no es un problema de importación)Me indican que en VBA si se puede conseguir al importar el txt(COMENTARIO:QUE YO SEPA NO SE PUEDEN MANIPULAR LOS PARÁMETROS DE IMPORTACIÓN MEDIANTE CÓDIGO, PERO NO HACE FALTA, HAY OTRAS FORMAS, MEDIANTE CÓDIGO PODEMOS MODIFICAR EL TXT ANTES DE IMPORTAR) pero mis conocimientos son muy básicos y no entiendo este lenguaje de programación. ¿Existe otro modo de hacer que en caso de valor Null tome el valor del mismo campo en la FILA O REGISTRO anterior?   
Gracias por la ayuda   
  
Otra cosa:1-abre el txt con el wordpad e intenta hacer"reemplazar texto"  
A ver si puedes repararlo tu mismo y nos ahorramos trabajo.  
2-Mandame un fragmento de txt de 2 o 3 albaranes a mi mail  
que encontraras en mi currículo.  
Esto funcionará muy pronto! 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)