我们看看下面的代码:
这里为了节省效率,更新缓存的操作放到了异步中去执行,但是执行到Article findArticle = _articleDAL.GetAtricleById(id);这一步的时候,ef的上下文对象会被释放掉,调用查询等操作就会报错:Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance
我对这个原因的理解:
是依赖注入生命周期的问题,scope模式是同一个请求获取得到相同的实例(ef注入的默认方式是scope),然后我又使用task开了一个先线程形成异步,这样就造成请求执行完了对象就已经释放了,然后线程里边缺还去用到了ef的上下文对象,所以得到的就是为空的
对.net core注入模式的了解可以参考:http://www.tnblog.net/aojiancc2/article/details/167
对于默认模式我们在这里也可以看到
想到的解决方法:
方法一:先把需要的数据查询出来然后在使用异步
这样就不怕ef上下文对象被释放了,因为不需要用到了
方法二:我在想既然对象会被释放,那我在异步中重新去依赖注入容器获取一下不就行了
但是这样并不行,要么就是HttpContext对象被释放
那么就是ef上下文对象被释放:
即使你把重新获取的代码放到异步的外面,获取到的ef上下文对象依然是被释放的,因为scope模式是同一个请求获取得到相同的实例,请求完了这个上下文对象就会被释放
方法三:修改ef上下文注入的方式
变成Transient瞬时模式,每次从容器获取都能得到不同的对象
然而还是会被释放,因为我们_articleDAL还是在主线程被创建的,所以_articleDAL下面关联的ef上下文对象也是属于主线程的,主线程执行完了,ef上下文对象依然会被释放
方法四:修改生命周期和重新去依赖注入容器获取结合使用,也就是2,3方法结合一起使用
这样不就可以在异步方法所在线程中维护对象的生命周期么,只要异步所在的线程没有执行完,对象就不会被释放
然而并没有什么卵用还是不行,为什么和想像中的不一样呢。不用异步没有问题,先查询出来在异步更新缓存也没有问题。
但是在异步中去使用ef查询始终有问题呢,难道是因为HttpContext是在主线程中么,所以用它从容器中获取的对象其实还是受主线程的控制,
而且在异步方法中使用HttpContext去获取对象本身就是不科学的。
方法五:更新方法2中的获取依赖注入对象的方式
不去使用HttpContext的方式获取,因为HttpContext本身就属于请求那次的线程
我们使用静态类的方式去获取对象
果然这个问题确实是我们猜想的那样换种获取对象的方法就不会有问题了
net core手动获取依赖注入对象可以参考:
http://www.tnblog.net/aojiancc2/article/details/2980
算了我们绕了这么大一个圈圈其实还是第一种方法最简单,科学
tip:当然你还可以考虑使用单例模式或者AddDbContextPool方式注入,我这里就暂时不尝试了,先弄其他东西了
这个
问题
从未遇见过,是一位前辈问我
EF
Core
内存泄漏
问题
时我才去深入探讨这个
问题
,刚开始我比较惊讶,居然还有这种
问题
,然后就有了本文,直接拿前辈的示例代码并稍加修改成就了此文,希望对在自学
EF
Core
过程中的童鞋能有些许帮助。
EntityFramework
Core
内存泄漏回顾
接下来我将用简单示例代码来还原整个造成EntityFramework
Core
内存泄漏的过程,同时在...
目录一、异常 The ObjectContext instance has been disposed and can no longer be used for operations that require a connection1.将导航属性改为“非延迟加载”2.将属性先在连接未
释放
前查询出来二、InvalidOperationException: 已有打开的与此 Command 相关联的...
EF
Core
跟踪改变是在属性层面的。简单讲就是var context = new XXXContext()得到
上下文
后,用诸如context.DbSet.property = xxx的语句对
上下文
中的实体做出更改会被跟踪到,然后调用SaveChanges会把对实体的更改写入到数据库中。这是因为
EF
Core
会
自动
跟踪被查询实体的状态,然后在调用SaveChanges时检测这些实体的变化。因为同一实体被多次获取后,如果做了不同的更改,这可能会导致后期写入的时候不确定性,计算机执行是不能有二义性的。
非跟踪查询
跟踪行为决定了 Entity Framework
Core
是否将有关实体实例的信息保留在其更改跟踪器中。如果已跟踪某个实体,则该实体中检测到的任何更改都会在SaveChanges()期间永久保存到数据库。
EF
Core
还将修复跟踪查询结果中的实体与更改跟踪器中的实体之间的导航属性
var blogs = context.Blogs
.AsNoTracking()
.ToList();
在只读方案中使用结果时,非跟...
如果使用 AsNoTracking() 方法,就算 改变 值 添加 值 删除值 等 SaveChanges() 数据库都不会更改。这个用途 就是 确保 百分百 只读取 不做任何修改。
????欢迎点赞 :???? 收藏 ⭐留言 ???? 如有错误敬请指正,赐人玫瑰,手留余香!????本文作者:由webmote 原创,????作者格言:生活在于折腾,当你不折腾生活时,生活...
新建.net
core
2.1版本的MVC项目:在项目中的“appsettings.json”和“appsettings.Development.json”文件中插入:"ConnectionStrings": {"Database": "Server=127.0.0.1;User Id=xxx;Password=xxxxxx;Database=xxxxx;"}*根据环境(正式、测试)不同,xxxx替...
首先,在起初没有使用仓储模式时,本人在使用
EF
上下文
基本都用了using标记,随时使用随时
释放
,如下所示:
using(dbcontext con = new dbcontext()){
con.xxx......;
我们大家哦度知道,
EF
查询跟踪是存在数据缓存的,如果随时
释放
将无法利用缓存带来的查询速度提升。
同样,
EF
缓存也面临查询出现脏数据的
问题
,各有利弊。
EF
是默认开启数据查询缓...
一个多月来,加班似乎成了家常便饭,紧追慢赶手头几乎不可能实现的项目,也很少有机会写点什么了。最近在实现Delphi Server控件组操作Word编辑文档的时候,遇到了3年前就曾遇到的
问题
,以为这次能够圆满解决,但最后发现还是沿用的老方法--看来对于实现层,我还是个新手啊...好了废话不说,来说说我发明的这个笨法。
问题
的由来:当前项目中有个实现为,用Delphi的Server控件启动一