query framework entity-framework ef-code-first query-performance

entity-framework - query - entity framework performance



¿Obtener entidades con AsNoTracking() deshabilita la llamada automática a DetectChanges()? (2)

¿También causará la desactivación de la llamada automática a DetectChanges ()

No, no lo hará. Pero debe darse cuenta de que AsNoTracking y DetectChanges no tienen nada que ver entre sí (aparte de ser parte de EF). Los objetos recuperados con AsNoTracking nunca se detectarán cambios de todas formas, ya sea que AutoDetectChanges esté habilitado o no. Además, AsNoTracking funciona en un nivel DbSet , AutoDetectChangesEnabled en el nivel de contexto. Sería malo que un método DbSet afecte a todo el contexto.

o que [establecer AutoDetectChangesEnabled ] tiene que hacerse explícitamente

Bueno, probablemente no deberías deshabilitar AutoDetectChanges. Si lo haces debes saber lo que haces.

qué impacto (en términos de rendimiento) tiene si ambas acciones se llevan a cabo

Como se ha dicho, no están relacionados. Ambos pueden mejorar el rendimiento a su manera.

  • AsNoTracking es excelente si desea obtener datos de solo lectura. No tiene efectos secundarios (como en: su efecto es claro)
  • La configuración de AutoDetectChangesEnabled = false detiene las llamadas automáticas de DetectChanges (que pueden ser numerosas), pero tiene efectos secundarios que debe tener en cuenta. Del libro DbContext de Lerman & Miller:

    Hacer ejercicio cuando se debe llamar a DetectChanges no es tan trivial como pueda parecer. El equipo de Entity Framework recomienda encarecidamente que solo cambie a llamar manualmente a DetectChanges si tiene problemas de rendimiento. También se recomienda optar por no activar DetectChanges automáticamente para las secciones de código de bajo rendimiento y volver a habilitarlo una vez que la sección en cuestión haya terminado de ejecutarse.

Llegué a conocer este concepto de AsNoTracking() , DetectChanges() y AutoDetectChangesEnabled recientemente. Entiendo que al recuperar registros de la base de datos a través de Entity Framework con AsNoTracking() , Entity Framework no realiza un seguimiento de los cambios en esos registros y la actualización de cualquier propiedad del registro recuperado fallará en ese caso.

Mi pregunta es si los registros se recuperan de esa manera, ¿también causará la desactivación de la llamada automática a DetectChanges () o tiene que hacerse explícitamente estableciendo:

Context.Configuration.AutoDetectChangesEnabled = false;

También amablemente, hágame saber qué impacto (en términos de rendimiento) tiene si ambas acciones se llevan a cabo mientras se obtienen los datos estrictamente con fines de solo lectura:

Context.Configuration.AutoDetectChangesEnabled = false; Context.Set<T>().AsNoTracking();


Hemos encontrado que establecer AutoDetectChangesEnabled = false puede tener impactos sustanciales (es decir, un factor de 10).

Antecedentes : nuestro sistema está compuesto completamente de objetos del modelo EF que utilizan proxies de detección de cambios. Es decir, todos nuestros campos de base de datos y propiedades relacionales se declaran como virtuales. También tenemos un modelo de objeto relativamente profundo. Es decir, el objeto A contiene un conjunto de objetos B, que a su vez contiene un conjunto de Objetos C, etc. Hemos observado que crear una instancia de un número no trivial (> 100) de estos objetos a través de una consulta EF / LINQ es costoso. Por ejemplo, en un caso, la creación de una instancia de 250 objetos requirió aproximadamente 2 segundos. También observamos que crear instancias de la misma estructura, pero usar objetos anónimos en lugar de unos 25 ms. Por último, observamos que si establecemos AutoDetectChangesEnabled = false , podríamos usar la consulta para crear una instancia de los objetos del modelo EF y la materialización nuevamente fue de aproximadamente 25 ms.

Por lo tanto, al menos para nosotros, se lograron enormes ganancias al establecerlo como falso. Utilizamos un patrón de Unidad de trabajo e indicamos explícitamente si la Unidad de trabajo es de solo lectura o no. Para una unidad de trabajo de solo lectura, establecer AutoDetectChangesEnabled = false es perfectamente seguro, ya que nunca habrá ningún cambio. De hecho, agregamos este cambio a nuestro sistema dos años después de nuestra versión inicial (por lo que había muchas, muchas unidades de trabajo preexistentes en el código) y el cambio no rompió nada en absoluto, y mejoró significativamente el rendimiento.

También experimentamos con AsNoTracking() y descubrimos que prácticamente no nos proporcionó ningún aumento de rendimiento. Como lo entiendo, una consulta con AsNoTracking() significa que los objetos no se colocarán en el mapa de identidad, y esto obligará a EF a recuperar el objeto del disco si se hace referencia más de una vez dentro del contexto (por ejemplo, en diferentes consultas). Por lo tanto, hay algunos inconvenientes potenciales de AsNoTracking() .

Detalles de implementación :

  • Tenemos una subclase de DBContext que proporciona gran parte de la infraestructura para nuestra unidad de trabajo
  • Nuestra unidad de trabajo es básicamente una envoltura liviana alrededor del contexto.
  • Cuando se asigna una unidad de trabajo (normalmente en un bloque de uso ) recibe uno de estos contextos mediante inyección (usamos Castle / Windsor)
  • Durante la inicialización, la unidad de trabajo llama a un método en el contexto en el que establece AutoDetectChangesEnabled en falso
  • Actualmente, hacemos esto todo el tiempo porque siempre usamos proxies de detección de cambios y no requieren AutoDetectChangesEnabled
  • Anteriormente, solo lo hacíamos para unidades de trabajo de ''solo lectura'', ya que si no se modifica nada en una UOW no hay necesidad de detectar cambios (cuando asignamos una unidad de trabajo indicamos explícitamente si es de solo lectura o no)
  • -