masivo improve framework c# .net entity-framework sqlbulkcopy

c# - improve - SqlBulkCopy y Entity Framework



insert entity framework c# (8)

Como complemento a la respuesta de @DaveHogan,

Ahora hay nuevas bibliotecas que permiten realizar inserciones masivas (usando SqlBulkCopy bajo el capó) para Entity Framework utilizando entidades de datos en lugar de DataTable.

Descargo de responsabilidad : soy el propietario del proyecto Entity Framework Extensions

Esta biblioteca no es gratuita pero permite realizar fácilmente:

  • BulkSaveChanges
  • BulkInsert
  • Actualización masiva
  • BulkDelete
  • BulkMerge

Debajo del capó, se utiliza SqlBulkCopy. Usar el método de extensión es mucho más fácil / rápido que codificar una solución personalizada para que lo use cada inserto masivo.

Ejemplo

// Easy to use context.BulkSaveChanges(); // Easy to customize context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

bajo rendimiento

Lamento que tengas un bajo rendimiento,

Asegúrese de no incluir el tiempo de algún error común, como olvidarse de JIT Compile, utilizando Agregar en lugar de AddRange que afectan el rendimiento de la prueba pero no está relacionado con nuestra biblioteca.

La mayoría de las personas informan que obtienen una mejora de rendimiento de entre 25 y 50 veces al excluir todos los errores comunes de referencia de rendimiento.

Ver: Extensiones de Entity Framework - Benchmark

Mi proyecto actual consta de 3 capas estándar: datos, negocios y presentación. Me gustaría usar entidades de datos para todas mis necesidades de acceso a datos. Parte de la funcionalidad de la aplicación será que deberá copiar todos los datos de un archivo plano en una base de datos. El archivo no es tan grande, así que puedo usar SqlBulkCopy. He encontrado varios artículos sobre el uso de la clase SqlBulkCopy en .NET. Sin embargo, todos los artículos utilizan DataTables para mover datos de un lado a otro.

¿Hay alguna forma de usar entidades de datos junto con SqlBulkCopy o tendré que usar DataTables?



Probamos y probamos un par de enfoques al realizar inserciones masivas con EF y finalmente fuimos con parámetros de valor de tabla para obtener el mejor rendimiento en un rango de tamaños de filas. No tengo los números disponibles, pero sé que este rendimiento de bcp / BULK INSERT frente a los parámetros de valores de tabla fue un factor de guía.

Originalmente, usamos SqlBulkCopy junto con un adaptador que tomó un IEnumerable<T> y creó un IDataReader . También generó los metadatos relevantes para SqlBulkCopy. La ventaja aquí era que la importación es solo un código. El código que @davehogan publicó se usó como base para esto.

Los parámetros con valores de tabla requieren un procedimiento almacenado y un tipo de tabla definidos en la base de datos. Si está utilizando el código primero, puede ejecutar SQL para crearlos como parte de su script de creación. Si bien esto es más trabajo, encontramos que obtuvimos un rendimiento significativamente más consistente y más rápido de filas en la base de datos.

Además, vale la pena considerar la no inserción masiva en la tabla principal. Usamos una tabla de almacenamiento temporal y le agregamos un índice agrupado una vez que se importan los datos. Luego realizamos un MERGE entre la tabla temporal y la tabla principal. Esto tiene la ventaja de no bloquear el índice de la tabla principal mientras se inserta y mejora la concurrencia. Tendemos a obtener más de 2500 filas / seg por CPU insertada usando este método.

Hazme saber si quieres más información.


Puede considerar que un conjunto de datos es una serialización de la entidad de datos. Sin embargo, en general, creo que SqlBulkCopy es una cosa de tabla a tabla, de ahí el motivo de las tablas de datos.



SqlBulkCopy es una transferencia directa, casi de tipo byte-array, de datos de filas del cliente a SQL Server. Es fácilmente la forma más eficiente de obtener datos en SQL Server.

Sin embargo, su desempeño reside en operaciones verdaderamente "masivas". Cientos o miles de filas no son necesariamente lo suficientemente altas como para justificar su uso. Decenas de miles a millones de filas fueron donde el rendimiento de SqlBulkCopy realmente brillará. Y, al final, todo de lo que realmente estamos hablando es de enviar datos al servidor .

Hay otros desafíos importantes para obtener un conjunto de filas en una tabla de base de datos de producción. La reindexación, el reordenamiento (si hay un índice agrupado), la validación de clave externa, todos estos tipos de cosas agregan tiempo a su inserción y son potencialmente bloqueo de tabla e índice.

Además, los datos de TVP se escriben en el disco (como datos de la tabla temporal) y luego se puede acceder a ellos para colocarlos en sus tablas. SqlBulkCopy es capaz de ir directamente a su mesa ... el rendimiento en ese caso es significativamente más rápido, sin embargo, uno debe equilibrar la velocidad para la concurrencia.

Creo que la regla general es que, si tiene que lidiar con un puñado de filas, piense en los TVP, y si tiene muchos miles de filas, considere enviarlo a SQL Server tan rápido como sea posible a través de SqlBulkCopy.


SqlBulkCopy usa un IDataReader cuando llama al método WriteToServer, por lo que debería poder implementar IDataReader en base a una colección que es IEnumerable. Esto le permitiría tomar un conjunto de entidades y llamar a SqlBulkCopy utilizando su implementación IDataReader.


Tendrá que convertir las entidades a un IDataReader o DataTable.

Hay una pequeña clase de ayuda diseñada para ayudar con: http://archive.msdn.microsoft.com/LinqEntityDataReader/Release/ProjectReleases.aspx?ReleaseId=389

EDIT: el enlace msdn está roto, la copia alternativa se puede encontrar aquí: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

Entonces puedes usar SqlBulkCopy así:

var sbCopy= new SqlBulkCopy(connectionString); sbCopy.DestinationTableName = "TableName"; sbCopy.WriteToServer(entitiesList.AsDataReader());