如何在Blazor后台服务中注入DbContextFactory?
问题:Blazor Server后台服务无法注入DbContextFactory
我正在开发第一个Blazor Server应用,这也是我的第一个Entity Framework Core项目。需求是搭建一个后台服务,每天凌晨检查数据库中昨日新增的特定类型记录,若存在则提取、格式化后发送邮件给相关人员。
手动通过页面触发报告时,EF查询、内容格式化及邮件发送的代码都能正常运行,但现在卡在了**如何给后台服务提供DbContextFactory
之前在Razor页面里都是用@inject IDbContextFactory<miniDARTSContext> DbFactory通过依赖注入获取实例,但后台服务要在Program.cs里配置,没法用Razor的注入方式。
我按照微软教程配置了名为PhaseChangeReportService的后台服务,原本它能每10秒向控制台输出运行计数,但我对其中的间接调用逻辑不太理解。
尝试修改PhaseChangeReportService的构造函数,添加IDbContextFactory<miniDARTSContext>参数后,构造函数的断点根本没触发,服务没有任何输出,也没抛出异常。
相关代码片段
原始PhaseChangeReportService代码
namespace miniDARTS.ScopedService { public sealed class PhaseChangeReportService : IScopedProcessingService { private int _executionCount; private readonly ILogger<PhaseChangeReportService> _logger; public PhaseChangeReportService(ILogger<PhaseChangeReportService> logger) { _logger = logger; } public async Task DoWorkAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { ++_executionCount; _logger.LogInformation("{ServiceName} working, execution count: {Count}", nameof(PhaseChangeReportService), _executionCount); await Task.Delay(10_000, stoppingToken); } } } }
修改后的构造函数
private readonly ILogger<PhaseChangeReportService> _logger; private readonly IDbContextFactory<miniDARTSContext> _dbContextFactory; public PhaseChangeReportService(ILogger<PhaseChangeReportService> logger, IDbContextFactory<miniDARTSContext> dbContextFactory) { _logger = logger; _dbContextFactory = dbContextFactory; }
Program.cs相关代码
// Configure the database connection. string connectionString = builder.Configuration.GetConnectionString("miniDARTSContext"); var serverVersion = new MySqlServerVersion(new Version(8, 0, 28)); builder.Services.AddDbContextFactory<miniDARTSContext>(options => options.UseMySql(connectionString, serverVersion), ServiceLifetime.Scoped); IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddHostedService<ScopedBackgroundService>(); services.AddScoped<IScopedProcessingService, PhaseChangeReportService>(); }) .Build(); host.RunAsync();
IScopedProcessingService.cs
namespace miniDARTS.ScopedService { public interface IScopedProcessingService { Task DoWorkAsync(CancellationToken stoppingToken); } }
ScopedBackgroundService.cs
namespace miniDARTS.ScopedService; public sealed class ScopedBackgroundService : BackgroundService { private readonly IServiceProvider _serviceProvider; private readonly ILogger<ScopedBackgroundService> _logger; public ScopedBackgroundService(IServiceProvider serviceProvider, ILogger<ScopedBackgroundService> logger) { _serviceProvider = serviceProvider; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation($"{nameof(ScopedBackgroundService)} is running."); await DoWorkAsync(stoppingToken); } private async Task DoWorkAsync(CancellationToken stoppingToken) { _logger.LogInformation($"{nameof(ScopedBackgroundService)} is working."); using (IServiceScope scope = _serviceProvider.CreateScope()) { IScopedProcessingService scopedProcessingService = scope.ServiceProvider.GetRequiredService<IScopedProcessingService>(); await scopedProcessingService.DoWorkAsync(stoppingToken); } } public override async Task StopAsync(CancellationToken stoppingToken) { _logger.LogInformation($"{nameof(ScopedBackgroundService)} is stopping."); await base.StopAsync(stoppingToken); } }
我的疑问
我肯定在服务/依赖注入的基础概念上有误解,但搜了一圈没找到可行方案,希望得到帮助。
内容的提问来源于stack exchange,提问作者Neil Wehneman
相关产品推荐
相关产品推荐

