c# - ¿Cómo debo inyectar una instancia de DbContext en un IHostedService?
asp.net .net (1)
Una buena manera de usar los servicios dentro de los servicios alojados es crear un alcance cuando sea necesario. Esto permite utilizar servicios / contextos db, etc. con la configuración de por vida con la que están configurados. En teoría, no crear un alcance podría conducir a la creación de DbContexts únicos y a la reutilización de contexto inadecuada (EF Core 2.0 con grupos de DbContext).
Para hacer esto, inyecte un
IServiceScopeFactory
y
IServiceScopeFactory
para crear un ámbito cuando sea necesario.
Luego resuelva cualquier dependencia que necesite de este ámbito.
Esto también le permite registrar servicios personalizados como dependencias con ámbito en caso de que desee mover la lógica del servicio alojado y usar el servicio alojado solo para desencadenar algún trabajo (por ejemplo, desencadenar una tarea regularmente; esto crearía ámbitos de forma regular, crearía el servicio de tareas en este alcance que también recibe un contexto db inyectado).
public class MyHostedService : IHostedService
{
private readonly IServiceScopeFactory scopeFactory;
public MyHostedService(IServiceScopeFactory scopeFactory)
{
this.scopeFactory = scopeFactory;
}
public void DoWork()
{
using (var scope = scopeFactory.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();
…
}
}
…
}
Pregunta
¿Cómo debo inyectar (usando la inyección de dependencia estándar) una instancia de
DbContext
en un
IHostedService
?
Que he probado
Actualmente tengo mi clase
IHostedService
toma una
MainContext
(derivada de
DbContext
) en el constructor.
Cuando ejecuto la aplicación obtengo:
No se puede consumir el servicio de ámbito ''Microsoft.EntityFrameworkCore.DbContextOptions'' del singleton ''Microsoft.Extensions.Hosting.IHostedService''.
Así que traté de hacer que las
DbContextOptions
transitorias especificando:
services.AddDbContext<MainContext>(options =>
options.UseSqlite("Data Source=development.db"), ServiceLifetime.Transient);
en mi clase de
Startup
.
Pero el error sigue siendo el mismo, aunque, de acuerdo con
este problema resuelto de Github,
las
DbContextOptions
pasadas deben tener la misma vida útil especificada en la llamada
AddDbContext
.
No puedo hacer que el contexto de la base de datos sea un singleton; de lo contrario, las llamadas simultáneas generarían excepciones de concurrencia (debido al hecho de que no se garantiza que el contexto de la base de datos sea seguro para subprocesos).