前言

上一篇我们简单讲述了在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. 动画requestAnimationFrame

    前言 在研究canvas的2D pixi.js库的时候,其动画的刷新都用requestAnimationFrame替代了setTimeout 或 setInterval 但是jQuery中还是采用了s ...

  2. ArcGIS 10.0紧凑型切片读写方法

    首先介绍一下ArcGIS10.0的缓存机制: 切片方案 切片方案包括缓存的比例级别.切片尺寸和切片原点.这些属性定义缓存边界的存在位置,在某些客户端中叠加缓存时匹配这些属性十分重要.图像格式和抗锯齿等 ...

  3. 我为Net狂 ~ 社交平台系列小集合!

    微信平台: 我为Net狂(dotNetCrazy) 资源贴吧: http://tieba.baidu.com/f?kw=毒逆天 个人博客: http://dunitian.cnblogs.com/ h ...

  4. 06.SQLServer性能优化之---数据库级日记监控

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 之前说了一下数据库怎么发邮件:http://www.cnblogs.com/duniti ...

  5. Android 问题汇总(持续更新)

    Q1:Error:(93, 12) 错误: 需要常量表达式 问题描述:这个问题是在添加一个module到项目中时遇到的,主要原因是因为原来module中的R文件是不会以final形式存在的,但是在mo ...

  6. C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)

    第一次接触HtmlAgilityPack是在5年前,一些意外,让我从技术部门临时调到销售部门,负责建立一些流程和寻找潜在客户,最后在阿里巴巴找到了很多客户信息,非常全面,刚开始是手动复制到Excel, ...

  7. 【NLP】十分钟快览自然语言处理学习总结

    十分钟学习自然语言处理概述 作者:白宁超 2016年9月23日00:24:12 摘要:近来自然语言处理行业发展朝气蓬勃,市场应用广泛.笔者学习以来写了不少文章,文章深度层次不一,今天因为某种需要,将文 ...

  8. PHP获取上个月最后一天的一个容易忽略的问题

    正常来说,PHP是有一个很方便的函数可以获取上个月时间的 strtotime (PHP 4, PHP 5, PHP 7) strtotime - 将任何英文文本的日期时间描述解析为 Unix 时间戳 ...

  9. spring boot 实战:我们的第一款开源软件

    在信息爆炸时代,如何避免持续性信息过剩,使自己变得专注而不是被纷繁的信息所累?每天会看到各种各样的新闻,各种新潮的技术层出不穷,如何筛选出自己所关心的? 各位看官会想,我们是来看开源软件的,你给我扯什 ...

  10. Toast显示图文界面——Android开发之路1

    Toast的多种使用方法 Toast其实是一个功能特别强大的组件,不仅仅可以吐司一个文本内容,还可以吐司图片以及图文混排的界面.具体用法如下: 第一种:简单的纯文本内容的吐司: Toast.makeT ...