热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于DbContext能不能单次请求内唯一?DbContex需不需要主动释放?欢迎各路大侠来“参战”!...

基于上篇文章《HiBlogs》重写笔记[1]--从DbContext到依赖注入再到自动注入园友Flaming丶淡蓝吴瑞祥提出了讨论和质疑,吓得我连夜查询资料ÿ

基于上篇文章《HiBlogs》重写笔记[1]--从DbContext到依赖注入再到自动注入园友 @Flaming丶淡蓝@ 吴瑞祥 提出了讨论和质疑,吓得我连夜查询资料(玩笑~)。
本来重点是想分析“自动注入”和对“注入”有更深的理解。不过既然有疑问和讨论那也是很好的。总比时不时来篇“这个不行”“那个要死了”的好。
之所以没有在评论区马上回复,是因为我确实不懂。所以下班后赶紧查阅相关资料。
我个人得出来的结论是:DbContext可以单次请求内唯一,且可以不主动释放。(其实当时心里也纳闷了。asp.net core就是这么干的啊,如果有问题还玩个毛线啊)
相关资料:http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext/
这篇资料博客应该还是有一定的权威性的,内容是EF团队解释回应。

Hello Jon,
The default behavior of DbContext is that the underlying connection is automatically opened any time is needed and closed when it is no longer needed. E.g. when you execute a query and iterate over query results using “foreach”, the call to IEnumerable.GetEnumerator() will cause the connection to be opened, and when later there are no more results available, “foreach” will take care of calling Dispose on the enumerator, which will close the connection. In a similar way, a call to DbContext.SaveChanges() will open the connection before sending changes to the database and will close it before returning.
Given this default behavior, in many real-world cases it is harmless to leave the context without disposing it and just rely on garbage collection.
That said, there are two main reason our sample code tends to always use “using” or dispose the context in some other way:
1. The default automatic open/close behavior is relatively easy to override: you can assume control of when the connection is opened and closed by manually opening the connection. Once you start doing this in some part of your code, then forgetting to dipose the context becomes harmful, because you might be leaking open connections.
2. DbContext implements IDiposable following the recommended pattern, which includes exposing a virtual protected Dispose method that derived types can override if for example the need to aggregate other unmanaged resources into the lifetime of the context.
By the way, with DbContext the pattern to open the connection manually and override the automatic open/close behavior is a bit awkward:
((IObjectContextAdapter)dbContext).ObjectContext.Connection.Open()
But we have a bug to make this easier as it used to be with ObjectContext before, e.g.:
dbContext.Database.Connection.Open()
Hope this helps,
Diego

谷歌翻译如下(英文不行,不知道翻译是否正确):

乔恩,
DbContext的默认行为是底层连接在需要时自动打开,并在不再需要时关闭。例如,当您执行查询并使用“foreach”迭代查询结果时,对IEnumerable .GetEnumerator()的调用将导致打开连接,并且稍后再没有可用的结果,“foreach”将会关闭调用Dispose在枚举器上,这将关闭连接。以类似的方式,调用DbContext.SaveChanges()将在将更改发送到数据库之前打开连接,并在返回之前关闭它。
鉴于这种默认行为,在许多现实世界的情况下,离开上下文而不处理它,只依靠垃圾回收是无害的。
也就是说,我们的示例代码往往总是使用“使用”或以其他方式处理上下文的两个主要原因:
1.默认的自动打开/关闭行为相对容易被覆盖:您可以通过手动打开连接来控制何时打开和关闭连接。一旦您在代码的某些部分开始执行此操作,那么忘记使用上下文会变得有害,因为您可能会泄露打开的连接。
2.DbContext根据推荐的模式实现IDiposable,其中包括暴露一个虚拟保护的Dispose方法,如果需要将其他非托管资源聚合到上下文的生命周期中,派生类型可以覆盖。
顺便说一下,用DbContext打开手动连接的模式,覆盖自动打开/关闭的行为有点尴尬:
((IObjectContextAdapter)的DbContext).ObjectContext.Connection.Open()
但是,我们有一个错误,使之更容易,因为它曾经与ObjectContext之前,例如:
dbContext.Database.Connection.Open()
希望这可以帮助,
迭戈

光说不练假把式,我们还是亲自来测试一下吧。

我们测试分两种情况:

  • 1、主动释放DbContext
  • 2、不释放DbContext
  • 3、最好能用多线程模拟下并发
  • 4、然后查看执行时数据库的连接数,和程序执行完之后数据库的连接数。

测试代码:

//模拟数据库的一些操作(为了相对真实,包含了新增、修改和查询)
private static void DbOperation(BloggingContext db)
{db.Blogs.Add(new Blog(){Rating = 1,Url = "www.i.haojima.net"});db.SaveChanges();db.Blogs.First().Url = "www.haojima.net";db.SaveChanges();foreach (var item in db.Blogs.Take(10).ToList()){Console.WriteLine("查询到的博客id:" + item.BlogId);}
}

条件输入:

static void Main(string[] args)
{Console.WriteLine("是否主动释放DbContext(y/n)");var yes = Console.ReadLine();Console.WriteLine("请输入模拟并发量");var number = Console.ReadLine();SemaphoreSlim _sem = new SemaphoreSlim(int.Parse(number));

循环代码:

var i = 0;
while (i <&#61; 5000)
{Console.WriteLine("启动第" &#43; i&#43;&#43; &#43; "个线程");_sem.Wait();#region Threadnew Thread(() &#61;>{if (yes &#61;&#61; "y"){using (BloggingContext bloggingContext &#61; new BloggingContext())//主动释放{DbOperation(bloggingContext);}}else{BloggingContext bloggingContext &#61; new BloggingContext();//不释放DbOperation(bloggingContext);}}).Start();#endregion_sem.Release();

查看连接数量&#xff08;sql语句&#xff09;&#xff1a;

SELECT count(1) AS &#39;连接到EFCoreDemoDB2数据库的数量&#39; FROM
[Master].[dbo].[SYSPROCESSES] WHERE [DBID] IN ( SELECT [DBID]
FROM [Master].[dbo].[SYSDATABASES]
WHERE NAME&#61;&#39;EFCoreDemoDB2&#39;
)

操作截图如下&#xff08;你也可以下载demo代码自行测试&#xff09;&#xff1a;

主动释放、模拟200并发量
208266-20170925230005901-862919019.png
208266-20170925230053167-1707538948.png

数据库看到的连接数最多的时候54个
208266-20170925230237792-2139909965.png

不释放、模拟200并发量
208266-20170925230304370-1560618856.png

数据库看到的连接数最多的时候56个
208266-20170925230351417-580559352.png

程序执行完成后&#xff0c;连接自动释放了
208266-20170925230414948-1021812975.png

 

【技巧】&#xff1a;
我们使用ef或dbcontext的时候主要注意三个问题&#xff1a;

  • 1、多个线程不能访问同一个dbcontext
  • 2、同一个跟踪实体不能被多个dbcontext操作
  • 3、如果查询数据不需要被修改&#xff0c;一定按需查询.select(t&#61;>new Dto(){ })。最不济也要AsNoTracking().ToList()。
    一般也就不会出现奇怪的问题了。

 

【注意】运行测试的时候用命令行执行或者“开始执行不调试”

demo&#xff1a;https://github.com/zhaopeiym/BlogDemoCode/tree/master/EFCoreDemo

当然&#xff0c;我也不知道这种测试是否合理。如果园友有更好的测试方式可以提供。欢迎大家交流。

转:https://www.cnblogs.com/zhaopei/p/dispose-on-dbcontext.html



推荐阅读
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
author-avatar
露露bear_715
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有