¿El subproceso DbContext es seguro?

Me preguntaba si la clase DbContext es segura para subprocesos, supongo que no, ya que actualmente estoy ejecutando subprocesos paralelos que acceden a DbContext en mi aplicación y DbContext una serie de excepciones de locking y otras cosas que parecen ser un hilo relacionado.

Hasta hace poco no recibía ningún error … pero hasta hace poco no estaba accediendo al DbContext en los hilos.

Si estoy en lo cierto, ¿qué sugieren las personas como una solución?

No es seguro para subprocesos Simplemente crea una nueva instancia de DbContext en tu hilo.

No, no es seguro para subprocesos: EF completo no es seguro para subprocesos porque el contexto EF nunca debe compartirse.

Editado: respuesta anterior a continuación.

Ahora siempre uso este patrón con DbContext:

 using(var db = new LogDbContext()) { // Perform work then get rid of the thing } 

Mi aproximación de uno por hilo de solicitud significaba que los objetos almacenados en caché en el DbContext se mantendrían obsoletos incluso mientras otras instancias de DbContext estaban escribiendo nuevos valores en la base de datos real detrás de él. Esto crearía algunos problemas extraños de, por ejemplo, una solicitud que realiza una inserción y la siguiente solicitud de la lista que entra en una secuencia diferente que tenía una lista caducada y obsoleta de los datos para esa consulta.

Hay enfoques que hacen que el siguiente trabajo funcione e incluso mejore el rendimiento de las aplicaciones de estilo de muchas lecturas / pocas escrituras, pero requieren más diseño y estrategia que el patrón mucho más simple anterior.

Actualizar

También uso un método de ayuda útil para los métodos de biblioteca, como las llamadas de registro. Aquí está el método de ayuda:

  public static async Task Using(Db db, Func action) { if (db == null) { using (db = new Db()) { await action(db); } } else { await action(db); } } 

Con esto, puedo escribir fácilmente código que toma un DbContext existente opcional, o crea una instancia dentro de un contexto de uso, dependiendo de cómo se llame.

Por ejemplo, mientras trabajo con un DbContext podría cargar algunos datos, registrar algo de información y luego guardar esos datos; lo mejor es hacerlo todo con el mismo DbContext desde una perspectiva de rendimiento. Por otro lado, también podría querer registrar algo en respuesta a una acción simple, y no cargar ni escribir ningún otro dato. Al aprovechar el método anterior, puedo tener solo un método de registro que funciona tanto si quiere trabajar dentro de un DbContext existente como si no:

 public async Task WriteLine(string line, Db _db = null) { await Db.Using(_db, db => { db.LogLines.Add(new LogLine(line)); await db.SaveChangesAsync(); }); } 

Ahora esta llamada a método se puede llamar dentro o fuera de un DbContext existente y aún así comportarse correctamente, en lugar de tener que tener 2 versiones de este y cualquier otro método de registro de conveniencia u otro método de utilidad que tenga, y en lugar de tener que saber y plan para el contexto de cada llamada que se les haga a ellos o a quienes llaman. Esto básicamente me devuelve uno de los beneficios de la estrategia de threadstatic a continuación, donde no tuve que preocuparme cuando exactamente el db se abrió en las llamadas a las utilidades que deberían estar preocupadas.

Respuesta anterior

Normalmente me ocupo de la seguridad de los hilos con EF DbContext así:

 public class LogDbContext : DbContext { . . . [ThreadStatic] protected static LogDbContext current; public static LogDbContext Current() { if (current == null) current = new LogDbContext(); return current; } . . . } 

Con esto en su lugar, puedo obtener un DbContext para este hilo así:

 var db = LogDbContext.Current(); 

Es importante notar que dado que cada DbContext mantiene su propio caché local, cada hilo ahora tendrá su propio caché separado de objetos de entidad, lo que puede introducir un comportamiento loco si no está preparado para ello. Sin embargo, la creación de nuevos objetos DbContext puede ser costosa, y este enfoque minimiza ese costo.