在Entity Framework Core中创建迁移时如何配置DbContext?

时间:2015-03-17 21:41:08

标签: c# dependency-injection .net-core entity-framework-core dbcontext

使用Entity Framework的迁移命令时,是否可以配置/引导依赖注入?

Entity Framework Core支持DbContext子类的依赖注入。此机制包括允许在DbContext之外配置数据访问。

例如,以下内容将使用从config.json

检索的连接字符串将EF配置为持久保存到SQL Server
ServiceCollection services = ...

var configuration = new Configuration().AddJsonFile( "config.json" );
services.AddEntityFramework( configuration )
    .AddSqlServer()
    .AddDbContext<BillingDbContext>( config => config.UseSqlServer() );

但是,迁移命令不知道执行此代码,因此Add-Migration因缺少提供程序或缺少连接字符串而失败。

通过覆盖OnConfiguring子类中的DbContext来指定提供程序和配置字符串,可以使迁移工作,但是当其他地方需要不同的配置时,这会妨碍。最终保持我的迁移命令和我的代码都工作变得非常复杂。

注意:我的DbContext与使用它的入口点位于不同的程序集中,我的解决方案有多个启动项目。

7 个答案:

答案 0 :(得分:4)

正如@bricelam所述,实体框架7中尚不存在此功能.GitHub问题aspnet/EntityFramework#639

跟踪此缺失的功能

与此同时,我发现更简单的解决方法是利用全局状态而不是使用子类化。通常不是我的第一个设计选择,但它现在运作良好。

在MyDbContext中:

public static bool isMigration = true;

protected override void OnConfiguring( DbContextOptionsBuilder optionsBuilder )
{
    // TODO: This is messy, but needed for migrations.
    // See https://github.com/aspnet/EntityFramework/issues/639
    if ( isMigration )
    {
        optionsBuilder.UseSqlServer( "<Your Connection String Here>" );
    }
}

Startup.ConfigureServices()

public IServiceProvider ConfigureServices( IServiceCollection services )
{
    MyContext.isMigration = false;

    var configuration = new Configuration().AddJsonFile( "config.json" );
    services.AddEntityFramework( configuration )
        .AddSqlServer()
        .AddDbContext<MyDbContext>( config => config.UseSqlServer() );
    // ...
}

(在我的情况下,配置代码实际上存在于Autofac模块中。)

答案 1 :(得分:2)

使用IDesignTimeDbContextFactory

如果在与派生DbContext相同的项目中或在应用程序的启动项目中找到实现此接口的类,则这些工具会绕过创建DbContext的其他方法,改为使用设计时工厂。

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace MyProject
{
    public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
    {
        public BloggingContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
            optionsBuilder.UseSqlite("Data Source=blog.db");

            return new BloggingContext(optionsBuilder.Options);
        }
    }
}

在Entity Framework 2.0,2.1中应用

现在使用IDbContextFactory<TContext> obsolete

实现此接口以为没有公共默认构造函数的上下文类型启用设计时服务。设计时服务将自动发现与派生上下文在同一程序集中的此接口的实现。

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace MyProject
{
    public class BloggingContextFactory : IDbContextFactory<BloggingContext>
    {
        public BloggingContext Create()
        {
            var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
            optionsBuilder.UseSqlServer("connection_string");

            return new BloggingContext(optionsBuilder.Options);
        }
    }
}

更多信息:https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext

如果您对硬编码的连接字符串不满意,请查看this文章。

答案 2 :(得分:1)

结合上面的答案,这对我有用

private readonly bool isMigration = false;
public MyContext()
{
    isMigration = true;
}

public MyContext(DbContextOptions<MyContext> options) : base(options)
{

}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (isMigration)
    {
        optionsBuilder.UseSqlServer("CONNECTION_STRING");
    }
}

答案 3 :(得分:1)

在.NET Core中,应使用自2.1版以来的IDesignTimeDbContextFactory,因为IDbContextFactory已过时。

public class FooDbContextFactory : IDesignTimeDbContextFactory<FooDbContext>
{
    public FooDbContext CreateDbContext(string[] args)
    {
        IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();

        var builder = new DbContextOptionsBuilder<FooDbContext>();
        var connectionString = configuration.GetConnectionString("ConnectionStringName");
        builder.UseSqlServer(connectionString);

        return new FooDbContext(builder.Options);
    }
}

答案 4 :(得分:0)

我知道这是一个老问题,但我使用了onConfiguring方法而且我没有遇到这个问题

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(Startup.Configuration.Get("Data:DefaultConnection:ConnectionString"));
}

答案 5 :(得分:0)

我只是要求一个实例并在我的Startup.cs文件中运行迁移

  public void ConfigureServices(IServiceCollection services)
    {
        // ASPNet Core Identity
        services.AddDbContext<RRIdentityDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("RRIdentityConnectionString")));

     }

然后在配置中:

   public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        var rrIdentityContext = app.ApplicationServices.GetService<RRIdentityDbContext>();
        rrIdentityContext.Database.Migrate();
    }

注意:没有&#39; EnsureCreated&#39;对于数据库。迁移应该创建它,如果它不存在,虽然它应该如何计算出我不知道的权限 - 所以我创建了一个空的数据库。

答案 6 :(得分:0)

如果您正在寻找为imgrations配置共文本的解决方案,则可以在DBContext类中使用它:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            IConfigurationRoot configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .Build();
            var connectionString = configuration.GetConnectionString("DbCoreConnectionString");
            optionsBuilder.UseSqlServer("Data Source=localhost;Initial Catalog=aspnetcore;Integrated Security=True");
        }
    }

请记住要安装这两个软件包以具有SetBasePathAddJsonFile方法: Microsoft.Extensions.Configuration.FileExtensions

Microsoft.Extensions.Configuration.Json