0

I'm trying to use Hangfire in an ASP.NET Core 5 web application. I'm using dependency injection to pass in various dependencies to a hangfire task that will run every minute. Unfortunately, when I attempt to execute a query using entity framework core, I receive the following error message:

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: 'AppDbContext'.'

Here is the task I want to run each minute with Hangfire:

public class ReportContentGenerator : IReportContentGenerator
{
    private readonly ILogger<ImageCopier> _logger;
    private readonly CosmosDbService _cosmosDbService;
    private readonly IBlobStorageService _blobStorageService;
    private readonly AppDbContext _dbContext;

    public ReportContentGenerator(ILogger<ImageCopier> logger, IBlobStorageService blobStorageService, CosmosDbService cosmosDbService, AppDbContext appDbContext)
    {
        _logger = logger;
        _blobStorageService = blobStorageService;
        _cosmosDbService = cosmosDbService;
        _dbContext = appDbContext;
        Console.WriteLine("Image copier instantiated...");
    }

    public async void TransposeImageAnalysisIntoReportContent()
    {
        // Query CosmosDB for all orders that have not yet had their images copyed from the staging storage into the processing storage. 
        var orders = await _cosmosDbService.GetItemsAsync("SELECT * FROM c WHERE c['status']['value'] = 'Processing' OR c['status']['value'] = 'Draft' ");

        var filaments = await  _dbContext.Filaments.ToListAsync();
        var recommendationsContent = await _dbContext.ReportContents
                                                .ToListAsync();
                                                
                                                
        // Ommitted for brevity
        
    }
}

Here is my COnfigureServices...

// Add Hangfire services.
services.AddHangfire(configuration => configuration
    .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
    .UseSimpleAssemblyNameTypeSerializer()
    .UseRecommendedSerializerSettings()
    .UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection"), new SqlServerStorageOptions
    {
        CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
        SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
        QueuePollInterval = TimeSpan.Zero,
        UseRecommendedIsolationLevel = true,
        DisableGlobalLocks = true
    }));
services.AddHangfireServer();

services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAd");
services.AddAuthentication()
   .AddJwtBearer("ApiAuth", options =>
   {
       options.Audience = Configuration["AzureAdApi:ResourceId"];
       options.Authority = $"{Configuration["AzureAdApi:Instance"]}{Configuration["AzureAdApi:TenantId"]}";
   });

services.AddSingleton(InitializeCosmosClientInstanceAsync(Configuration.GetSection("CosmosDb")).GetAwaiter().GetResult());
services.Configure<BlobStorageOptions>(Configuration.GetSection("BlobStorageOptions"));
services.AddSingleton<IBlobStorageService, BlobStorageService>();
services.AddSingleton<IImageCopier, ImageCopier>();
services.AddScoped<IReportContentGenerator, ReportContentGenerator>();

Here is where I instantiate my Hangfire tasks in Startup Configure:

 public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJobs, IWebHostEnvironment env)
 {
     //Ommitted for brevity...
     RecurringJob.AddOrUpdate<IImageCopier>(x => x.CopyImages(), Cron.Minutely);
     RecurringJob.AddOrUpdate<IReportContentGenerator>(x => x.TransposeImageAnalysisIntoReportContent(), Cron.Minutely);
      //Ommitted for brevity...
  }
pedrommuller
  • 15,741
  • 10
  • 76
  • 126
tnk479
  • 672
  • 11
  • 26

2 Answers2

0

you have to configure database connection for hangfire

Hangfire Configration for .NET Core

Ammar H Alshaar
  • 303
  • 3
  • 4
  • I'm sorry. I forgot to include that code. I do in fact have the sql sink configured properly. – tnk479 Apr 01 '21 at 17:42
0

For anyone else who hits this, the fix is to replace the void return type in my tasks with the Task return type:

public async Task TransposeImageAnalysisIntoReportContent() {
     ...
}
tnk479
  • 672
  • 11
  • 26