0

I'm creating an ASP.NET Core application. It is using Entity Framework Core for database access. I'm using services.AddDbContext in Startup.cs and the DB Context is injected into my controller as expected.

I am also have a background task using IHostedService that is added as a Singleton. I'd like to have an instance of my DBContext in my implementation of IHostedService. When I try to do this I get a run time error that my IHostedService cannot consume a scoped service (my DB Context).

The DB Context class takes a parameter of DbContextOptions options and passes the options to the base constructor (DbContext).

I need to create an instance of my DB Context in my implementation of IHostedService (a singleton object) but I can't seem to figure out how to correctly create a new instance of DbContextOptions from my IHostedService implementation.

James
  • 419
  • 4
  • 25

2 Answers2

2

For resolving a Scoped Service from a Singleton Service, you could create the scoped service from IServiceProvider.

Here is the demo code:

    public class DbHostedService : IHostedService
{
    private readonly ILogger _logger;

    public DbHostedService(IServiceProvider services,
        ILogger<DbHostedService> logger)
    {
        Services = services;
        _logger = logger;
    }

    public IServiceProvider Services { get; }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "Consume Scoped Service Hosted Service is starting.");

        DoWork();

        return Task.CompletedTask;
    }

    private void DoWork()
    {
        _logger.LogInformation(
            "Consume Scoped Service Hosted Service is working.");

        using (var scope = Services.CreateScope())
        {
            var context =
                scope.ServiceProvider
                    .GetRequiredService<ApplicationDbContext>();

            var user = context.Users.LastOrDefault();

            _logger.LogInformation(user?.UserName);
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "Consume Scoped Service Hosted Service is stopping.");

        return Task.CompletedTask;
    }
}

Reference: Consuming a scoped service in a background task

Edward
  • 28,296
  • 11
  • 76
  • 121
-1

I think you need not IHostedService. Myeby your need this

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<BlogContext>(options =>

       options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddMvc();
        services.AddSession();
    }
FX_Sektor
  • 1,206
  • 2
  • 14
  • 32
  • That code you have is what I am using. The IHostedService is for a different purpose but still needs the DBContext – James Sep 10 '18 at 20:23