实体框架核心 DbContextFactory 未注册

Posted

技术标签:

【中文标题】实体框架核心 DbContextFactory 未注册【英文标题】:Entity Framework Core DbContextFactory not registering 【发布时间】:2021-12-27 15:24:36 【问题描述】:

我正在使用 .NET 5 和 Entity Framework Core 以及 Hot Chocolate 来创建 GraphQL api。列出的为从 api 获得适当性能的必要更改之一是使用在同一上下文中运行的并行操作,而 EF 并不擅长这一点。所述修复是使用“池化上下文工厂”。

当我尝试在初始启动时构建上下文模型和数据库时出现问题。我的上下文工厂没有注册,但标准的 dbContext 是。我不确定自己遗漏了什么或在哪里寻找问题/解决方案,因此我在这里呼吁更广泛的受众,希望其他人能看到我看不到的东西。

这是我添加上下文工厂的 Startup 的 ConfigureServices 部分:

public void ConfigureServices(IServiceCollection services)

    // Configure context
    services.AddDbContextFactory<AppContext>((s, options) =>
        options
            .UseSqlServer(_config.GetConnectionString("TransactDB"))
            .UseLoggerFactory(s.GetRequiredService<ILoggerFactory>())
    );

    // This bit works if I use it, but the bit above doesn't.
    //services.AddDbContext<AppContext>(options => 
    //  options.UseSqlServer(_config.GetConnectionString("TransactDB"))
    //);

    // other code removed for brevity


这是程序文件的代码:

public class Program

    public static void Main(string[] args)
    
        IHost host = CreateHostBuilder(args).Build();
        CreateDbIfNotExists(host);
        host.Run();
    

    private static void CreateDbIfNotExists(IHost host)
    
        using (IServiceScope scope = host.Services.CreateScope())
        
            IServiceProvider services = scope.ServiceProvider;
            try
            
                AppContext context = services.GetRequiredService<AppContext>(); // this line here is where it breaks
                context.Database.EnsureCreated();
            
            catch (Exception ex)
            
                ILogger<Program> logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occured while creating the DB.");
            
        
    

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(c => c.AddConsole())
            .ConfigureWebHostDefaults(webBuilder =>
            
                webBuilder.UseStartup<Startup>();
            );

这是我的上下文:

public class AppContext : DbContext

    public AppContext(DbContextOptions<AppContext> options)
        : base(options)
    
        // intentionally left blank
    

    public DbSet<Site> Sites  get; set;  = default!;
    public DbSet<Customer> Customers  get; set;  = default!;
    public DbSet<Employee> Employees  get; set;  = default!;
    public DbSet<Vehicle> Vehicles  get; set;  = default!;
    public DbSet<Transaction> Transactions  get; set;  = default!;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    
        new SiteEntityTypeConfiguration().Configure(modelBuilder.Entity<Site>());
        new CustomerEntityTypeConfiguration().Configure(modelBuilder.Entity<Customer>());
        new EmployeeEntityTypeConfiguration().Configure(modelBuilder.Entity<Employee>());
        new VehicleEntityTypeConfiguration().Configure(modelBuilder.Entity<Vehicle>());
        new TransactionEntityTypeConfiguration().Configure(modelBuilder.Entity<Transaction>());

        foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
        
            relationship.DeleteBehavior = DeleteBehavior.Restrict;
        

        base.OnModelCreating(modelBuilder);
    

最后,这是我在启动应用程序时在控制台中看到的错误:

fail: AppApi.Program[0]
    An error occured while creating the DB.
    System.InvalidOperationException: No service for type 'AppApi.Common.Data.AppContext' has been registered.
       at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
       at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
       at AppApi.Program.CreateDbIfNotExists(IHost host) in C:\Users\me\dev\App\back-end\AppApi\Program.cs:line 26

如果我使用标准AddDbContext&lt;AppContext&gt;,即使同时使用两者,上述错误也不会被记录。这意味着,对我来说,AddDbContextFactory&lt;AppContext&gt; 实际上根本没有做任何事情,但是 VisualStudio 将它识别为 IServiceCollection 接口上的有效方法,所以我不确定它为什么没有注册。我敢肯定它很小,当我终于找到它时,我可能会有一些选择词,但现在我不知所措。

如果人们需要查看其他代码或其他信息,请告诉我。我将自己继续挑选,如果我在别人之前找到答案,我会提供答案。

【问题讨论】:

查看 EF Core 文档 - Using a DbContext factory @IvanStoev 除非我失明,否则我的实现遵循 EF Core 文档。如果你能找到我丢失的部分,请告诉我,因为我当然不能。 services.GetRequiredService&lt;AppContext&gt;() 不适用于请求的工厂 - 正如您在链接中看到的那样,工厂的使用方式不同,例如获取工厂var factory = services.GetRequiredService&lt;IDbContextFactory&lt;AppContext&gt;&gt;();,然后使用它获取上下文using (var context = factory.CreateDbContext()) 【参考方案1】:

感谢@IvanStoev 为我指明了正确的方向。我的印象是,仅在控制器和服务中才需要从工厂创建上下文实例。

工作代码如下所示:

...
private static void CreateDbIfNotExists(IHost host)

    using (IServiceScope scope = host.Services.CreateScope())
    
        IServiceProvider services = scope.ServiceProvider;
        try
        
            var factory = services.GetRequiredService<IDbContextFactory<BennyNetContext>>();
            using (BennyNetContext context = factory.CreateDbContext())
            context.Database.EnsureCreated();
        
        catch (Exception ex)
        
            ILogger<Program> logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occured while creating the DB.");
        
    

...

【讨论】:

以上是关于实体框架核心 DbContextFactory 未注册的主要内容,如果未能解决你的问题,请参考以下文章

保存已编辑的核心数据实体未保存

核心数据实体未删除

核心数据 - 实体关系未按预期工作

删除核心数据中所有未提交的实体[重复]

为啥实体框架核心加载实体的关系而不添加包含

实体框架核心实体 > 值对象 > 实体关系