1

I have a class Issue which contains some information including their dates. I would like to create a background service that deletes data older than 7 days from the the database.

Here is the code I have tried:

using APIExample;
using Microsoft.Identity.Client;

public class BackgroundWorker : BackgroundService
{
    private readonly AppDbContext _appDbContext;

    public BackgroundWorker(AppDbContext appDbContext)
    {
        _appDbContext = appDbContext;
    }

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _appDbContext.Issue.RemoveRange(_appDbContext.Issue.Where(a => (a.Created.AddDays(7) >= DateTime.Now)));
        _appDbContext.SaveChanges();
        return Task.CompletedTask;
    }
}

I have injected this in the program.cs class

builder.Services.AddHostedService<BackgroundWorker>();

This is the error I am getting:

System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: BackgroundWorker': Cannot consume scoped service 'APIExample.AppDbContext' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.)'

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 2
    Looks like you adding your classes to DI with inappropriate scopes, just like the error message says. I.e. you are using `AddScoped` and `AddSingleton` and should have the same scope for the classes that the error message says. – Uwe Keim Jan 16 '23 at 09:22
  • There's an overload that takes a factory function to provide your background service. Perhaps you can leverage that. https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicecollectionhostedserviceextensions.addhostedservice?view=dotnet-plat-ext-7.0#microsoft-extensions-dependencyinjection-servicecollectionhostedserviceextensions-addhostedservice-1(microsoft-extensions-dependencyinjection-iservicecollection-system-func((system-iserviceprovider-0))) – Aluan Haddad Jan 16 '23 at 09:29
  • This will not work. The service will run only once when it started then it will be shut down. If you expect to run the service every 7 days you need to add a loop in the execution method: https://stackoverflow.com/questions/75067441/while-true-or-while-true-with-thread-sleep-in-a-background-service/75067493#75067493 – Radu Hatos Jan 16 '23 at 09:31
  • Thank you all. Your comments were useful. . – Jacob Modiba Jan 16 '23 at 11:45

1 Answers1

1

You can not inject DbContext like this way, use ServiceScopeFactory

        public class BackgroundWorker : BackgroundService
        {
          private readonly IServiceScopeFactory _serviceScopeFactory;
    
        
            public BackgroundWorker(IServiceScopeFactory serviceScopeFactory)
            {
                _serviceScopeFactory = serviceScopeFactory;
            }
        
            protected override Task ExecuteAsync(CancellationToken stoppingToken)
            {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                 var _appDbContext= scope.ServiceProvider.GetService<AppDbContext>();
                _appDbContext.Issue.RemoveRange(_appDbContext.Issue.Where(a => (a.Created.AddDays(7) >= DateTime.Now)));
                _appDbContext.SaveChanges();
                return Task.CompletedTask;
            }
        }
    }
Soheil
  • 190
  • 1
  • 1
  • 14