2010-03-31 36 views
14

Mi proyecto actual consiste en 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 tendrá que copiar todos los datos dentro 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 están usando DataTables para mover datos hacia adelante y hacia atrás.SqlBulkCopy y Entity Framework

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

Respuesta

1

Puede considerar que un conjunto de datos es una serialización de la entidad de datos. Sin embargo, en términos generales, creo que SqlBulkCopy es una cosa de tabla a tabla, de ahí la razón para las tablas de datos.

1

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

19

Deberá convertir las entidades a IDataReader o DataTable.

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

EDIT: enlace de MSDN está roto, copia alt se puede encontrar aquí: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

continuación, puede utilizar SqlBulkCopy de este modo:

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

se rompe el vínculo –

+2

@JonBarker - Aquí está el enlace de GitHub: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs – DaveHogan

+0

@DaveHogan Me gusta la idea que tiene aquí. Estamos sembrando más de 200 mil productos y es doloroso por decir lo menos. Intenté incluirlo en nuestro repositorio EF de repositorio, pero al crear un elemento de Office que tiene un objeto secundario de direccionamiento, no crearía los elementos hijo o relación. ¿Es posible este tipo de cosas o está más allá del alcance del código vinculado? Gracias – Jon

5

Hemos probado y probado un par de aproximaciones al insertar mayor uso de EF y, finalmente, fuimos con los parámetros con valores de tabla para conseguir º El mejor rendimiento en un rango de tamaños de fila. No tengo los números a mano, pero sé que este Performance of bcp/BULK INSERT vs. Table-Valued Parameters fue un factor guía.

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

Los parámetros con valores de tabla requieren un procedimiento almacenado y un tipo de tabla definido en la base de datos. Si usa código primero, puede ejecutar SQL para crearlos como parte de su script de creación. Si bien esto es más trabajo, descubrimos 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 no insertar a granel en su mesa principal. Usamos una tabla de almacenamiento dinámico temporal y agregamos un índice agrupado una vez que se importan los datos. Luego realizamos un MERGE entre la tabla de temperatura y la tabla principal. Esto tiene el beneficio 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 con este método.

Quiero saber si quieres más información.

0

SqlBulkCopy es una transferencia directa, casi en forma de matriz de bytes, de datos de fila del cliente al servidor SQL. Es la manera más fácil de obtener datos en SQL Server.

Sin embargo, su rendimiento se basa en operaciones verdaderamente "a granel". Cientos o miles de filas no son necesariamente lo suficientemente altas como para justificar el uso.Decenas de miles a millones de filas son el rendimiento de SqlBulkCopy realmente brillará. Y, al final, de lo que realmente estamos hablando es de obtener los datos en el servidor.

Existen otros desafíos importantes para obtener un conjunto de filas en la tabla de una base de datos de producción. Reindexar, reordenar (si hay un índice agrupado), validación de la clave externa, todo este tipo de cosas le agrega tiempo a su inserción y es potencialmente un bloqueo de tabla e índice.

Además, los datos de TVP se escriben en el disco (como datos de tablas temporales), y luego se puede acceder a ellos para ponerlos 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 obtener SQL Server tan pronto como sea posible a través de SqlBulkCopy.

-2

Como complemento a la respuesta @DaveHogan,

Ahora hay nuevas bibliotecas que permiten la realización de Inserción masiva (usando SqlBulkCopy bajo el capó) para Entity Framework utilizando las entidades de datos en lugar de DataTable.

Negación: yo soy el dueño del proyecto Entity Framework Extensions

Esta biblioteca no es libre, sino que permite realizar fácilmente:

  • BulkSaveChanges
  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

Debajo del capó, se usa SqlBulkCopy. Usar el método de extensión make es mucho más fácil/rápido que codificar una solución personalizada para cada Bulk Insert a usar.

Ejemplo

// Easy to use 
context.BulkSaveChanges(); 

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

bajo rendimiento

Siento que está recibiendo malos resultados,

Asegúrese de que no está incluido el tiempo de algún error común como olvidar JIT Compile, usando Add en lugar de AddRange, lo que afecta el rendimiento de la prueba pero no está relacionado con nuestra biblioteca.

La mayoría de las personas informan obtener una mejora del rendimiento de entre 25 y 50 cuando se excluyen todos los errores de referencia de rendimiento comunes.

Ver: Entity Framework Extensions - Benchmark

+0

bajo rendimiento –

+0

Hola @Ashraf, por favor, háganos saber por qué Dices mal desempeño. Normalmente es causada por un error común que no está relacionado con nuestra biblioteca, como usar Add over AddRange –

+1

Lo siento, mi error. Necesitamos deshabilitar la caché de rastreo. –

1

Es posible utilizar Bulk package biblioteca. La versión Bulk Insert 1.0.0 se utiliza en proyectos que tienen Entity framework> = 6.0.0.Más descripción se puede encontrar por debajo de enlace- Bulkoperation source code