设计时 DbContext 创建

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

可通过多种方式尝试创建 DbContext工具。 如果找到, IDesignTimeDbContextFactory<TContext> 则工具会使用它而不是其他创建模式。 设计时工厂是 针对单独的迁移项目 和启动项目特定于平台的应用程序的建议模式。

从应用程序服务

如果启动项目使用 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 及其构造函数中的任何依赖项都需要在应用程序的服务提供商中注册为服务。 这可以通过在DbContext上创建一个构造函数,该构造函数将DbContextOptions<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);
    }
}

如果上下文构造函数具有未在 DI 中注册的依赖项、未使用 DI,或者工具无法执行应用程序启动项目,则设计时工厂尤其有用。

在运行时应用程序在设计时配置相同的提供程序、模型选项和迁移程序集。 否则,这些工具可以为与应用程序使用的模型不同的模型搭建基架迁移。 不要假定存在可选的命令行参数;验证参数并提供合适的开发默认源或配置源。

Args

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

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

dotnet ef database update -- --environment Production

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