前言

上一篇我们简单讲述了在EF Core1.1中如何进行迁移,本文我们来讲讲EF Core1.1中那些不为人知的事,细抠细节,从我做起。

显式创建DbContext实例

通过带OnConfiguring的构造函数

这个想必是我们最简单的方式了吧,通过调用继承自DbContext的类并且调用它的无参构造函数,同时我们需要谨记的时每当实例化时我们都需要将其释放也就是将其实例包裹在Using中。如下:

using (var context = new EFCoreContext())
{
}

接着通过重载OnConfiguring来配置EF Core上下文实例,如下。

public class EFCoreContext: DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(@"Server=.;Database=EFTest;Trusted_Connection=True;");
}

【注意】:重载OnConfiguring和之前EF版本中的OnModelCreating创建模型不一样,OnModelCreating创建模型上下文只实例化一次,但是OnConfiguring每实例化一个上下文时都会被调用一次,所以OnConfiguring能充分利用上下文中的构造函数或者其他数据。

在EF 6.x中对于上下文有许多构造函数,例如连接字符串传参,在EF Core 1.1中也是可以的如下:

public class EFCoreContext: DbContext
{
private readonly string _connectionString; public EFCoreContext(string connectionString)
{
_connectionString = connectionString;
} protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(_connectionString);
}

使用不带依赖注入的DbContextOptions

在DbContext的构造函数中我们可以接受一个DbContextOptions对象,这个主要用在当在DI容器中创建DbContext实例时会用到,当然它也能被显式调用,通过创建DbCOntextOptions对象来与上下文隔离,所以用它可以为每一个上下文的实例使用相同的options,如下:

    public class EFCoreContext : DbContext
{
public EFCoreContext(DbContextOptions options)
: base(options)
{
}
}
    public class HomeController : Controller
{
private static DbContextOptions _contextOptions; public IActionResult Index()
{
_contextOptions = new DbContextOptionsBuilder()
.UseSqlServer("")
.Options; using (var context = new EFCoreContext(_contextOptions))
{ } return View();
}
}

看到这里我们看到确确实实不再需要重载OnConfiguring,但是OnConfiguring将还是会被一直重载和调用,为什么会这样尼,因为我们在配置中注入上下文它会调用构造函数并同时来对OnConfiguring进行适当的调整。

使用依赖注入创建DbContext实例

我们只要在DI容器中注册上下文类型,然后它将被DI容器所解析,但是将上下文注册到DI容器中我们就不用管了吗,你还得注意到以下两点。我们一般将其注入到DI容器中是这样做的。

    public class EFCoreContext : DbContext
{
public EFCoreContext(DbContextOptions options)
: base(options)
{
}
}
            services.AddDbContext<EFCoreContext>(options =>
{
options.UseSqlServer(sqlStr, d => d.MigrationsAssembly("StudyEFCore"));
});

合情合理合法,但是为什么不能如下这样用尼

  services.AddSingleton<EFCoreContext>();

利用单例的形式注入难道就不行么,如果你这样做了,你就等着程序崩溃吧,因为上下文DbContext不是线程安全的,也就是说不能被注册到单例来使用没有额外的锁。接着就是在将其注入到DI容器后,当我们使用时还是用Using来包裹,你别以为注入到DI容器中就万事大吉它替你什么都做了,DI容器不会替你自动处理,当然了,如果你只是暂时在DI容器中使用的话,通常不会发生灾难。所以我们需要谨记如下两点。

(1)将上下文注入到DI容器中后,当使用DbContext依然还是用Using包括,因为DI容器不会自动将其释放。

(2)DbContext是非线程安全的,即使是在DI容器中,也无非保证不出问题,大部分情况下是不会有问题的,不要担心。

带有DbContextOptions的DI创建DbContext实例

我们在DI中注册一个DbContextOptions实例还是有点用,它只会被创建一次并作为单例使用。比如我们可以初始化数据啊,如下

    public class EFCoreContext : DbContext
{
public EFCoreContext(DbContextOptions options)
: base(options)
{
}
}
        private static IServiceProvider _serviceProvider;
public IActionResult Index()
{
var contextOptions = new DbContextOptionsBuilder()
.UseSqlServer("")
.Options; var services = new ServiceCollection()
.AddSingleton(contextOptions)
.AddScoped<EFCoreContext>(); _serviceProvider = services.BuildServiceProvider();
return View();
}

现在EFCoreContext上下文将会被DI容器解析,通过将DbContextOptions实例将被注入到它的构造函数中。这个_serviceProvider就是注入上下文的提供者,我们上述也说了可以初始化数据,如何初始化尼,来我们看看。在Startup.cs中有如下配置使用方法:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
....
}

这个app有如下属性:

发现什么没有,这个就是所有注入的服务的抽象属性,我们将其转换成EFCoreContext就可以在这个方法中初始化数据,我们看看。

        private static EFCoreContext context;
public static void Initialize(IServiceProvider serviceProvider)
{
context = (EFCoreContext )serviceProvider.GetService(typeof(EFCoreContext )); //do your something
}

使用泛型DbContextOptions创建DbContext实例

上述我们介绍的都是非泛型的DbContextOptions对象,如下:

     public class EFCoreContext : DbContext
{
public EFCoreContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.AddEntityConfigurationsFromAssembly(GetType().GetTypeInfo().Assembly);
}
}

但是其参数中的DbContextOptions还有一个泛型版本,那么泛型是用来干嘛的了,我们先看如下例子:

    public class EFCoreContext1 : DbContext
{
public EFCoreContext1text1(DbContextOptions<EFCoreContext1> options)
: base(options)
{
}
} public class EFCoreContext2 : DbContext
{
public EFCoreContext2(DbContextOptions<EFCoreContext2> options)
: base(options)
{
}
} var contextOptions1 = new DbContextOptionsBuilder<EFCoreContext1>()
.UseSqlServer(connectionString1)
.Options; var contextOptions2 = new DbContextOptionsBuilder<EFCoreContext2>()
.UseSqlServer(connectionString2)
.Options; var services = new ServiceCollection()
.AddSingleton(contextOptions1)
.AddScoped<EFCoreContext1>()
.AddSingleton(contextOptions2)
.AddScoped<EFCoreContext2>(); _serviceProvider = services.BuildServiceProvider();

看到什么没有,如果有多个上下文类型在DI容器中注册时我们可以允许每个上下文的类型都依赖于自己的Options。当解析EFCoreContext1时将会导致DbContextOptions<EFCoreContext1>会被注入,同理当解析EFCoreContext2时将导致DbContextOptions<EFCoreContext2>会被注入。

使用AddDbContext来创建DbContext实例

通过AddDbContext语法糖来注册DbContext和DbContextOptions实例。如下:

var services = new ServiceCollection()
.AddDbContext<EFCoreContext>(
b => b.UseSqlServer(connectionString));

默认情况下将EFCoreContext作为scope进行注册,将DbContextOptions作为单例进行注册,你可更改将EFCoreContext作为单例注册,上述我们已经讨论过这个问题了啊。好了到了这里想必我们知道创建EF Core上下文实例的几种方式了吧,我们概括为以下三点。

(1)直接调用上下文构造函数并重载OnConfiguring创建上下文实例。

(2)传递DbContextOptions到构造函数中创建上下文实例。

(3)通过DI容器来创建上下文实例。

使用DbContextOptionsBuilder来配置一个DbContext并最终构造一个DbContextOptions对象,这也能够通过重载OnConfiguring方法或者通过构造options来传递到DbContext的构造函数中去,无论是通过无参构造函数还是通过DbContextOptions传递到上下文的构造函数中去,抑或是通过将DbContext注入到DI容器中去都是一样的,都没有什么本质区别,只不过通过DI简便一点而且逼格比较高而已,没有其他。

总结

好了,本节我们对于EF Core 1.1中创建上下文的几种方式都已叙述完毕,你是否已经Understand呢,晚安,世界,又熬夜了。

EntityFramework Core 1.1是如何创建DbContext实例的呢?的更多相关文章

  1. [.NET Core] - 使用 EF Core 的 Scaffold-DbContext 脚手架命令创建 DbContext

    Scaffold-DbContext 命令 参数 Scaffold-DbContext [-Connection] <String> [-Provider] <String> ...

  2. EntityFramework Core 3.x上下文构造函数可以注入实例呢?

    前言 今天讨论的话题来自一位微信好友遇到问题后请求我的帮助,当然他的意图并不是本文标题,只是我将其根本原因进行了一个概括,接下来我们一起来探索标题的问号最终的答案是怎样的呢? 上下文构造函数是否可以注 ...

  3. 非构造函数方式创建DbContext实例的方法

    using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Design;using Microsoft.Entit ...

  4. [Abp vNext 源码分析] - 14. EntityFramework Core 的集成

    一.简要介绍 在以前的文章里面,我们介绍了 ABP vNext 在 DDD 模块定义了仓储的接口定义和基本实现.本章将会介绍,ABP vNext 是如何将 EntityFramework Core 框 ...

  5. EntityFramework Core上下文实例池原理分析

    前言 无论是在我个人博客还是著作中,对于上下文实例池都只是通过大量文字描述来讲解其基本原理,而且也是浅尝辄止,导致我们对其认识仍是一知半解,本文我们摆源码,从源头开始分析.希望通过本文从源码的分析,我 ...

  6. EntityFramework Core如何映射动态模型?

    前言 本文我们来探讨下映射动态模型的几种方式,相信一部分童鞋项目有这样的需求,比如每天/每小时等生成一张表,此种动态模型映射非常常见,经我摸索,这里给出每一步详细思路,希望能帮助到没有任何头绪的童鞋, ...

  7. 【EFCore】利用Entityframework Core创建数据库模型

    利用Entityframework Core创建数据库模型 本文中Entityframework Core版本为v3.1.6 简介 Entity Framework (EF) Core 是微软轻量化. ...

  8. .NET Core之Entity Framework Core 你如何创建 DbContext

    本文版权归博客园和作者吴双共同所有,欢迎转载,转载和爬虫请注明博客园蜗牛原文地址 http://www.cnblogs.com/tdws/p/5874212.html. 目前国内各大论坛,各位大牛的分 ...

  9. [转].NET Core之Entity Framework Core 你如何创建 DbContext

    本文转自:http://www.cnblogs.com/tdws/p/5874212.html 本文版权归博客园和作者吴双共同所有,欢迎转载,转载和爬虫请注明博客园蜗牛原文地址 http://www. ...

随机推荐

  1. rnandroid环境搭建

    react-native 环境搭建具体步骤这个大家已经玩烂了,这个主要是记录下来自己做win7系统遇到的坑 1.com.android.ddmlib.installexception 遇到这个问题,在 ...

  2. shell变量

    定义变量 定义变量时,变量名不加美元符号($),如: variableName="value" 注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样.同时,变量名 ...

  3. [APUE]标准IO库(上)

    一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...

  4. JavaScript基础知识总结(四)

    JavaScript语法 八.函数 函数就是完成某个功能的一组语句,函数由关键字function + 函数名 + 加一组参数定义: 函数在定义后可以被重复调用,通常将常用的功能写成一个函数,利用函数可 ...

  5. VB.NET设置控件和窗体的显示级别

    前言:在用VB.NET开发射频检测系统ADS时,当激活已存在的目标MDI子窗体时,被其他子窗体遮住了,导致目标MDI子窗体不能显示. 这个问题怎么解决呢?网上看到一篇帖子VB.NET设置控件和窗体的显 ...

  6. Postman - 功能强大的 API 接口请求调试和管理工具

    Postman 是一款功能强大的的 Chrome 应用,可以便捷的调试接口.前端开发人员在开发或者调试 Web 程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的 Fi ...

  7. CentOS7之按时间段截取指定的Tomcat日志到指定文件的方法

    CentOS7之按时间段截取指定的Tomcat日志到指定文件的方法 sed -n '/2016-11-02 15:00:/,/2016-11-02 15:05:/p' catalina.out > ...

  8. JAVA代码验证身份证信息

    java验证身份证信息代码 转自:http://www.blogjava.net/xylz/archive/2011/01/05/342330.html import java.util.Calend ...

  9. 工大助手(C#与python交互)

    工大助手(爬虫--C#与python交互) 基本内容 工大助手(桌面版) 实现登陆.查成绩.计算加权平均分等功能 团队人员 13070046 孙宇辰 13070003 张帆 13070004 崔巍 1 ...

  10. Vue.js——60分钟webpack项目模板快速入门

    概述 browserify是一个 CommonJS风格的模块管理和打包工具,上一篇我们简单地介绍了Vue.js官方基于browserify构筑的一套开发模板.webpack提供了和browserify ...