【问题标题】:EF Core 2.1 - No database provider has been configured for this DbContextEF Core 2.1 - 没有为此 DbContext 配置数据库提供程序
【发布时间】:2020-06-16 16:51:47
【问题描述】:

我有 ASP.Net Core 2.1 和 EF Core 2.1。这就是我的 DbContext 类的样子

app.DAL.EF -> 层

using app.domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;

namespace app.EF
{
 public class MyAppContext : DbContext
 {
    public MyAppContext(DbContextOptions<MyAppContext> options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new CustomerConfiguration());
        modelBuilder.HasDefaultSchema("app");
        base.OnModelCreating(modelBuilder);
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
    }

    public DbSet<Customer> Customers { get; set; }
 }

   public class MyAppContextConfiguration : IDesignTimeDbContextFactory<MyAppContext>
   {
    public MyAppContext CreateDbContext(string[] args)
    {
        IConfigurationRoot configuration = new ConfigurationBuilder()
                                            .SetBasePath(Directory.GetCurrentDirectory())
                                            .AddJsonFile("appsettings.json", optional: false, true)
                                            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT ") ?? "Production" }.json", optional: true)
                                            .Build();

        var optionsBuilder = new DbContextOptionsBuilder<MyAppContext>();
        //optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
        var dbConString = configuration.GetConnectionString("ITMDbConnection");

        optionsBuilder.UseSqlServer(dbConString);

        return new MyAppContext(optionsBuilder.Options);
    }
}

public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
    public void Configure(EntityTypeBuilder<Customer> builder)
    {
        builder.HasKey(x => x.Id);
    }
}}

app.DI -> 层

  public static class Factory
  {
    public static void Initialize(ref IServiceCollection services)
    {
        //services.AddTransient<MyAppContext>();
        services.AddDbContext<MyAppContext>(options =>
        {

        });
        //services.AddTransient<MyAppContextConfiguration>();
        services.AddTransient<ICustomerRepository, CustomerRepository>();
    }
}

app.API -> 层

 namespace app.api
 {
 public class Startup
 {
     public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        Factory.Initialize(ref services);
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}}

从包管理器控制台运行Add-Migration DbInit时,抛出以下错误

没有为此 DbContext 配置数据库提供程序。可以通过覆盖 DbContext.OnConfiguring 方法或在应用程序服务提供者上使用 AddDbContext 来配置提供者。如果使用了 AddDbContext,那么还要确保您的 DbContext 类型在其构造函数中接受 DbContextOptions 对象并将其传递给 DbContext 的基本构造函数。

谢谢!

【问题讨论】:

  • 错误信息很清楚。这应该使用什么数据库?甲骨文、PostgreSQL、MySQL?它将连接到哪里?一个本地数据库,一个远程数据库,AWS RDS?您需要在AddDbContext 中指定提供者和连接。其中,顺便说一句,应该在Startup.cs。这些方法是 DI 配置方法,而不是工厂或层。如果你想简化你的代码,你可以创建一个扩展方法来接收并且返回一个IServiceCollection,允许你像其他DI配置方法一样链接配置调用
  • @PanagiotisKanavos MyAppContextConfiguration 类中提到的不一样吗?
  • 您没有在任何地方使用CreateDbContext。这段代码有点过于复杂。那些类、方法不是层,它们只是一个 DbContext 和一些启动配置方法。 DbContext 配置和 DI 注册由AddDbContext 执行。一个简单的options.UseSqlServer(Configuration.GetConnectionString("ITMDbConnection")) 就可以了。 MyAppContextConfiguration 类不在 Startup.cs 中的任何地方使用
  • ASP.NET Core 2.x 和 3.x 中的主机构建器已经执行了CreateDbContext 中的配置步骤 - 加载appsettings.json、任何环境文件等。这意味着Configuration Startup.cs 中的字段可以加载连接字符串
  • 如果我在 Factory 或 Startup 类中使用此 options.UseSqlServer()。然后引入了紧耦合

标签: c# entity-framework-core entity-framework-migrations asp.net-core-2.1 ef-core-2.1


【解决方案1】:

正如它所说的那样 - 没有附加数据库提供程序。

查看您的所有代码。您在哪里指定数据库提供程序? UseSqlServer 之类的东西(在 DbContext 的 OnConfiguring 中),具体取决于您要使用的数据库提供程序。

【讨论】:

    【解决方案2】:

    配置服务内部

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    

    在 appsettings.json 中

    {
        "ConnectionStrings": {
            "DefaultConnection": "SQL connection string"
        }
    }
    

    【讨论】:

    • MyAppContextConfiguration类中也提到了
    • @Kgn-web 提到,是的。已执行,没有
    • 你/我们能找到一种方法来调用 CreateDbContext() 吗?
    • 已经尝试使用services.AddDbContext&lt;MyAppContextConfiguration() 抛出一些其他错误
    • 看起来你的代码首先指向了app.EF,那启动项目呢?如果您的启动项目是 app.EF,它会从 app.EF 获取连接字符串。否则它会从您的启动项目配置文件中获取。
    【解决方案3】:

    错误很明显 - 从未配置过提供程序和连接。所有这些代码都可以用这个上下文替换:

    public class MyAppContext : DbContext
     {
        public DbSet<Customer> Customers { get; set; }
    
        public MyAppContext(){}
    
        public MyAppContext(DbContextOptions<MyAppContext> options)
            :base(options)
        {}
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //The base method is empty
            modelBuilder.HasDefaultSchema("app");
        }
     }
    
    

    然后在ConfigureServices 中调用AddDbContext

    
     public class Startup
     {
         public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<MyAppContext>(options =>
            {
                var dbConString = Configuration.GetConnectionString("ITMDbConnection");
                options.UseSqlServer(dbConString);
            });
    
    
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }
    
        ....
    
    }
    

    尽管如此,大多数应用程序都有不止一个 DbContext。一种选择是向Startup.cs 添加另一种方法来注册它们。对于更复杂的应用程序,例如由不同域/模块/子系统/项目组成的应用程序,更好的想法是创建扩展方法,例如:

    public static CustomerDomainExtensions
    {
        public static IServicesCollection AddCustomerDomain(this IServicesCollection services,IConfiguration configuration)
        {
            return services.AddCustomerContexts(configuration)
                           .AddRepositories(...)
                           ...;
    
        }
    
        public static AddCustomerContexts(this IServicesCollection services,IConfiguration configuration)
        {
            var dbConString = Configuration.GetConnectionString("ITMDbConnection");
            services.AddDbContext<MyAppContext>(options =>
            {
                options.UseSqlServer(dbConString);
            });
            //Add more contexts ...
        }
    }
    
    

    Startup.cs 中,这将在ConfigureServices 中调用。这就是所有Microsoft.Extensions.* 类的工作方式,通过提供AddUse 扩展方法供Startup.cs 使用:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCustomerDomain(Configuration);
    
    
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }
    

    编辑

    为 DbContext 添加了默认构造函数

    【讨论】:

    • 如果可以的话可以补充一下IDesignTimeDbContextFactory&lt;T&gt;的用途是什么
    • 仅当 DbContext 没有默认构造函数时才需要此接口。解决方案是添加一个默认构造函数。来自the docsImplement this interface to enable design-time services for context types that do not have a public default constructor.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 2021-05-04
    相关资源
    最近更新 更多