Tener más de un contexto de entidad

asp.net-core asp.net-core-mvc entity-framework-core

Pregunta

Digamos que he ampliado el marco de identidad dbContext para crear el mío propio, y tengo nuestro controlador autenticado que se inyecta con dbContext y busca una entidad relacionada con el ApplicationUser actual. El marco de la entidad relacionará las dos entidades que conducen a un error del servidor porque de referencias circulares.

No queremos serializar referencias circulares.

Así que creamos un nuevo dbContext en el método que distingue un nuevo dbcontext y consulta las entidades no relacionadas, esto funcionará. Pero esto no es comprobable , no queremos que nuestro controlador dependa estrictamente del dbContext , queremos que sea inyectado.

Así que agregamos un segundo parámetro, en el constructor, desafortunadamente esto hará que el sistema inyecte el mismo dbContext dos veces , no tan útil.

Intentamos crear una clase fakeDbContext que heredó de dbContext y agregarle servicios y usarla, pero ahora tenemos dos dbcontext , que potencialmente pueden generar migraciones, configuraciones y errores ...

¿Cuál es la forma correcta de hacer esto en el nuevo MVC6?

Editar...

Descubrí que si mi controlador requiere un IEnumerable<dbContext> obtengo todo el objeto registrado como servicio de ese tipo, por lo que solo dbContext duplicando la parte en startup.cs donde agregamos el dbContext en el área de registro del servicio y obtengo dos de ellos. ..

El inconveniente aquí es que no sé cuál es el virgen , parece que va en orden de registro, pero no tengo idea, si esto va a cambiar.

Editar 2 ...

He creado una clase TransientDbService que solo tiene un método de fábrica tomando el IserviceProvider , la usa para obtener las opciones para construir el dbContext y luego exponerlo. Lo he registrado como transitorio, luego en el controlador necesito este tipo de servicio.

El inconveniente aquí es que si alguna vez necesitaré un tercer dbContext debería escribir más código, más código significa errores y mantenerlo.

Edición 3 ...

No tener dos dbContext en absoluto. La siguiente configuración me permite no tener relaciones valorizadas.

Database.ChangeTracker.QueryTrackingBehavior = Microsoft.Data.Entity.QueryTrackingBehavior.NoTracking;

El inconveniente aquí es que no puedo usar mi modelo de gráfico, haciendo que todo sea más complejo ...

Editar 4 ...

https://github.com/aspnet/DependencyInjection/issues/352

Respuesta aceptada

Tiene razón al pensar que ninguna consulta de seguimiento ayudará en algunos casos, pero otras veces tendrá que crear más de una instancia del DbContext.

Normalmente, utiliza el AddDbContext<TContext>() en el inicio para asegurarse de que se crea una instancia de su tipo de contexto por solicitud y de que se DbContextOptions las DbContextOptions y el proveedor de servicios adecuados. Cuando necesita desviarse de este patrón, tiene algunas opciones, por ejemplo:

  1. Incluya un constructor en su clase DbContext derivada que tome un IServiceProvider y lo pase al constructor base. Asegúrese de que su controlador tome IServiceProvider . Una vez hecho esto, deberías poder crear DbContext manualmente con algo como esto:

    using(var context1 = new MyDbContext(serviceProvider), var context2 = new MyDbContext(serviceProvider)) { ...

  2. Para evitar tener que cambiar las firmas de constructor en su tipo derivado DbContext , puede aprovechar la clase DbContextActivator (es nuestro espacio de nombres interno), por ejemplo:

    using(var context1 = DbContextActivator.CreateInstance<MyDbContext>(serviceProvider), var context2 = DbContextActivator.CreateInstance<MyDbContext>(serviceProvider) {...

Nota: Si aún está utilizando AddDbContext<MyDbContext>(options => ...) en el inicio, debería extraer esas opciones automáticamente del proveedor de servicios. Pero también puede elegir incluir DbContextOptions como un parámetro en el constructor o anular el método OnConfiguring() para eso.

Le estoy dando ejemplos que crean dos DbContexts separados en un bloque de uso, pero también debería poder mezclarlos con el DbContext regular "por solicitud" que se inyectaría en el constructor del controlador.

Además de estas opciones disponibles actualmente, he creado un nuevo problema para rastrear otras posibles mejoras sobre cómo crear múltiples instancias del mismo tipo DbContext en la misma solicitud:

https://github.com/aspnet/EntityFramework/issues/4441




Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué