多种方式创建 Entity Framework Core 上下文

作者 | 喵叔

责编 | 刘静

出品 | CSDN(ID:CSDNnews)

我们在利用 Entity Framework Core 创建上下文实例的时候往往都是调用构造函数并重载 OnConfiguring 方法,这是 Entity Framework Core 默认的常用的创建上下文实例的方式。除了这种方式,微软也为我们准备了其他两种创建上下文实例的方式。算上常用的方式微软一共提供了三种创建上下文实例的方式,分别是:

  1. 直接调用上下文无参构造函数并重载 OnConfiguring 方法;

  2. 继承自上下文基类 DbContext 并传递 DbContextOptions 到上下文构造函数中;

  3. 使用依赖注入创建上下文实例。

上述三种方式总结起来就是两种创建上下文实例的方式,分别是 显示创建 和 通过依赖注入容器创建 。下面我分别来讲解这两种创建上下文实例的方式。

显示创建上下文实例

显示创建上下文实例是 Entity Framework Core 中常用的方式,当我们不需要通过依赖注入方式创建上下文实例的话就可以通过这种方式创建。

显示创建上下文实例最简单的方法是通过创建一个派生自 DbContext 的类,并且调用它的无参构造函数。代码如下:

public class EFContext : DbContext
{
    public EFContext(DbContextOptions options)
        :base(options)
    {
    }
}

上述代码在运行时每次创建一个新的上下文实例都会调用 OnConfiguring 方法,这样我们可以通过利用 OnConfiguring 使用传递给上下文构造器或者其他实例的参数。这里需要注意的是每次调用上下文实例就必须使用 using 语句进行处理,也就是释放调用。

在 Entity Framework Core 中我们可以为每个上下文实例使用相同的 DbContextOptions 对象,这是因为 DbContext 构造函数可以接受 DbContextOptions 对象,它可以被显示调用可以通过它来隔离上下文。代码如下:

public class EFContext : DbContext
{
    public EFContext(DbContextOptions options)
        :base(options)
    {
    }
}
class Program
{
    private static IServiceProvider serviceProvider;
    static void Main(string[] args)
    {
        DbContextOptions context = new DbContextOptionsBuilder()
            .UseSqlServer("数据库连接字符串")
            .Options;
        var services = new ServiceCollection()
            .AddSingleton(context)
            .AddScoped<EFContext>();
        serviceProvider = services.BuildServiceProvider();
    }
}

上述代码中并没有进行重载 OnConfiguring 方法,但是在代码运行时 OnConfiguring 会被调用和重载,这时因为在进行注入上下文的时候会调用构造函数,还会对 OnConfiguring 进行调整。

依赖注入创建上下文实例

依赖注入上下文实例的方式有四种,分别是带无参构造函数的注入、带 DbContextOptions 实例的构造函数注入、使用泛型 DbContextOptions 注入和使用 AddDbContext 或 AddDbContextPool 注入。下面我分别来讲一讲。

1. 使用带无参构造函数的注入
DbContext 上下文派生类可以有一个无参数的构造函数并覆盖OnConfiguring方法。这样上下文类就没有任何依赖关系,这样除了上下文类型本身之外,其他任何内容都不需要在容器中注册。

2. 使用带 DbContextOptions 实例的构造函数注入
有时候需要在注入容器中注册 DbContextOptions 实例,将其注册为单例即可,这时我们只需要创建一次。下面我们以使用 DependencyInjection 为例来讲解一下,DependencyInjection 位于 Microsoft.Extensions.DependencyInjection 包中。代码如下:

public class EFContext : DbContext
{
    public EFContext(DbContextOptions options)
        :base(options)
    {
    }
}
class Program
{
    private static IServiceProvider serviceProvider;
    static void Main(string[] args)
    {
        DbContextOptions context = new DbContextOptionsBuilder()
            .UseSqlServer("数据库连接字符串")
            .Options;
        var services = new ServiceCollection()
            .AddSingleton(context)
            .AddScoped<EFContext>();
        serviceProvider = services.BuildServiceProvider();
    }
}

上述代码中通过 serviceProvider 将上下文注入容器中,DbContextOptions 实例也被注入到了构造函数中。

1. 使用泛型 DbContextOptions 注入
有时我们需要注册多个 DbContext 上下文类,这时我们就可以使用泛型 DbContextOptions,代码如下:

class Program
{
    private static IServiceProvider serviceProvider;
    static void Main(string[] args)
    {
        DbContextOptions context1 = new DbContextOptionsBuilder()
            .UseSqlServer("数据库连接字符串1")
            .Options;
        DbContextOptions context2 = new DbContextOptionsBuilder()
            .UseSqlServer("数据库连接字符串2")
            .Options;
        var services = new ServiceCollection()
            .AddSingleton(context1)
            .AddScoped<EFContext1>()
            .AddSingleton(context2)
            .AddScoped<EFContext2>();
        serviceProvider = services.BuildServiceProvider();
    }
}

代码在运行时会按照顺序逐个注入,也是是说当代码解析到 EFContext1 时会注入 DbContextOptions<EFContext1>,解析到 EFContext2 时会注入 DbContextOptions<EFCoreDbContext2>

1. 使用 AddDbContext 或 AddDbContextPool 注入
使用 AddDbContext 或 AddDbContextPool 注入比较简单,只需要短短的几行代码即可:

static void Main(string[] args)
{
    var services = new ServiceCollection()
         .AddDbContext<EFContext>(p => p.UseSqlServer("数据库连接字符串"));
}

我们将 EFCoreDbContext 注册为 Scope,并将 DbContextOptions<EFCoreDbContext> 通过委托构建为单例。委托继续使用与 OnConfiguring 中相同的 DbContextOptionsBuilder。Scope 是默认的注册类型,如果不想注册为 Scope 可以通过向 AddDbContext 传参来更高,但是要注意的是因为DbContext非线程安全,因此不可传递 Singleton。

总结

通过上面的讲解你应该了解了创建上下文实例的方式,不过是普通方式和通过注入的方式在大型的项目中必须通过充分的研究再决定使用哪种方式,因为这两种方式在不同的环境下都有可能引起性能问题。另外还需要注意上下文实例在使用之后必须进行释放处理,另外上下文实例可以被注入为 Scoped 类型和 Transient 类型,但是唯独不能注入为 Singleton 类型,因为 DbContext上下文是非线程安全的。

作者简介:朱钢,笔名喵叔,CSDN博客专家,.NET高级开发工程师,7年一线开发经验,参与过电子政务系统和AI客服系统的开发,以及互联网招聘网站的架构设计,目前就职于北京恒创融慧科技发展有限公司,从事企业级安全监控系统的开发。

声明:本文系作者独立观点,不代表CSDN立场。

【END】

这四个Python项目,让你很快读懂Python!

https://edu.csdn.net/topic/python115?utm_source=csdn_bw

热 文 推 荐 

So easy!10 行代码写个“让你惊叹”的文章生成器 | 原力计划

31 岁的我为何会在创业成功后选择编程?

 微信推出“腾讯QQ”小程序;马化腾又要发红包;GitLab 12.5 稳定版发布| 极客头条

Facebook 与 Twitter 再曝漏洞!用户数据再次被共享?

Java 开发者最困惑的四件事

华为荣耀首款双模 5G 手机来了!

倪光南:中国 5G 有望成为世界第一

微信几亿人在线的点赞、取消点赞系统,用Redis如何实现?

量子算命,在线掷筊:一个IBM量子云计算机的应用实践,代码都有了

从黑客文化看区块链开源社区的自我组织与成功之道

 点击阅读原文,参加中国开发者现状调查!

你点的每个“在看”,我都认真当成了喜欢

C#/.Net企业级系统架构设计实战精讲教程

12-03
课程通过实际项目融入常用开发技术架构,讲授风格独特,提供详细上课日志及答疑,赠送配套的项目架构源码注释详细清晰且表达通俗,均能直接在实际项目中应用,正真的物超所值,价格实惠 任务作业: 综合运用《C#/.Net企业级系统架构设计实战精讲教程》课程所学知识技能设计一个学生成绩管理系统的架构。要求: 1.系统基于MVC的三层架构,各层单独建不同的解决方案文件夹。 2.采用Model First开发方式,设计架构时只需要设计学生表(TbStudent)和课程表(TbCourse)。学生表必须有的字段是ID、stuName、age;课程表必须有的字段是ID、courseName、content。 3.数据访问层采用Entity Framework或NHibernate来实现,必须封装对上述表的增删改查方法。 4.必须依赖接口编程,也就是必须要有数据访问层的接口层、业务逻辑层的接口层等接口层。层层之间必须减少依赖,可以通过简单工厂或抽象工厂。 5.至少采用简单工厂、抽象工厂、Spring.Net等技术中的2种来减少层与层之间的依赖等。 6.封装出DbSession类,让它拥有所有Dal层实例和SaveChanges方法。 7.设计出数据访问层及业务逻辑层主要类的T4模板,以便实体增加时自动生成相应的类。 8.表现层要设计相关的控制器和视图来验证设计的系统架构代码的正确性,必须含有验证增删改查的方法。 9.开发平台一定要是Visual Studio平台,采用C#开发语言,数据库为SQL Server。 10.提交整个系统架构的源文件及生成的数据库文件。 (注意: 作业需写在CSDN博客中,请把作业链接贴在评论区,老师会定期逐个批改~~)
©️2020 CSDN 皮肤主题: 代码科技 设计师: Amelia_0503 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值