EntityFramework Core 1.1是如何创建DbContext实例的呢?
前言
上一篇我们简单讲述了在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实例的呢?的更多相关文章
- [.NET Core] - 使用 EF Core 的 Scaffold-DbContext 脚手架命令创建 DbContext
Scaffold-DbContext 命令 参数 Scaffold-DbContext [-Connection] <String> [-Provider] <String> ...
- EntityFramework Core 3.x上下文构造函数可以注入实例呢?
前言 今天讨论的话题来自一位微信好友遇到问题后请求我的帮助,当然他的意图并不是本文标题,只是我将其根本原因进行了一个概括,接下来我们一起来探索标题的问号最终的答案是怎样的呢? 上下文构造函数是否可以注 ...
- 非构造函数方式创建DbContext实例的方法
using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Design;using Microsoft.Entit ...
- [Abp vNext 源码分析] - 14. EntityFramework Core 的集成
一.简要介绍 在以前的文章里面,我们介绍了 ABP vNext 在 DDD 模块定义了仓储的接口定义和基本实现.本章将会介绍,ABP vNext 是如何将 EntityFramework Core 框 ...
- EntityFramework Core上下文实例池原理分析
前言 无论是在我个人博客还是著作中,对于上下文实例池都只是通过大量文字描述来讲解其基本原理,而且也是浅尝辄止,导致我们对其认识仍是一知半解,本文我们摆源码,从源头开始分析.希望通过本文从源码的分析,我 ...
- EntityFramework Core如何映射动态模型?
前言 本文我们来探讨下映射动态模型的几种方式,相信一部分童鞋项目有这样的需求,比如每天/每小时等生成一张表,此种动态模型映射非常常见,经我摸索,这里给出每一步详细思路,希望能帮助到没有任何头绪的童鞋, ...
- 【EFCore】利用Entityframework Core创建数据库模型
利用Entityframework Core创建数据库模型 本文中Entityframework Core版本为v3.1.6 简介 Entity Framework (EF) Core 是微软轻量化. ...
- .NET Core之Entity Framework Core 你如何创建 DbContext
本文版权归博客园和作者吴双共同所有,欢迎转载,转载和爬虫请注明博客园蜗牛原文地址 http://www.cnblogs.com/tdws/p/5874212.html. 目前国内各大论坛,各位大牛的分 ...
- [转].NET Core之Entity Framework Core 你如何创建 DbContext
本文转自:http://www.cnblogs.com/tdws/p/5874212.html 本文版权归博客园和作者吴双共同所有,欢迎转载,转载和爬虫请注明博客园蜗牛原文地址 http://www. ...
随机推荐
- SQL Server 数据加密功能解析
SQL Server 数据加密功能解析 转载自: 腾云阁 https://www.qcloud.com/community/article/194 数据加密是数据库被破解.物理介质被盗.备份被窃取的最 ...
- AutoMapper
什么是AutoMapper? AutoMapper是一个对象和对象间的映射器.对象与对象的映射是通过转变一种类型的输入对象为一种不同类型的输出对象工作的.让AutoMapper有意思的地方在于它提供了 ...
- WinForm 天猫2013双11自动抢红包【源码下载】
1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...
- 80 端口被占用 pid=4
80端口被pid=4的系统进程给占用的解决方法: 一般开发的时候我们都会安装sqlserver ,也会把Sql server Reporting Services 安装上去.原因就是这个服务占用了80 ...
- dubbo服务提供与消费
一.前言 项目中用到了Dubbo,临时抱大腿,学习了dubbo的简单实用方法.现在就来总结一下dubbo如何提供服务,如何消费服务,并做了一个简单的demo作为参考. 二.Dubbo是什么 Dubbo ...
- [C#] 走进 LINQ 的世界
走进 LINQ 的世界 序 在此之前曾发表过三篇关于 LINQ 的随笔: 进阶:<LINQ 标准查询操作概述>(强烈推荐) 技巧:<Linq To Objects - 如何操作字符串 ...
- bootstrap-fileinput 简单使用
bootstrap-fileinput 是一款图片/文件上传 bootstrap 插件,简单示例代码: <!DOCTYPE html> <html> <head> ...
- redis成长之路——(二)
redis操作封装 针对这些常用结构,StackExchange.Redis已经做了一些封装,不过在实际应用场景中还必须添加一些功能,例如重试等 所以对一些常功能做了一些自行封装SERedisOper ...
- Spring异步功能
使用 Spring 的异步功能时,实质是使用的 Servlet3 及以上版本的异步功能. Spring 的异步处理机制需要在 web.xml 中全部的 servlet 和 filter 处配置 < ...
- 使用Hudson搭建自动构建服务器
环境: ubuntu1404_x64 说明: 使用hudson和git搭建自动构建服务器的简单示例 安装hudson及相关插件 安装hudson 安装命令如下: sudo sh -c "ec ...