配置 DbContext

本文展示的是使用 DbContextOptions 配置 DbContext 的模式。选项集(Options)主要是用来选择和配置数据存储的。

配置 DbContextOptions

DbContext 必须具有一个 DbContextOptions 的实例才能执行。这可以通过重写 OnConfiguring 来配置,或者通过构造方法参数由外部提供。

如果同时使用了两种方式,OnConfiguring 会基于已提供的选项集(options)被执行,这意味着 OnConfiguring 是成了附加的过程,可以在其中重写由构造方法参数获取的选项集。

构造方法参数

带构造方法的上下文类型代码:

  1. public class BloggingContext : DbContext
  2. {
  3. public BloggingContext(DbContextOptions<BloggingContext> options)
  4. : base(options)
  5. { }
  6. public DbSet<Blog> Blogs { get; set; }
  7. }

提示

DbContext 的基础构造方法还接受非泛型版本的 DbContextOptions。对于具有多个上下文类型的应用程序,不建议使用该非泛型版本。

从构造方法参数初始化上下文实例的应用程序代码:

  1. var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
  2. optionsBuilder.UseSqlite("Data Source=blog.db");
  3. using (var context = new BloggingContext(optionsBuilder.Options))
  4. {
  5. // 业务代码
  6. }

警告

OnConfiguring 比较迟被调用,因此可以在其中覆盖从DI或构造函数获得的选项值。该方法不适合用来测试(除非指向完整的数据库)。

OnConfiguring 的上下文类型代码:

  1. public class BloggingContext : DbContext
  2. {
  3. public DbSet<Blog> Blogs { get; set; }
  4. protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  5. {
  6. optionsBuilder.UseSqlite("Data Source=blog.db");
  7. }
  8. }

从初始化上下文实例的应用程序代码:

  1. using (var context = new BloggingContext())
  2. {
  3. // 业务代码
  4. }

通过依赖注入使用 DbContext

EF 支持通过依赖注入容器来使用 DbContext。可以使用 AddDbContext<TContext> 将你的 DbContext 类型添加到服务容器。

AddDbContext 将使得 DbContext 类型、TContext 以及 DbContextOptions<TContext> 都可以从服务容器注入获得。

查看后面的 阅读更多 可以深入了解依赖注入。

将 DbConext 添加到依赖注入:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddDbContext<BloggingContext>(options => options.UseSqlite("Data Source=blog.db"));
  4. }

这需要向 DbContext 类型中添加接受 DbContextOptions 类型的参数的构造方法。

上下文类型:

  1. public class BloggingContext : DbContext
  2. {
  3. public BloggingContext(DbContextOptions<BloggingContext> options)
  4. :base(options)
  5. { }
  6. public DbSet<Blog> Blogs { get; set; }
  7. }

(ASP.NET Core 中的)应用程序代码:

  1. public MyController(BloggingContext context)

(直接使用 ServiceProvider 的)应用程序代码:

  1. using (var context = serviceProvider.GetService<BloggingContext>())
  2. {
  3. // do stuff
  4. }
  5. var options = serviceProvider.GetService<DbContextOptions<BloggingContext>>();

使用 IDesignTimeDbContextFactory<TContext>

作为上述选项的替代,你还可以提供一个 IDesignTimeDbContextFactory<TContext> 的实现。EF 工具集能够使用该工厂来创建 DbContext 的实例。这可能是实现设计时特定的体验的要求,比如说数据迁移。

实现这个接口能够为没有公共默认构造方法的上下文类型启用设计时服务。设计时服务将自动发现与上下文实例同一程序集的该接口的实现。

例如:

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

阅读更多