2012-04-11 20 views
42

Al usar DbContext en un escenario de base de datos descubrí que agregar y eliminar entidades es muy lento en comparación con ObjectContext. Si agrega 2000 entidades y guarda los cambios al final, DbContext es de 3 a 5 veces más lento que ObjectContext (por cierto: sé que sería mejor agregar una gran cantidad de entidades usando SqlBulkCopy, pero ese no es el punto). Si el ahorro cambia después de cada adición, DbContext es casi dos veces más lento. Cuando se trata de eliminación, incluso empeora: al guardar al final de todas las eliminaciones de entidades, DbContext es alrededor de 18 veces más lento que ObjectContext.DbContext es muy lento al agregar y eliminar

Tomé mi aplicación de prueba altamente desarrollada que uso para comparar las tecnologías de acceso a la base de datos y una pequeña aplicación de consola para verificarla. Ambos mostraron malos resultados para agregar y eliminar entidades usando DbContext. Estos son los resultados de la aplicación de consola:

Inserting 2000 entities via DbContext saving changes at the end: 2164ms 
Inserting 2000 entities via ObjectContext saving changes at the end: 457ms 
Inserting 2000 entities via DbContext saving changes after each object addition: 8420ms 
Inserting 2000 entities via ObjectContext saving changes after each object adding: 4857ms 
Inserting 2000 entities via DbContext using a new DbContext for each object addition: 4018ms 
Deleting 2000 entities via DbContext saving changes at the end: 4794ms 
Deleting 2000 entities via ObjectContext saving changes at the end: 261ms 
Deleting 2000 entities via DbContext saving changes after each object deletion: 25536ms 
Deleting 2000 entities via ObjectContext saving changes after each object deletion: 2110ms 

He intentado utilizar EF 4,3 en 2010 y VC EF 5.0 Beta 2 en VS 11 con casi los mismos resultados. Utilicé las plantillas T4 proporcionadas por el "EF 4.x POCO Entity Generator for C#", el "EF 4.x DbContext Generator for C#" y el "EF 5.x DbContext Generator for C#".

¿Qué podría estar mal? De acuerdo con los resultados de las pruebas, nunca usaría DbContext en una aplicación que tenga que agregar o eliminar entidades (lo que hace que DbContext me resulte desafortunadamente inutilizable).

puse las aplicaciones de prueba de la consola en mi servidor web: EF 4.3 DbContext Test, EF 5.0 DbContext Test

/correcciones son apreciados Cualquier idea.

+0

Dos referencias además de Ladislavs respuesta: http://stackoverflow.com/questions/5943394/why-is-inserting-entities-in-ef-4-1-so-slow-compared-to-objectcontext/5943699 # 5943699 y http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework/5942176#5942176 – Slauma

Respuesta

86

tratar de añadir esto a sus pruebas DbContext:

dbContext.Configuration.AutoDetectChangesEnabled = false; 

// Now do all your changes 

dbContext.ChangeTracker.DetectChanges(); 
dbContext.SaveChanges(); 

y tratar de ejecutar las pruebas de nuevo.

Hubo algunos cambios arquitectónicos en DbContext API que verifica los cambios en las entidades cada vez que Add, Attach o Delete cualquier cosa del contexto. En ObjectContext API, esta detección solo se ejecuta cuando activó SaveChanges. Es la mejor solución para la mayoría de los escenarios comunes, pero requiere un manejo especial para el procesamiento masivo de datos.

+1

Gracias Ladislav. Esa fue la causa del problema de rendimiento al agregar/eliminar muchas entidades y guardar los cambios al final. Después de establecer AutoDetectChangesEnabled en falso, el resultado fue casi el mismo que con ObjectContext.Pero aún así el único inserto y especialmente la eliminación única seguida de un SaveChanges es más lento en comparación con ObjectContext, incluso si configuro AutoDetectChangesEnabled en false e invoco DetectChanges antes de SaveChanges. La eliminación de 2000 entidades aún tomó alrededor de 17 segundos al usar DbContext mientras que –

+0

... tomó solo alrededor de 2,1 segundos cuando se usa un ObjectContext. Supongo que es solo por estos cambios en el seguimiento de cambios. Por cierto: ¿podría explicar por qué la comprobación de cambios cada vez que se agregan, adjuntan o eliminan es una mejor solución para la mayoría de los escenarios comunes? –

+3

@ JürgenBayer: He reproducido la gran diferencia de rendimiento para 'DeleteObject/Remove' que describió en su comentario. La diferencia desaparece si elimina 'DetectChanges' del código (que en realidad no es necesario si solo agrega y elimina entidades). Pero, sin embargo, tengo entendido que 'ObjectContext.SaveChanges()' llama a 'DetectChanges' internamente, mientras que 'DbContext.SaveChanges()' no aparece cuando 'AutoDetectChanges' está deshabilitado. Entonces, llamar 'DetectChanges' +' DbContext.SaveChanges() '(con AutoDetectChanges desactivado) debería ser lo mismo que llamar' ObjectContext.SaveChanges() '- en teoría. – Slauma

11

En EF6 ahora puede usar AddRange y RemoveRange en DbSet.

De la documentación en los enlaces:

Tenga en cuenta que si AutoDetectChangesEnabled se establece en true (que es el valor predeterminado), entonces DetectChanges se llamará una vez antes {añadiendo, eliminando} cualesquiera entidades y no ser llamado de nuevo. Esto significa que, en algunas situaciones, {Agregar, Eliminar} Rango puede funcionar mucho mejor que llamar {Agregar, Eliminar} varias veces lo haría.