A BackgroundService is a singleton, so scoped services (DbContext) must be resolved only from a new scope.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // ====================================================================== // Q: How do you run background work in ASP.NET Core? // // A BackgroundService is a singleton, so scoped services (DbContext) must be // resolved only from a new scope. For heavy or critical jobs: a separate worker // / Azure Function / Hangfire, plus a message queue for reliability. // ====================================================================== public class PriceSyncWorker(IServiceScopeFactory scopes, ILogger<PriceSyncWorker> log) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using var timer = new PeriodicTimer(TimeSpan.FromMinutes(5)); while (await timer.WaitForNextTickAsync(stoppingToken)) { try { await using var scope = scopes.CreateAsyncScope(); // new DbContext every time var sync = scope.ServiceProvider.GetRequiredService<PriceSync>(); await sync.RunAsync(stoppingToken); } catch (Exception ex) when (ex is not OperationCanceledException) { log.LogError(ex, "Price sync failed"); // the worker keeps running } } } } builder.Services.AddHostedService<PriceSyncWorker>(); |