前言

上一篇我们简单讲述了在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. HTTPS 互联网世界的安全基础

    近一年公司在努力推进全站的 HTTPS 化,作为负责应用系统的我们,在配合这个趋势的过程中,顺便也就想去搞清楚 HTTP 后面的这个 S 到底是个什么含义?有什么作用?带来了哪些影响?毕竟以前也就只是 ...

  2. Castle Core 4.0.0 alpha001发布

    时隔一年多以后Castle 项目又开始活跃,最近刚发布了Castle Core 4.0.0 的alpha版本, https://github.com/castleproject/Core/releas ...

  3. ifconfig: command not found(CentOS专版,其他的可以参考)

    ifconfig: command not found 查看path配置(echo相当于c中的printf,C#中的Console.WriteLine) echo $PATH 解决方案1:先看看是不是 ...

  4. 0.Win8.1,Win10,Windows Server 2012 安装 Net Framework 3.5

    后期会在博客首发更新:http://dnt.dkill.net 网站部署之~Windows Server | 本地部署:http://www.cnblogs.com/dunitian/p/482280 ...

  5. iOS开发之ReactiveCocoa下的MVVM(干货分享)

    最近工作比较忙,但还是出来更新博客了,今天给大家分享一些ReactiveCocoa以及MVVM的一些东西,干活还是比较足的.在之前发表过一篇博文,名字叫做<iOS开发之浅谈MVVM的架构设计与团 ...

  6. 使用NUnit为游戏项目编写高质量单元测试的思考

    0x00 单元测试Pro & Con 最近尝试在我参与的游戏项目中引入TDD(测试驱动开发)的开发模式,因此单元测试便变得十分必要.这篇博客就来聊一聊这段时间的感悟和想法.由于游戏开发和传统软 ...

  7. npm 使用小结

    本文内容基于 npm 4.0.5 概述 npm (node package manager),即 node 包管理器.这里的 node 包就是指各种 javascript 库. npm 是随同 Nod ...

  8. Atiti.大企业病与小企业病 大公司病与小公司病

    Atiti.大企业病与小企业病 大公司病与小公司病 1. 大企业病,一般会符合机构臃肿 .多重领导 .人才流失的特点.1 2. 大企业病避免方法1 3. 小企业病 1 3.1.1. 表现1 4. 如何 ...

  9. JavaScript 写计算器改进版

    <html><head><style> .short{height:50px;width:55px;float:left;}</style></h ...

  10. BZOJ 1597: [Usaco2008 Mar]土地购买 [斜率优化DP]

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4026  Solved: 1473[Submit] ...