versiones ventajas usar porque framework first example ejemplo desventajas code performance entity-framework entity-framework-4.1 poco

performance - ventajas - entity framework versiones



¿Por qué DbSet.Add funciona tan lento? (1)

El mismo tema se trató aquí hace 8 meses: ¿Cómo puedo acelerar DbSet.Add ()? . No se propuso otra solución que utilizar SqlBulkCopy que no es aceptable para nosotros. Decidí volver a mencionarlo con la esperanza de que haya nuevos pensamientos e ideas sobre este tema y se propongan otras soluciones. Al menos solo tengo curiosidad de por qué esta operación tarda tanto tiempo en ejecutarse.

Bueno, el problema es: tengo que actualizar las entidades 30K en la base de datos (EF 4.1, POCO). El tipo de entidad es bastante simple y contiene Id entero + otras 4 propiedades enteras sin relaciones con otros tipos. 2 casos:

  • Todos ellos son nuevos registros. Ejecutar context.Entities.Add (entidad) una por una para cada entidad lleva 90 segundos con Cntx.Configuration.AutoDetectChangesEnabled = false (el valor verdadero hace que se ejecute para siempre). Entonces SaveChanges toma solo un segundo. Otro enfoque: adjuntarlo al contexto como este toma los mismos 90 segundos:

    Cntx.Entities.Attach(entity); Cntx.Entry(entity).State = EntityState.Added;

  • Todos ellos son registros existentes con algunos cambios. En el caso, solo toma unos pocos milisegundos para adjuntarlo al contexto de datos existente como este:

    Cntx.Entities.Attach(entity); Cntx.Entry(entity).State = EntityState.Modified;

    ¿Ver la diferencia?

¿Qué hay detrás del escenario del método Add que hace que funcione tan increíblemente lento?


Tengo resultados interesantes de pruebas de rendimiento y he encontrado un culpable. No he visto ninguna información como esta en ninguna fuente de EF que haya leído.

Resulta ser Igual anulado en una clase base. La clase base se supone que contiene la propiedad Id compartida entre todos los tipos de entidades concretas. Este enfoque recomendado por muchos libros de EF y bastante bien conocido. Puede encontrarlo aquí, por ejemplo: ¿Cómo implementar mejor Equals para tipos personalizados?

Más exactamente, el rendimiento se mata con la operación de desempaquetado (objeto de conversión de tipo concreto) que lo hizo funcionar tan lento. Como comenté en esta línea de código, ¡tardó 3 segundos en ejecutarse oponiéndose a 90 segundos antes!

public override bool Equals ( object obj ) { // This line of code made the code so slow var entityBase = obj as EntityBase; ... }

Cuando lo encontré comencé a pensar en lo que podría ser una alternativa a estos iguales. La primera idea fue implementar IEquatable para EntityBase, pero no se ejecutó en absoluto. Entonces, lo que finalmente decidí hacer es implementar IEquatable para cada clase de entidad concreta en mi modelo. Tengo solo algunos de ellos, así que es una actualización menor para mí. Puede poner toda la funcionalidad de operación Equal (generalmente es 2 objetos Ids de comparación) en el método de extensión para compartir entre clases concretas de entidades y ejecutarlo de esta manera: Equal ((EntityBase) ConcreteEntityClass). Lo más interesante, este IEquatable acelera EntitySet. ¡Agregue 6 veces!

Así que no tengo más problemas con el rendimiento, el mismo código se ejecuta para mí con menos de un segundo. ¡Obtuve 180 veces más rendimiento ! ¡Asombroso!

Conclusión :

  1. la manera más rápida de ejecutar EntitySet.Add es tener IEquatable para la entidad específica (0.5 seg)
  2. Falta IEquatable hace que se ejecute 3 seg.
  3. Tener iguales (objeto obj) que la mayoría de las fuentes recomiendan hace que se ejecute 90 segundos