ASP.NET Core 8 Web 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:验证服务描述符“ServiceType:Microsoft.Extensions.Hosting.IHostedService 生命周期时出错:单例实现类型:CloudStackData.WebAPI.RefreshDiskTypeBackgroundService”:无法使用单例“Microsoft”中的作用域服务“Vdc.Libs.Data.IVdcUnitOfWork” .Extensions.Hosting.IHostedService'.

System.InvalidOperationException:无法使用单例“Microsoft.Extensions.Hosting.IHostedService”中的范围服务“Vdc.Libs.Data.IVdcUnitOfWork”

读完这个错误后,我得出结论,我应该将

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:验证服务描述符“ServiceType:Microsoft.Extensions.Hosting.IHostedService 生命周期时出错:单例实现类型:CloudStackData.WebAPI.RefreshDiskTypeBackgroundService”:无法使用单例“Vdc”中的作用域服务“Vdc.Libs.Data.DbContextWrite” .Libs.Data.IVdcUnitOfWork'.

我开始陷入困境。

VdcUnitOfWork
是我们创建的自定义类:

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

并且

DbContextWrite
是另一个自定义类:

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

事实是,在使用

AddHostedService
添加托管服务后,我无法再运行 API(我有四个托管服务,但为了简化而只放了一个)。

有什么帮助吗?

c# dependency-injection service asp.net-core-webapi .net-8.0
1个回答
2
投票

要在

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>();
         var unitOfWork = scope.ServiceProvider.GetService<IVdcUnitOfWork>();
         var memoryCache = scope.ServiceProvider.GetService<IMemoryCache>();

         // Use services here
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.