设计时 DbContext 创建Design-time DbContext Creation

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

工具可通过多种方式来创建 DbContext

从应用程序服务From application services

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

工具首先尝试通过调用 Program.CreateHostBuilder() 、调用 Build() ,然后访问属性来获取服务提供程序 Services

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. => CreateHostBuilder(args).Build().Run();
  5. // EF Core uses this method at design time to access the DbContext
  6. public static IHostBuilder CreateHostBuilder(string[] args)
  7. => Host.CreateDefaultBuilder(args)
  8. .ConfigureWebHostDefaults(
  9. webBuilder => webBuilder.UseStartup<Startup>());
  10. }
  11. public class Startup
  12. {
  13. public void ConfigureServices(IServiceCollection services)
  14. => services.AddDbContext<ApplicationDbContext>();
  15. }
  16. public class ApplicationDbContext : DbContext
  17. {
  18. public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
  19. : base(options)
  20. {
  21. }
  22. }

备注

创建新的 ASP.NET Core 应用程序时,默认情况下会包括此挂接。

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

使用不带参数的构造函数Using a constructor with no parameters

如果无法从应用程序服务提供程序获得 DbContext,则工具将查找 DbContext 项目中的派生类型。 然后,它们尝试使用不带参数的构造函数创建实例。 如果使用方法配置,则这可能是默认构造函数 DbContext OnConfiguring

从设计时工厂From a design-time factory

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

  1. using Microsoft.EntityFrameworkCore;
  2. using Microsoft.EntityFrameworkCore.Design;
  3. using Microsoft.EntityFrameworkCore.Infrastructure;
  4. namespace MyProject
  5. {
  6. public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
  7. {
  8. public BloggingContext CreateDbContext(string[] args)
  9. {
  10. var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
  11. optionsBuilder.UseSqlite("Data Source=blog.db");
  12. return new BloggingContext(optionsBuilder.Options);
  13. }
  14. }
  15. }

备注

在 EFCore 5.0 之前, args 未使用参数(请参阅此问题)。 这在 EFCore 5.0 中是固定的,任何其他设计时参数都将通过该参数传递到应用程序。

如果需要以不同于运行时的方式配置 DbContext 的设计时,则设计时工厂特别有用 DbContext 。如果构造函数采用其他参数,但未在 di 中注册,如果根本不使用 di,或者出于某种原因而不是使用 BuildWebHost ASP.NET Core 应用程序的类中的方法 Main