创建每周自动删7天前数据的后台服务遇依赖注入错误
问题解决:后台服务删除过期Issue数据的报错处理
错误原因
HostedService是**单例(Singleton)生命周期服务,而AppDbContext默认是作用域(Scoped)**生命周期。直接在单例服务中注入作用域服务会导致DbContext被长期持有,违背其设计初衷,因此触发依赖注入验证错误。
另外原代码存在两个逻辑问题:
- 日期判断逻辑颠倒:
a.Created.AddDays(7) >= DateTime.Now会筛选出创建时间不足7天的数据,应该改为DateTime.Now >= a.Created.AddDays(7)来匹配超过7天的旧数据。 - 原
ExecuteAsync仅执行一次,无法满足自动定时清理的需求。
修正后的代码
后台服务类修改
using APIExample; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System.Threading; using System.Threading.Tasks; public class BackgroundWorker : BackgroundService { private readonly IServiceProvider _serviceProvider; // 注入服务提供者,而非直接注入DbContext public BackgroundWorker(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { // 定时执行,此处设置为每天执行一次,可根据需求调整间隔 while (!stoppingToken.IsCancellationRequested) { // 创建独立作用域,获取Scoped生命周期的DbContext using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>(); // 筛选并删除超过7天的Issue数据 var oldIssues = dbContext.Issue.Where(a => DateTime.Now >= a.Created.AddDays(7)); dbContext.Issue.RemoveRange(oldIssues); await dbContext.SaveChangesAsync(stoppingToken); // 等待24小时后再次执行,stoppingToken用于优雅停止服务 await Task.Delay(TimeSpan.FromDays(1), stoppingToken); } } }
Program.cs注入代码保持不变
builder.Services.AddHostedService<BackgroundWorker>();
关键说明
- 用
IServiceProvider创建作用域:每次清理任务执行时生成独立作用域,确保DbContext使用后被正确释放,符合Scoped生命周期的设计规范。 - 循环+Delay实现定时任务:通过
while循环配合Task.Delay,实现周期性自动清理,避免服务启动后仅执行一次就结束。 - 修正日期筛选逻辑:确保仅删除创建时间超过7天的历史数据。
- 异步方法优化:使用
SaveChangesAsync和异步Delay,避免阻塞线程影响服务性能。
内容的提问来源于stack exchange,提问作者Jacob Modiba
相关产品推荐
相关产品推荐

