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

问题描述 投票:2回答:2

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

没有为此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");

    }
}

启动类 - 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();
}
c# asp.net-core entity-framework-core ef-migrations
2个回答
4
投票

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

  • 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 add the migration-projectpublic 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 ... }
  • 在你的连接字符串中使用IP地址和端口号(灵感来自this corefx issue),而不是server-name / dns(FWIW:query to get IP)。所以现在我在我的appsettings.Development.json中有这个: “ConnectionStrings”:{“MyConnectionStringName”:“Data Source = 10.1.2.3,1433; Initial Catalog = MyCatalog; Integrated Security = SSPI”}

TLDR: other suggestions

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

命令行中的项目名称

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

Update-Database -Verbose -Project x.Data -StartupProject x.Web

从代码迁移

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

myDbContext.Database.Migrate();

在Main.cs中设置DbContext

This EntityFrameworkCore issue说:

问题是,当EF调用CreateWebHostBuilderBuildWebHost时,它会在不运行Main的情况下执行此操作。 (这是故意的,因为EF需要构建模型并在不启动应用程序的情况下使用DbContext。)这意味着当EF调用这些方法时,静态IConfiguration属性仍为null - 因为它仅在Main中设置。因此,当EF调用其中一种方法时,您需要确保设置/处理IConfiguration,或者使用IDesignTimeDbContextFactory

这对我来说不是必需的,我猜是因为.Net Core 2 loads the configuration behind the scenes

将IDesignTimeDbContextFactory与环境变量一起使用

This EntityFrameworkCore issue说:

执行此操作的典型方法是在IDesignTimeDbContextFactory中读取文件,环境变量或类似内容。

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

在设计时创建DbContext

Microsoft documentation提到:

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

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

  • 从应用程序服务:作为启动项目的ASP.NET核心应用程序: 这些工具尝试从应用程序的服务提供者处获取DbContext对象。 [...]工具首先尝试通过调用Program.BuildWebHost() [JP:或CreateWebHostBuilder]并访问IWebHost.Services属性来获取服务提供者。 DbContext本身及其构造函数中的任何依赖项都需要在应用程序的服务提供程序中注册为服务。这可以通过在DbContext上使用构造函数来实现,该构造函数将DbContextOptions<TContext>的实例作为参数并使用AddDbContext<TContext>方法。
  • 使用没有参数的构造函数 如果无法从应用程序服务提供程序获取DbContext,则工具会在项目中查找派生的DbContext类型。然后他们尝试使用没有参数的构造函数创建实例。如果使用DbContext方法配置OnConfiguring,则这可以是默认构造函数。
  • 来自一家设计工厂 您还可以通过实现DbContext接口告诉工具如何创​​建IDesignTimeDbContextFactory<TContext>:如果在与派生的DbContext相同的项目中或在应用程序的启动项目中找到实现此接口的类,则这些工具会绕过创建DbContext并使用设计时工厂。

0
投票

当我在向dbcontext提供选项的同时将dbcontext添加到以下服务时,我遇到了同样的问题: -

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

然后我添加了dbcontext没有像下面这样的选项,它解决了我的问题

services.AddDbContext<TodoContext>();

我还必须将onConfiguring方法添加到dbcontext类,以便上下文可以访问连接字符串: -

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=IdenDB;Trusted_Connection=True;MultipleActiveResultSets=true");
}

我不确定这是否是正确的做事方式,因为我刚开始使用核心,但here是一个答案,可以更详细地解释这个问题

© www.soinside.com 2019 - 2024. All rights reserved.