Entity Framework Thread Safety

Los objetos de contexto generados por Entity Framework no son seguros para subprocesos.

¿Qué SaveChanges() si utilizo dos contextos de entidad separados, uno para cada hilo (y llamo SaveChanges() en cada uno)? ¿Esto estará seguro para subprocesos?

 // this method is called from several threads concurrently public void IncrementProperty() { var context = new MyEntities(); context.SomeObject.SomeIntProperty++; context.SaveChanges(); } 

Creo que el contexto del marco de entidad implementa algún tipo de variable “contador” que realiza un seguimiento de si los valores actuales en el contexto son nuevos o no.

  1. Con el código anterior, llamado desde hilos separados, ¿todavía tengo que bloquear el incremento / guardar cambios?
  2. Si es así, ¿cuál es la forma preferida de lograr esto en este escenario simple?

Más de un hilo que opera en un único contexto de Entity Framework no es seguro para subprocesos.

Una instancia separada de contexto para cada hilo es thread-safe. Mientras que cada hilo de ejecución tenga su propia instancia de contexto EF, estarás bien.

En su ejemplo, puede llamar a ese código desde cualquier cantidad de hilos al mismo tiempo y cada uno estará felizmente trabajando con su propio contexto.

Sin embargo, sugeriría implementar un bloque ‘usar’ para esto de la siguiente manera:

 // this method is called from several threads concurrently public void IncrementProperty() { using (var context = new MyEntities()) { context.SomeObject.SomeIntProperty++; context.SaveChanges(); } } 

Creo que “SomeObject.SomeIntProperty” es estático. Esto no tiene nada que ver con que la Entidad sea enhebrable. Si está escribiendo en variables estáticas en un entorno multiproceso, siempre debe envolverlos con un doble locking de verificación para garantizar la seguridad del hilo.

Puede utilizar el enfoque de fábrica para inyectar su DbContext como una fábrica en lugar de una instancia en sí misma, eche un vistazo a esto: https://github.com/vany0114/EF.DbContextFactory

Es más seguro y evita codificar la creación de la instancia en sus repositorys.

http://elvanydev.com/EF-DbContextFactory/

Hay una extensión para Ninject para hacer eso de una manera muy sencilla, simplemente llamando al método kernel.AddDbContextFactory(); también necesita cambiar su repository recibiendo un Func