DbContext instance used in two places concurrently - EF - Hangfire

Viewed 654

I'm using EF Core and Hangfire to run a recurring job. Hangfire seems to be causing the following error:

A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext. For more information on how to avoid threading issues with DbContext

And.. I'm not sure why. I register the EF context as follows:

services 
    .AddDbContext<PaymentContext>(options => options.UseNpgsql(connectionString),
    ServiceLifetime.Transient); 

And then..

app.UseHangfireDashboard();
app.UseHangfireServer();
   
RecurringJob.AddOrUpdate(() => myService.ExecuteMyJob(), Cron.Minutely);

Where myService has been injected into the Startup.Configure function, and myService contains the reference to the DbContext. Which is transient in theory, and so shouldn't be shared by the service and other places.

However the stacktrace leads here:

var plans = _context.Plan
                .Include(pp => pp.PlanItem)
                .Where(pp => pp.PolicyId == policyId)
                .ToList() // materialise query
                .OrderBy(pp => pp.PlanItem.First().Date)
                .ToList();
1 Answers

You should create scope for your dependency.

public class Job
{
    private readonly IServiceProvider _serviceProvider;
    
    public Job(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public void ExecuteJob()
    {
        using (var scope = serviceProvider.CreateScope())
        {
            var databaseContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
            // do something
        }
    }
}
Related