Estoy tratando de encontrar la diferencia entre usar SqlBulkCopy con la opción de copia SqlBulkCopyOptions.UseInternalTransaction
y sin ella, pero en mi aplicación de prueba no detecté ninguna diferencia. Si BatchSize
es por ejemplo 0 y agrego 100 registros (en un DataTable
) donde el registro número 50 causa un error al agregarlo a la tabla de la base de datos, obtengo 0 registros en la tabla. Si BatchSize
se establece en 10, por ejemplo, obtengo 40 registros (4 lotes de 10 registros, el quinto incluye el registro defectuoso y hace que la copia masiva se cancele). No importa si S qlBulkCopyOptions.UseInternalTransaction
está configurado o no, siempre obtengo el mismo resultado. Parece que los lotes siempre se copian en una transacción interna.SqlBulkCopy: ¿Cuál es la diferencia entre pasar SqlBulkCopyOptions.UseInternalTransaction y no pasarlo?
Si usted está interesado en mi aplicación de prueba, aquí está: SqlBulkCopy-Error-and-Transaction-Test.zip
Mis preguntas son:
- Es
SqlBulkCopyOptions.UseInternalTransaction
obsoleta porqueSqlBulkCopy
siempre utiliza las transacciones internas? - En caso negativo: ¿Cuál es el significado real de esta opción? ¿En qué casos haría la diferencia?
espero que alguien pueda aclarar
Editar: De acuerdo con la respuesta y los comentarios que supongo que mi problema no ist suficientemente claro. Sé la documentación. Dice que "de forma predeterminada, una operación de copia masiva es su propia transacción". y que cada lote usa su propia transacción al pasar UseInternalTransaction
. Pero si eso significa que, de forma predeterminada, la operación de copia masiva usa solo una transacción para toda la copia masiva (y no una para cada lote) no obtendría registros en la base de datos si configuro BatchSize a un determinado tamaño y un lote que se encuentra después el primero causa un error. Si solo se utilizara una transacción, se revertirían todos los registros agregados al registro de transacciones. Pero obtengo los registros de los lotes que se encuentran antes del lote que incluye el registro defectuoso. Según esto, parece que, por defecto, cada lote se ejecuta en su propia transacción. Eso significa que no importa si paso UseInternalTransaction
o no. Si estoy en el camino equivocado aquí, realmente agradecería que alguien pudiera aclarar.
Un hecho podría ser importante: uso SQL Server 2012. Tal vez el SQL Server 2008 se comporte de manera diferente. Lo comprobaré.
Editar: Gracias a la respuesta de usr Creo que he encontrado la respuesta: Me depurado y perfilado un poco y descubrí que la _internalTransaction ámbito privado está realmente no establece si UseInternalTransaction no está definido. SqlBulkCopy no usa una transacción propia (interna). Pero los perfiles indicaron que SqlBulkCopy usa TDS (flujo de datos tabulares) para copiar los datos (sin importar qué BatchSize sea). No encontré mucha información sobre TDS especialmente para SQL Server, pero supongo que SQL Server ejecuta las operaciones de copia masiva de TDS en una transacción interna. Por lo tanto, UseInternalTransaction parece ser algo redundante para SQL Server, pero para estar seguro lo configuré.
http://msdn.microsoft.com/en-us/library/tchktcdk%28v=vs.80%29.aspx –
Gracias Tim. Sí, la documentación dice "Por defecto, una operación de copia masiva es su propia transacción". Un poco más tarde dice "Puede especificar explícitamente la opción UseInternalTransaction en el constructor de la clase SqlBulkCopy para provocar explícitamente que se ejecute una operación de copia masiva en su propia transacción, haciendo que cada lote de la operación de copia masiva se ejecute dentro de una transacción separada". Esto es confuso. ¡Y mi aplicación de prueba no muestra una sola diferencia! Ver mi comentario a la respuesta de Arion. Solo si paso una transacción propia, obtengo 0 registros agregados en caso de error. Prueba mi aplicación de prueba ... –
Tim Schmelter: El enlace es irrelevante. No aclara la cuestión de cómo escribir ** un lote ** en el servidor sin una transacción. Si entiendo la pregunta de OP, no se trata de cómo hacer que toda la operación de copia masiva sea una transacción. Confirmo el hallazgo de Jurgen. UseInternalTransaction no es efectivo en este caso. – JohnC