.Net 8 API:无法从单例注册作用域服务

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

在我的 API 中,我使用“AddHostedService”注册了一些服务,这些服务需要注入一些接口,例如:

Program.cs:

builder.Services.AddScoped<IHypervisorRepository, HypervisorRepository>();
builder.Services.AddScoped<IAccountRepository, AccountRepository>();
builder.Services.AddScoped<ICloudStackDbUnitOfWork, CloudStackDbUnitOfWork>();
builder.Services.AddScoped<ICloudStackCoreConnectionFactory, MySqlCloudStackCoreConnectionFactory>();

builder.Services.AddScoped<IJobUtility, JobUtility>();
builder.Services.AddScoped<IVdcUnitOfWork, VdcUnitOfWork>();
builder.Services.AddScoped<IMemoryCache, MemoryCache>();

builder.Services.AddHostedService<CheckDatabaseHealthBackgroundService>();

CheckDatabaseHealthBackgroundService.cs:

public sealed class CheckDatabaseHealthBackgroundService : BackgroundService, IDisposable
{
    private readonly IServiceProvider _provider;
    private readonly IJobUtility _jobUtility;
    private readonly IVdcUnitOfWork _unitOfWork;
    private readonly ICloudStackCoreConnectionFactory _connFactory;
    private readonly IMemoryCache _cache;
    private readonly ILogger<CheckDatabaseHealthBackgroundService> _logger;
    
    public CheckDatabaseHealthBackgroundService(
        IServiceProvider provider,
        IJobUtility jobUtility,
        IVdcUnitOfWork unitOfWork,
        ICloudStackCoreConnectionFactory connFactory,
        IMemoryCache cache,
        ILogger<CheckDatabaseHealthBackgroundService> logger)
    {
        _provider = provider;
        _jobUtility = jobUtility;
        _unitOfWork = unitOfWork;
        _connFactory = connFactory;
        _cache = cache;
        _logger = logger;
    }

但是在我启动 API 后,会抛出以下异常:

System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: CloudStackData.WebAPI.RefreshDiskTypeBackgroundService': Cannot consume scoped service 'Vdc.Libs.Data.IVdcUnitOfWork' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.
 ---> System.InvalidOperationException: Cannot consume scoped service 'Vdc.Libs.Data.IVdcUnitOfWork' from singleton 'Microsoft.Extensions.Hosting.IHostedService'

读完这个错误后,我得出结论,我应该将“CheckDatabaseHealthBackgroundService”所需的服务添加为单例,而不是限定范围,所以我尝试了:

Program.cs:

builder.Services.AddScoped<IHypervisorRepository, HypervisorRepository>();
builder.Services.AddScoped<IAccountRepository, AccountRepository>();
builder.Services.AddScoped<ICloudStackDbUnitOfWork, CloudStackDbUnitOfWork>();
builder.Services.AddScoped<ICloudStackCoreConnectionFactory, MySqlCloudStackCoreConnectionFactory>();

builder.Services.AddSingleton<IJobUtility, JobUtility>();
builder.Services.AddSingleton<IVdcUnitOfWork, VdcUnitOfWork>();
builder.Services.AddSingleton<IMemoryCache, MemoryCache>();

builder.Services.AddHostedService<CheckDatabaseHealthBackgroundService>();

现在抛出的异常是:

System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: CloudStackData.WebAPI.RefreshDiskTypeBackgroundService': Cannot consume scoped service 'Vdc.Libs.Data.DbContextWrite' from singleton 'Vdc.Libs.Data.IVdcUnitOfWork'.

我开始陷入困境。

VdcUnitOfWork 是我们的另一个库。

VdcUnitOfWork.cs:

public sealed class VdcUnitOfWork : EFDbUnitOfWork<DbContextWrite>, IVdcUnitOfWork, IUnitOfWork, IDisposable, IDbContextWrapper
{
    public VdcUnitOfWork(DbContextWrite dbContext)
        : base(dbContext)
    {
    }
}

DbContextWrite 也是我们的另一个库。

DbContextWrite.cs:

public abstract class DbContextWrite : DbContext
{
    protected DbContextWrite([NotNull] DbContextOptions options)
        : base(options)
    {
    }
}

事实是,在使用 AddHostedService 添加托管服务后,我无法再运行该 API(我有四个托管服务,但为了简化只放了一个)。

有什么帮助吗?

c# .net api dependency-injection service
1个回答
0
投票

要在

HostedService
(单例)中使用作用域服务,您需要注入
IServiceScopeFactory
(使用
.NET 8.0
中的主构造函数):

public sealed class CheckDatabaseHealthBackgroundService
      (IServiceScopeFactory scopeFactory) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
         // get scoped services:
         using var scope = scopeFactory.CreateScope();
         var jobUtility = scope.ServiceProvider.GetService<IJobUtility>();

         // do the same with all other scoped Services
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.