在.NET 8.0上运行program.cs时出现System.AggregateException

问题描述 投票:0回答:2

我正在尝试基于

IHostedService
实现电子邮件后台服务。

但我收到此错误:

System.AggregateException:“无法构造某些服务(验证服务描述符时出错”ServiceType:Business.Abstract.ICustomerService Lifetime:Scoped ImplementType:Business.Concrete.CustomerManager”:无法解析类型“DataAccess”的服务。尝试激活“DataAccess.Concrete.EntityFramework.EfCustomerDal”时出现“Concrete.EntityFramework.SqlContext”。)(验证服务描述符“ServiceType:DataAccess.Abstract.ICustomerDal 生命周期:作用域实现类型:DataAccess.Concrete.EntityFramework.EfCustomerDal”时出错:尝试激活“DataAccess.Concrete.EntityFramework.EfCustomerDal”时无法解析类型“DataAccess.Concrete.EntityFramework.SqlContext”的服务。)(验证服务描述符“ServiceType:Microsoft.Extensions.Hosting.IHostedService 生命周期时出错:Singleton” ImplementType:KodiksProject.API.Services.EmailBackgroundService':尝试激活'KodiksProject.API.Services.EmailBackgroundService'时无法解析类型'Business.Concrete.CustomerManager'的服务。)'

如何解决这个问题?

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);
    }
}

我尝试了一切,但无法解决这个问题。在我尝试与后台工作人员发送电子邮件之前,这是有效的。我看不出我的依赖注入或服务寿命有任何问题。

我被困在这里,不知道该怎么办。

你能帮我解决这个问题吗?

c# asp.net-core service ihostedservice
2个回答
1
投票

文档的在后台任务中使用范围服务对此进行了介绍。托管服务注册为单例,它们不应该(如果启用范围验证则不能)消耗范围依赖项。默认情况下,EF Core 上下文添加为单例(即通过

AddDbContext...
调用)。解决方案是注入
IServiceProvider
并用它来解决依赖关系。例如:

public class ConsumeScopedServiceHostedService : BackgroundService
{
    private readonly ILogger<ConsumeScopedServiceHostedService> _logger;
    private readonly IServiceProvider Services;

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

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Consume Scoped Service Hosted Service running.");

        using var scope = Services.CreateScope();
        var scopedProcessingService = scope.ServiceProvider
            .GetRequiredService<IScopedProcessingService>();

        await scopedProcessingService.DoWork(stoppingToken);
    }
}

另请阅读:

  1. 使用寿命
  2. 强制依赖 - 基本上为什么单例不应该解析作用域服务(例如,如果您使用 EF 而不回收“每次迭代”的作用域,您最终可能会出现内存泄漏行为)。

0
投票

这是因为您的 dbcontext 已被释放而发生的,要解决此问题,您可以在 EmailService 的 SendEmailAsync 方法中创建一个工作范围单元,然后它必须正常工作。这是使用后台服务时的普遍问题。

© www.soinside.com 2019 - 2024. All rights reserved.