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

vos*_*d01 7 c# dependency-injection dbcontext entity-framework-core .net-core

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

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

例如,以下内容将使用从中检索的连接字符串将EF配置为持久保存到SQL Server config.json

ServiceCollection services = ...

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

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

迁移可制成通过覆盖工作OnConfiguring的内DbContext子类来指定供应商和配置字符串,但在不同的配置是其他地方所期望的方式获得.最终保持我的迁移命令和我的代码都工作变得非常复杂.

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

Sor*_*ren 8

使用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

适用于实体框架2.0、2.1


现在使用IDbContextFactory<TContext> 已经过时了

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

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这个类现在已经过时了。 (2认同)

Mik*_*Mik 7

如果您正在寻找为 imgrations 配置 cotext 的解决方案,您可以在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(connectionString);
        }
    }
Run Code Online (Sandbox Code Playgroud)

记得安装这两个包来拥有SetBasePathAddJsonFile方法: Microsoft.Extensions.Configuration.FileExtensions

Microsoft.Extensions.Configuration.Json


vos*_*d01 6

正如@bricelam 所评论的,Entity Framework 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>" );
    }
}
Run Code Online (Sandbox Code Playgroud)

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() );
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

  • 您可以检查 optionsBuilder.IsConfigured 属性而不是 isMigration 标志。 (3认同)