.NET 8运行Program.cs遇System.AggregateException的解决求助
问题背景
基于IHostedService实现邮件后台服务时,启动Program.cs触发System.AggregateException,此前未添加邮件后台发送逻辑时功能正常。
错误详情
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Business.Abstract.ICustomerService Lifetime: Scoped ImplementationType: Business.Concrete.CustomerManager': Unable to resolve service for type 'DataAccess.Concrete.EntityFramework.SqlContext' while attempting to activate 'DataAccess.Concrete.EntityFramework.EfCustomerDal'.) (Error while validating the service descriptor 'ServiceType: DataAccess.Abstract.ICustomerDal Lifetime: Scoped ImplementationType: DataAccess.Concrete.EntityFramework.EfCustomerDal': Unable to resolve service for type 'DataAccess.Concrete.EntityFramework.SqlContext' while attempting to activate 'DataAccess.Concrete.EntityFramework.EfCustomerDal'.) (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: KodiksProject.API.Services.EmailBackgroundService': Unable to resolve service for type 'Business.Concrete.CustomerManager' while attempting to activate 'KodiksProject.API.Services.EmailBackgroundService'.)'
相关代码片段
ICustomerService
public interface ICustomerService { IResult Add(Customer customer); IResult Update(Customer customer); IResult Delete(int id); IDataResult<Customer> Get(int id); IDataResult<List<Customer>> GetAll(); Task SendEmailsToCustomersAsync(); }
CustomerManager
public class CustomerManager : ICustomerService { ICustomerDal _customerDal; private readonly IEmailService _emailService; public CustomerManager(ICustomerDal customerDal, IEmailService emailService) { _customerDal = customerDal; _emailService = emailService; } public IResult Add(Customer customer) { _customerDal.Add(customer); return new SuccessResult(); } public IResult Delete(int id) { _customerDal.Delete(id); return new SuccessResult(); } public IDataResult<Customer> Get(int id) { return new SuccessDataResult<Customer>(_customerDal.Get(c => c.CustomerId == id)); } public IDataResult<List<Customer>> GetAll() { return new SuccessDataResult<List<Customer>>(_customerDal.GetAll()); } public IResult Update(Customer customer) { _customerDal.Update(customer); return new SuccessResult(); } public async Task SendEmailsToCustomersAsync() { var customerEmails = await _customerDal.GetAllCustomerEmailsAsync(); var tasks = new List<Task>(); foreach (var email in customerEmails) { var task = _emailService.SendEmailAsync(email, "asdasas", "asasadasdasd"); tasks.Add(task); } await Task.WhenAll(tasks); } }
SqlContext
public class SqlContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"my connection string"); } public DbSet<Customer> Customers { get; set; } public DbSet<Order> Orders { get; set; } public DbSet<Product> Products { get; set; } }
EfCustomerDal
public class EfCustomerDal : EfEntityRepositoryBase<Customer, SqlContext>, ICustomerDal { private readonly SqlContext _context; public EfCustomerDal(SqlContext context) { _context = context; } public async Task<List<string>> GetAllCustomerEmailsAsync() { var emails = await _context.Customers .Select(c => c.Email) .ToListAsync(); return emails; } }
ICustomerDal
public interface ICustomerDal : IEntityRepository<Customer> { Task<List<string>> GetAllCustomerEmailsAsync(); }
EmailService
public class EmailService : IEmailService { private readonly SmtpClient _smtpClient; public EmailService() { _smtpClient = new SmtpClient("server") { Port = 465, Credentials = new NetworkCredential("username", "password"), EnableSsl = true, }; } public async Task SendEmailAsync(string to, string subject, string body) { var mailMessage = new MailMessage("username", to, subject, body); await _smtpClient.SendMailAsync(mailMessage); } }
问题根源与解决方法
问题分析
- 核心底层问题:
SqlContext未注册到依赖注入容器,导致EfCustomerDal无法被构造 - 连锁问题:
CustomerManager依赖EfCustomerDal,因此也无法完成构造 - 生命周期冲突:
EmailBackgroundService是Singleton生命周期,直接依赖Scoped的ICustomerService,即使前面的问题解决,也会出现生命周期不兼容的错误
解决步骤
步骤1:注册SqlContext到DI容器
在Program.cs的服务配置中添加:
builder.Services.AddDbContext<SqlContext>(options => options.UseSqlServer(@"my connection string"));
(建议将连接字符串存入配置文件,避免硬编码)
步骤2:修正Singleton依赖Scoped服务的问题
IHostedService是Singleton,不能直接注入Scoped服务,需通过IServiceScopeFactory手动创建作用域。修改EmailBackgroundService:
public class EmailBackgroundService : BackgroundService { private readonly IServiceScopeFactory _scopeFactory; public EmailBackgroundService(IServiceScopeFactory scopeFactory) { _scopeFactory = scopeFactory; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { using (var scope = _scopeFactory.CreateScope()) { var customerService = scope.ServiceProvider.GetRequiredService<ICustomerService>(); await customerService.SendEmailsToCustomersAsync(); } // 设置邮件发送间隔,示例为每小时一次 await Task.Delay(TimeSpan.FromHours(1), stoppingToken); } } }
步骤3:确保其他服务正确注册
检查Program.cs中是否完成以下服务注册:
builder.Services.AddScoped<ICustomerDal, EfCustomerDal>(); builder.Services.AddScoped<ICustomerService, CustomerManager>(); builder.Services.AddScoped<IEmailService, EmailService>(); builder.Services.AddHostedService<EmailBackgroundService>();
内容的提问来源于stack exchange,提问作者Umut Konmus

