EFCore 无法识别数据库提供程序

Dbl*_*247 3 c# entity-framework-core asp.net-core entity-framework-migrations

我有一个 .Net Core WebApplication 项目,其中 Context 类位于类库中。如果我在 OnConfiguring(DbContextOptionsBuilder optionsBuilder) 方法中硬编码连接字符串,我可以生成迁移。由于最好让依赖注入管理上下文,因此我想将其添加到启动类中。但是,当我这样做时,出现以下错误:

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

DbContext 类:

public class CustomerManagerContext : IdentityDbContext<User, Role, long, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>
{
    public CustomerManagerContext() { }
    public CustomerManagerContext(DbContextOptions<CustomerManagerContext> options) : base(options)
    {
    }

    //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    //{
    //    base.OnConfiguring(optionsBuilder);
    //    optionsBuilder.UseSqlServer("SecretConnectionString");
    //}


    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<User>().ToTable("Users");
        builder.Entity<Role>().ToTable("Roles");
        builder.Entity<UserClaim>().ToTable("UserClaims");
        builder.Entity<UserRole>().ToTable("UserRoles");
        builder.Entity<UserLogin>().ToTable("UserLogins");
        builder.Entity<RoleClaim>().ToTable("RoleClaims");
        builder.Entity<UserToken>().ToTable("UserTokens");

    }
}
Run Code Online (Sandbox Code Playgroud)

启动类 - ConfigureServices 方法

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<CustomerManagerContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
    );

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

    services.AddIdentity<User, Role>()
        .AddEntityFrameworkStores<CustomerManagerContext>()
        .AddDefaultTokenProviders();
}
Run Code Online (Sandbox Code Playgroud)

Yah*_*ous 7

这让我很难受,得到如下错误:

  • No database provider has been configured for this DbContext.
  • No design-time services were found.
  • The server was not found or was not accessible.

但我最终得到了一个相当简单的解决方案/解决方法:

  • 在您的解决方案(或您的命令行)中设置默认启动项目
  • 在您Startup.cs 添加迁移项目

    public void ConfigureServices(IServiceCollection services)
    {
        var myDbContextAssemblyName = typeof(MyDbContext).Assembly.GetName().Name;
        var connectionString = Configuration.GetConnectionString(MyDbContext.ConnectionStringName);
        services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
            connectionString,
            x => x.MigrationsAssembly(myDbContextAssemblyName)));
            // do more ...
        }
    
    Run Code Online (Sandbox Code Playgroud)
  • 在您的连接字符串中使用IP 地址和端口号(受此corefx 问题启发),而不是服务器名称/dns(FWIW:查询以获取 IP)。所以现在我在我的appsettings.Development.json

    "ConnectionStrings": { "MyConnectionStringName": "Data Source=10.1.2.3,1433; Initial Catalog=MyCatalog; Integrated Security=SSPI" }

TLDR:其他建议

我发现了很多其他的建议,我会提到一些看起来很有趣的。也许它会帮助别人:

命令行中的项目名称

在命令行中提及启动项目和迁移项目:

Update-Database -Verbose -Project x.Data -StartupProject x.Web
Run Code Online (Sandbox Code Playgroud)

从代码迁移

还可以在StartUp调用迁移 ,“针对具有本地数据库的应用程序”。(我想否则会在多个节点上运行,可能会同时启动多个运行时迁移并出现并发问题?)

myDbContext.Database.Migrate();
Run Code Online (Sandbox Code Playgroud)

在 Main.cs 中设置 DbContext

此 EntityFrameworkCore 问题指出:

问题是,当 EF 调用CreateWebHostBuilder或者 BuildWebHost它没有运行Main. (这是有意为之,因为 EF 需要在DbContext不启动应用程序的情况下构建模型并使用。)这意味着当 EF 调用这些方法时,静态IConfiguration属性仍然为空——因为它只在Main. 因此,您需要确保 IConfiguration在 EF 调用这些方法之一时设置/处理它,或者使用IDesignTimeDbContextFactory.

这对我来说不是必需的,我猜是因为 .Net Core 2在幕后加载了配置

将 IDesignTimeDbContextFactory 与环境变量一起使用

此 EntityFrameworkCore 问题指出:

执行此操作的典型方法是读取文件、环境变量或IDesignTimeDbContextFactory.

这对我来说似乎太过分了。

在设计时创建 DbContext

微软文档提到:

某些 EF Core Tools 命令(例如,Migrations 命令)需要在设计时创建派生的 DbContext 实例,以便收集有关应用程序实体类型以及它们如何映射到数据库架构的详细信息。

他们提到了这些提供此设计时 DbContext 的方法:

  • 来自应用程序服务:对于作为启动项目的 ASP.NET Core 应用程序:

    这些工具尝试DbContext从应用程序的服务提供者那里获取对象。[...] 工具首先尝试通过调用Program.BuildWebHost()[JP: 或 CreateWebHostBuilder] 并访问IWebHost.Services 属性来获取服务提供者。在DbContext本身和它的构造需要的任何相关注册为应用程序的服务提供者的服务。这可以通过在DbContext将 的实例 DbContextOptions<TContext>作为参数的构造函数上轻松实现并使用该 AddDbContext<TContext>方法。

  • 使用没有参数的构造函数

    如果DbContext无法从应用程序服务提供商处获得,则工具会DbContext在项目中查找派生类型。然后他们尝试使用没有参数的构造函数创建一个实例。如果DbContext 使用该OnConfiguring方法配置,则这可以是默认构造函数。

  • 来自设计时工厂

    您还可以DbContext通过实现IDesignTimeDbContextFactory<TContext>接口告诉工具如何创​​建您的接口:如果在派生 DbContext 所在的同一项目中或在应用程序的启动项目中找到实现此接口的类,则工具会绕过其他创建DbContext 和使用接口的方法设计时工厂。


归档时间:

查看次数:

2333 次

最近记录:

7 年,2 月 前