Saltar al contenido

¿Cómo funciona SqlBulkCopy?

Es imprescindible entender el código de forma correcta previamente a usarlo a tu proyecto y si ttienes algo que aportar puedes decirlo en los comentarios.

Solución:

SqlBulkCopy no crea un archivo de datos. Transmite la tabla de datos directamente desde el objeto .Net DataTable al servidor utilizando el protocolo de comunicación disponible (Named Pipes, TCP / IP, etc.) e inserta los datos en la tabla de destino de forma masiva utilizando la misma técnica utilizada por BCP .

Tomó 7 años, pero finalmente tenemos una respuesta …

Al exponer la respuesta de Sam Anwar, puedo confirmar que está convirtiendo los datos en un flujo de bytes sin procesar y escribiéndolos en SQL como si se transmitieran desde un archivo. Cómo engaña a SQL para que piense que está leyendo un archivo.

Quería hacer una inserción masiva desde el interior de una consulta, para acelerar una inserción de índice agrupada lenta. Al encontrar su publicación aquí, de alguna manera me intrigó inquietantemente, así que pasé las últimas horas estudiándola.

La ruta de ejecución que realmente escribe datos en el servidor parece ser:

Tu codigo:

  1. Su código llama a System.Data.SqlClient.SqlBulkCopy.WriteToServer ()

dentro de System.Data.SqlClient.SqlBulkCopy:

  1. que llama a WriteRowSourceToServerAsync ()
  2. que llama a WriteRowSourceToServerCommon () para mapear las columnas y WriteToServerInternalAsync () para escribir los datos
  3. que llama a WriteToServerInternalRestContinuedAsync ()
  4. que llama a AnalyzeTargetAndCreateUpdateBulkCommand () (Esta es la respuesta. Vaya al paso 14 para obtener más información). y CopyBatchesAsync ()
  5. que (CopyBatchesAsync) llama a SubmitBulkUpdateCommand ()

– dentro de System.Data.SqlClient.TdsParser:

  1. que llama a System.Data.SqlClient.TdsParser.TdsExecuteSQLBatch ()
  2. que llama a WriteString () o métodos similares para convertir los datos en un byte array
  3. que llama a WriteByteArray ()
  4. que llama a WritePacket ()
  5. que llama a WriteSni ()
  6. que llama a SNIWritePacket ()

– dentro de System.Data.SqlClient.SNINativeMethodWrapper:

  1. que llama a System.Data.SqlClient.SNINativeMethodWrapper.SNIWritePacket ()
  2. cual externo llama a SNIWriteAsyncWrapper () o SNIWriteSyncOverAsync ()

Ahora aquí es donde se pone complicado. I pensar esto sigue, pero cómo llegué allí es un poco hacky. Abrí las propiedades del archivo en mi copia de sni.dll, fui a la pestaña de detalles y dentro de la propiedad Versión del producto encontré una referencia a un “hash de confirmación” de d0d5c7b49271cadb6d97de26d8e623e98abdc8db.

Así que busqué en Google ese hash y, a través de esta búsqueda de Nuget, encontré este paquete de Nuget, cuyo título incluye “System.Data.SqlClient.sni”, que implica el espacio de nombres System.Data.SqlClient.SNI, que encontré aquí, pero esto no tiene los métodos correctos y en realidad no parece comunicarse con un servidor.

Así que aquí es donde me quedé sin conocimientos técnicos; esto es lo más profundo que pude antes de que entre en el código nativo que no puedo encontrar en ningún lado. Y aunque no estoy seguro de qué fue todo ese otro ruido de arriba …

  1. Recuerde el paso 4 (WriteToServerInternalRestContinuedAsync ()) también llama a AnalyzeTargetAndCreateUpdateBulkCommand ()
  2. que concatena una consulta SQL dentro de un StringBuilder llamado updateBulkCommandText. Línea 544 en ese último enlace.

TLDR: En última instancia, parece que solo ejecuta un INSERTAR GRANEL consulta (que no requiere un archivo), y en realidad no usa INSERCIÓN A GRANEL (que lo hace). Tenga en cuenta que estos dos comandos se ven muy similares.

Una nota importante en los documentos de Microsoft:

Utilizado por herramientas externas para cargar un flujo de datos binarios. Esta opción no está diseñada para su uso con herramientas como SQL Server Management Studio, SQLCMD, OSQL o interfaces de programación de aplicaciones de acceso a datos como SQL Server Native Client.

Lo que interpreto como “utilícelo bajo su propio riesgo y no espere ayuda”. Lo cual es casi tan bueno como una luz verde, para ser justos.

SqlBulkCopy puede usar una tabla de datos, IDataReader o DataRow[] como fuente de datos. Eche un vistazo a los métodos WriteToServer de la clase. Descubrí que es un mecanismo bastante útil para introducir datos en SQL Server. He usado esto junto con CSVReader anteriormente. El enlace anterior le da una idea de cómo funciona con una clase que implementa IDataReader.

Es posible que deba jugar con los tamaños de los lotes para asegurarse de obtener el rendimiento que espera.

La Guía de rendimiento de carga de datos en MSDN es un recurso bastante útil si está buscando obtener el mejor rendimiento al escribir grandes cantidades de datos rápidamente. Se centra más en cosas como BCP y BULK INSERT, pero toca SQLBulkCopy y también proporciona bastante material para pensar (quizás demasiado, pero es una referencia útil al menos de todos modos).

Aquí tienes las comentarios y calificaciones

Si haces scroll puedes encontrar las explicaciones de otros programadores, tú de igual manera eres capaz dejar el tuyo si lo crees conveniente.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *