c# asp.net .net asp.net-core .net-core

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).