设计时 DbContext 创建

某些 EF Core Tools 命令(例如 Migrations 命令)要求在设计时创建派生的 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)    {    }}

 备注

创建新的 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);    }}

 备注

在 EFCore 5.0 args 之前,参数未使用 (看到 此问题) 。这在 EFCore 5.0 中得到修复,任何额外的设计时参数都通过该参数传递到应用程序中。

如果需要在设计时以不同于运行时的方式配置 DbContext,如果 DbContext 构造函数采用未在 DI 中注册的附加参数,如果你根本不使用 DI,或者如果你出于某种原因不希望在 ASP.NET Core 应用程序的 Main 类中使用 CreateHostBuilder 方法,则设计时工厂可能特别有用。

Args

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

dotnet ef database update -- --environment Production

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