I am new to .NET Core and writing an app which requires several background services to run on startup. I used Hangfire for this purpose but faced another issue: while DbContext
is required, I get this error:
Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances
I have defined all services as scoped. However since I required Hangfire to do the job for me had to write below code on startup.
using (var serviceScope = app.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
var jobService = services.GetRequiredService<ISystemStartupJobs>();
BackgroundJob.Enqueue(() => jobService.Run1()); //Run only once on startup (FIRE & FORGET )
RecurringJob.AddOrUpdate("Receive Email Messages", () => jobService.Run2(), "*/10 * * * * *"); //every 10 seconds
}
SystemStartupJobs
has 2 jobs and depends on different repositories all have DbContext
injected and defined as scoped service again.
Exception error appears when DbContext
tries to make first contact with the database.
Appreciate your help.
This is likely because context you are using is disposed, as the exception says. This is likely caused by DB context being scoped service, which means that DB context is disposed at the end of every HTTP request.
To remedy that, you can inject to your services IServiceProvider
and with that:
using var scope = _serviceProvider.CreateScope();
var repostiory = scope.GetRequiredService<MyRepository>();
Something like that:
public class SystemStartupJobs : ISystemStartupJobs
{
private readonly IServiceProvider _serviceProvider
public SystemStartupJobs(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task Method()
{
// ... somewhere in the code
using var scope = _serviceProvider.CreateScope();
var repo = scope.GetRequiredService<MyRepo>();
}
}