一例一个实体对象不能由多个 IEntityChangeTracker 实例引用的解决

本文主要是介绍一例一个实体对象不能由多个 IEntityChangeTracker 实例引用的解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前几日在检查日志的时候发现系统偶尔会出现 Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded 的错误,经过查找资料,是因为随着访问量的增多,并发增多造成。解决办法从微软的msdn上找到了想改解决办法。

Entity Framework Optimistic Concurrency Patterns  这里给出了微软这篇文章的链接,我采用的是微软提出的第一种解决办法:Resolving optimistic concurrency exceptions with Reload   其中 update 方法的写法修改成这样:

 public bool Update(T entity){using (var dbContext = new F()){bool saveFailed;do{saveFailed = false;try{//把entity附加到当前dbContextdbContext.Set<T>().Attach(entity);dbContext.Entry<T>(entity).State = EntityState.Modified;return dbContext.SaveChanges() > 0;}catch (DbUpdateConcurrencyException ex){saveFailed = true;// Update the values of the entity that failed to save from the store ex.Entries.Single().Reload();}} while (saveFailed);return false;}}


 当然,添加和删除的相应方法也做了同样的修改,修改后对相应的方法做测试,没有发现什么问题。于是就上线了。因为并发效果在本地没法实现,实际效果需要上线后观察。过了个周末,然后周一来检查执行的效果,Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded 的错误没出现,但是发现大量的 一个实体对象不能由多个 IEntityChangeTracker 实例引用的错误。通过定位,是update方法出现了问题。网上搜索这个错误出现的原因,搜索到的大部分是说由于主从表的关系导致此问题,而且说的都云里雾里,看不懂他们说的意思。但是虽然出错的地方刚好有主从表,但我明白,问题恐怕不是这里。因为这个错误大量出现是在我更改了update方法后才出现的。通过分析我更改的update方法前后的变化,更改前update方法传入的entity实例和update方法SaveChanges 共用的是一个dbcontext, 而更改后,由于使用了 using new 了一个新的 dbcontext,这两个 dbcontext 不一样了,怀疑是这里的问题。而通过把 using 去掉,也真解决了这个问题,不出现 一个实体对象不能由多个 IEntityChangeTracker 实例引用的错误了。但是这样的解决不能令人满意。因为没有理论支撑。由于百度和google都没有找到令人满意的解释,于是把目光投向了 stackoverflow 网站,这个网站还是有许多高手,一些解释感觉很深刻。 通过不停的变换关键词搜索,终于找到了两篇文章解释的比较清楚。我总结了下我这个问题出现的原因是这样的,看这两行代码: 

var examList = es2.Get(m => m.ExamMainGID == examMain.GID && m.QuestionLibraryGID == gid).FirstOrDefault();

es2.Update(examList); 

第一行代码es2.Get方法使用的数据连接是_dbContext, entity framework 每一个查询方法都会自动创建一个 IEntityChangeTracker 的跟踪,这个跟踪是使用的_dbContext连接创建的,他会跟踪exmalList的实例状态变化,比如状态的修改,删除等。而在执行 es2.Update(examList);  这个方法的时候,由于Update方法的实现是 using 了一个新的dbContext: using (var dbContext = new F()), 在这句:dbContext .Set<T>().Attach(entity); 就是把 entity附加到了新的dbContext对象中。按ef的规则,这里是需要创建一个新的 IEntityChangeTracker  跟踪器,就是这行出现了错误。原因就是一个实例的跟踪器只能有一个,在这里这个实例就是examList 。在stackoverflow 网站的这两篇文章中也给出了解决办法。有两种,第一种是公用一个数据连接dbContext,就是我以前的解决办法,不再重新new 一个新的数据连接上下文,而仍然使用es2.Get方法使用的数据连接。另外一种解决办法就属于场合用法了。即把通过 es2.Get方法获取的实例 examList 同_dbContext 剥离开来,然后再把exmaList对象附加到新的 dbContext 对象中。具体的写法是这样的:

//从_dbContext中分离entity
((IObjectContextAdapter)_dbContext).ObjectContext.Detach(entity);
//把entity附加到当前dbContext
dbContext.Set<T>().Attach(entity);dbContext.Entry<T>(entity).State = EntityState.Modified;return _dbContext.SaveChanges() > 0;

这里的((IObjectContextAdapter)_dbContext).ObjectContext.Detach(entity);就是用 Detach 把 entity从 _dbContext上下文数据连接剥离出来。剥离后再附加到新的数据连接中就不会再出现错误。这个方法是不推荐的。如果每次都这样采用剥离的方法,这是增加代码量,共用Context 数据连接才是正确的方法。

这里给出两篇stakoverflow的连接,有兴趣的可以看下:

http://stackoverflow.com/questions/10191734/entity-object-cannot-be-referenced-by-multiple-instances-of-ientitychangetracker

http://stackoverflow.com/questions/12112360/c-sharp-entity-framework-ientitychangetracker-issue

这篇关于一例一个实体对象不能由多个 IEntityChangeTracker 实例引用的解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/768179

相关文章

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

MySQL JSON 查询中的对象与数组技巧及查询示例

《MySQLJSON查询中的对象与数组技巧及查询示例》MySQL中JSON对象和JSON数组查询的详细介绍及带有WHERE条件的查询示例,本文给大家介绍的非常详细,mysqljson查询示例相关知... 目录jsON 对象查询1. JSON_CONTAINS2. JSON_EXTRACT3. JSON_TA

MySQL 设置AUTO_INCREMENT 无效的问题解决

《MySQL设置AUTO_INCREMENT无效的问题解决》本文主要介绍了MySQL设置AUTO_INCREMENT无效的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录快速设置mysql的auto_increment参数一、修改 AUTO_INCREMENT 的值。

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

解决JSONField、JsonProperty不生效的问题

《解决JSONField、JsonProperty不生效的问题》:本文主要介绍解决JSONField、JsonProperty不生效的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录jsONField、JsonProperty不生效javascript问题排查总结JSONField

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三