[EF Core]设计时DbContext
[文章内容来源于Microsoft Doc ]
某些EF Core 工具命令(如迁移)需要在设计时创建一个派生DbContext
实例,以便收集有关该应用程序的实体类型及其如何映射到数据库架构的详细信息。
设计时 DbContext 配置
配置 DbContextOptions
DbContext
必须具有 DbContextOptions
的实例才能执行工作。
DbContextOptions实例包含如下配置:
- 数据库提供程序 ,通常通过调用方法(UseSqlServer或者UseSqlite)进行选择。
- 必须的数据库实例连接字符串或标识符,通常通过参数传递到上面的提供者选择方法。
- 提供程序级别的可选行为选择器。
- EF Core 行为选择器
配置示例如下:
optionsBuilder .UseSqlServer(connectionString, providerOptions=>providerOptions.CommandTimeout(60)) .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
配置DbContextOptions根据DbContext的构造函数有没有参数分两种类型:构造函数传参设置,重写OnConfiguring方法设置。
-
构造函数参数
有参构造函数,利用参数将DbContextOptions传递到DbContext
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class BloggingContext : DbContext 2 { 3 public BloggingContext(DbContextOptions<BloggingContext> options) 4 : base(options) 5 { } 6 7 public DbSet<Blog> Blogs { get; set; } 8 }
-
OnConfiguring
无参构造函数,重写OnConfiguring方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class BloggingContext : DbContext 2 { 3 public DbSet<Blog> Blogs { get; set; } 4 5 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 6 { 7 optionsBuilder.UseSqlite("Data Source=blog.db"); 8 } 9 }
设计时 DbContext 创建
迁移工具有多种方式创建设计时DbContext:
- 从应用程序服务创建。
- 使用不带参数的构造函数创建。
- 从设计时工厂创建。
-
从应用程序服务创建
如果启动项目使用ASP.NET Core Web 主机或.Net Core 泛型主机,则这些工具将尝试从应用程序的服务提供程序获取 DbContext 对象。
工具首先尝试通过调用Program.CreateHostBuilder()
、调用Build()
,然后访问Services
属性来获取服务提供程序。DbContext
及其构造函数中的任何依赖项都需要在应用程序的服务提供程序中注册为服务。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Program 2 { 3 public static void Main(string[] args) 4 => CreateHostBuilder(args).Build().Run(); 5 6 // EF Core uses this method at design time to access the DbContext 7 public static IHostBuilder CreateHostBuilder(string[] args) 8 => Host.CreateDefaultBuilder(args) 9 .ConfigureWebHostDefaults( 10 webBuilder => webBuilder.UseStartup<Startup>()); 11 } 12 13 public class Startup 14 { 15 public void ConfigureServices(IServiceCollection services) 16 => services.AddDbContext<ApplicationDbContext>(); 17 } 18 19 public class ApplicationDbContext : DbContext 20 { 21 public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) 22 : base(options) 23 { 24 } 25 }
-
使用不带参数的构造函数创建
如果无法从应用程序服务提供程序获得 DbContext,则工具将查找项目中的DbContext
派生类型。 然后,它们尝试使用不带参数的构造函数创建实例。该方式需要DbContext重写OnConfiguring方法,在该方法中配置DbContextOptions。
-
从设计时工厂创建
通过实现IDesignTimeDbContextFactory<TContext>
接口来告诉工具如何创建 DbContext:如果在与派生DbContext
的项目相同的项目中或在应用程序的启动项目中找到了实现此接口的类,则这些工具将绕过创建 DbContext 的其他方法并改用设计时工厂。如果需要以不同于运行时的方式配置 DbContext 的设计时, DbContext
则设计时工厂特别有用。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using Microsoft.EntityFrameworkCore; 2 using Microsoft.EntityFrameworkCore.Design; 3 using Microsoft.EntityFrameworkCore.Infrastructure; 4 5 namespace MyProject 6 { 7 public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext> 8 { 9 public BloggingContext CreateDbContext(string[] args) 10 { 11 var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>(); 12 optionsBuilder.UseSqlite("Data Source=blog.db"); 13 14 return new BloggingContext(optionsBuilder.Options); 15 } 16 } 17 }