ASP.NET Core › Background Tasks & Hosted Services
How do you safely access scoped services like a DbContext from within a BackgroundService, which is registered as a singleton?
IntermediateAnswer
Since a BackgroundService instance is a singleton for the application's lifetime, you can't inject scoped services (like AppDbContext) directly into its constructor -- inject IServiceScopeFactory instead, and create a new scope for each unit of work, resolving scoped services from that scope and disposing it afterward.
public class OrderProcessor : BackgroundService {
private readonly IServiceScopeFactory _scopeFactory;
public OrderProcessor(IServiceScopeFactory scopeFactory) => _scopeFactory = scopeFactory;
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
while (!stoppingToken.IsCancellationRequested) {
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await ProcessPendingOrdersAsync(db);
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
}Real-world example A background order-processing service creates a fresh DI scope for every polling cycle, ensuring each cycle gets its own DbContext instance rather than sharing a single long-lived context across the entire application lifetime.