Search code examples
.net-coreentity-framework-coreblazor-server-side

Error : cannot access a disposed context instance


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.


Solution

  • 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>();
        }
    }