Search code examples
asp.net-mvchangfire

Hangfire in asp.net core webapi problem with DI


When I execute background job, and I try to resolve all dependencies, I get the exception:

Microsoft.EntityFrameworkCore.Query[10100]

An exception occurred while iterating over the results of a query for context type 'MyProj.DAL.ApplicationContext'.

System.ObjectDisposedException: 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.

Object name: 'ApplicationContext'

at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()

My code - in ConfigureServices(IServiceCollection services):

services.AddHangfire(cfg => cfg
     .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
     .UseSimpleAssemblyNameTypeSerializer()
     .UseRecommendedSerializerSettings()
     .UseMemoryStorage());
        
services.AddHangfireServer();

in Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider provider):

GlobalConfiguration.Configuration.UseActivator(new ContainerJobActivator(provider));

app.UseHangfireDashboard()

and

public class ContainerJobActivator : JobActivator
{
    private IServiceProvider _container;

    public ContainerJobActivator(IServiceProvider container)
    {
        _container = container;
    }

    public override object ActivateJob(Type type)
    {
        return _container.GetService(type);
    }
}

My DBContext

services.AddEntityFrameworkNpgsql().
            AddDbContext<ApplicationContext>(opt =>
            opt.UseNpgsql("server=localhost;port=5432;database=database;uid=root;password=password;"));

Solution

  • We need resolve IServiceScopeFactory in our job, than get our service

    using (var scope = _factoryScope.CreateScope())
    {
          _articleRepository = scope.ServiceProvider.GetService<IArticleRepository>() ?? throw new ArgumentNullException();
    
         // your job here.....
    
     }