You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8升级至.NET 9后无法解析EF Core作用域服务问题求助

.NET 9升级后EF Core依赖注入错误排查与解决

错误信息

运行升级到.NET 9的应用时出现以下错误:

Cannot resolve scoped service 'System.Collections.Generic.IEnumerable`1[Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptionsConfiguration`1[TestEFCore9Worker.Context.ExampleDbContext]]' from root provider.

错误详情

上下文代码

Program.cs 服务注册代码

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();

builder.Services.AddDbContextFactory<ExampleDbContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("DbConnectionString"));
});

builder.Services.AddDbContext<ExampleDbContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("DbConnectionString"));
});

var host = builder.Build();
host.Run();

ExampleDbContext.cs 实现代码

public class ExampleDbContext : DbContext
{
    public ExampleDbContext(DbContextOptions options) : base(options)
    {
    }

    public required virtual DbSet<ExampleModel> Examples { get; set; }
}

Worker.cs 后台服务代码

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IServiceScopeFactory _serviceScopeFactory;

    public Worker(ILogger<Worker> logger, IServiceScopeFactory serviceScopeFactory)
    {
        _logger = logger;
        _serviceScopeFactory = serviceScopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            if (_logger.IsEnabled(LogLevel.Information))
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            }

            using (IServiceScope serviceScope = _serviceScopeFactory.CreateScope())
            {
                var dbContextFactory = serviceScope.ServiceProvider.GetRequiredService<IDbContextFactory<ExampleDbContext>>();
                using var dbContext = dbContextFactory.CreateDbContext();

                var exampleModel = new ExampleModel { Name = Guid.NewGuid().ToString() };

                dbContext.Examples.Add(exampleModel);

                dbContext.SaveChanges();
            }

            await Task.Delay(1000, stoppingToken);
        }
    }
}

问题更新

移除Program.cs中的AddDbContext注册后,错误不再出现,但无法理解为何.NET 8中同时使用AddDbContext和AddDbContextFactory没有问题。

原因分析

.NET 9中EF Core对DbContext与DbContextFactory的注册逻辑做了调整:

  • 同时调用AddDbContext和AddDbContextFactory时,EF Core内部注册的IDbContextOptionsConfiguration<ExampleDbContext>服务生命周期为Scoped
  • 当从根服务提供者解析DbContextFactory相关服务时,尝试获取Scoped服务就会触发这个错误
  • .NET 8中EF Core的注册逻辑未引入这个冲突,因此同时注册两者可以正常运行

解决方案

方案一:移除冗余的DbContext注册

由于Worker中已经通过IDbContextFactory<ExampleDbContext>获取DbContext,无需直接注册DbContext。修改Program.cs,删除AddDbContext的代码:

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();

// 仅保留工厂注册
builder.Services.AddDbContextFactory<ExampleDbContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("DbConnectionString"));
});

var host = builder.Build();
host.Run();

方案二:统一配置并调整构造函数(如需保留两种注册)

  1. 修改DbContext的构造函数为泛型版本:
public class ExampleDbContext : DbContext
{
    public ExampleDbContext(DbContextOptions<ExampleDbContext> options) : base(options)
    {
    }

    public required virtual DbSet<ExampleModel> Examples { get; set; }
}
  1. 统一DbContext的配置逻辑,避免重复配置:
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();

// 先配置DbContextOptions
Action<DbContextOptionsBuilder> dbOptions = options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DbConnectionString"));

builder.Services.AddDbContextFactory<ExampleDbContext>(dbOptions);
builder.Services.AddDbContext<ExampleDbContext>(dbOptions);

var host = builder.Build();
host.Run();

内容的提问来源于stack exchange,提问作者ThangLe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 08:16:04