设计时 DbContext 创建

某些 EF Core Tools 命令(例如 迁移 命令)要求在设计时创建派生 DbContext 实例,以便收集有关应用程序的实体类型及其映射到数据库架构的详细信息。 在大多数情况下, DbContext 最好以类似于 运行时配置创建的配置方式。

工具尝试创建 DbContext以下各项的方法有多种:

从应用程序服务

如果启动项目使用 ASP.NET Core Web 主机.NET Core 泛型主机,这些工具将尝试从应用程序的服务提供商获取 DbContext 对象。

这些工具首先尝试通过调用 Program.CreateHostBuilder()、调用 Build()、访问 Services 属性来获取服务提供商。

public class Program
{
    public static void Main(string[] args)
        => CreateHostBuilder(args).Build().Run();

    // EF Core uses this method at design time to access the DbContext
    public static IHostBuilder CreateHostBuilder(string[] args)
        => Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(
                webBuilder => webBuilder.UseStartup<Startup>());
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
        => services.AddDbContext<ApplicationDbContext>();

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
}

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

Note

创建新的 ASP.NET Core 应用程序时,默认包含此挂钩。

自身 DbContext 及其构造函数中的任何依赖项都需要在应用程序的服务提供商中注册为服务。 这可以通过在采用参数实例DbContextOptions<TContext>并使用该方法的构造函数上DbContext轻松实现。AddDbContext<TContext>

使用没有参数的构造函数

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

从设计时工厂

还可以通过实现 Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory<TContext> 接口来告知工具如何创建 DbContext:如果在派生 DbContext 项目或应用程序启动项目中的同一项目中找到了实现此接口的类,则工具将绕过创建 DbContext 的其他方法,并改用设计时工厂。

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);
    }
}

如果需要 DbContext 在设计时配置与运行时不同的设计时间,如果 DbContext 构造函数未在 DI 中注册其他参数、根本不使用 DI,或者出于某种原因, CreateHostBuilder 你不希望在 ASP.NET Core 应用程序的 Main 类中使用方法,则设计时工厂尤其有用。

Args

同时IDesignTimeDbContextFactory<TContext>.CreateDbContextProgram.CreateHostBuilder接受命令行参数。

可以从工具中指定这些参数:

dotnet ef database update -- --environment Production

-- 标记指示 dotnet ef 将后面的所有内容都视为参数,而不要试图将它们解析为选项。 dotnet ef 未使用的任何额外参数都会转发到应用。