一例一个实体对象不能由多个 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

相关文章

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二:

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基

最详细安装 PostgreSQL方法及常见问题解决

《最详细安装PostgreSQL方法及常见问题解决》:本文主要介绍最详细安装PostgreSQL方法及常见问题解决,介绍了在Windows系统上安装PostgreSQL及Linux系统上安装Po... 目录一、在 Windows 系统上安装 PostgreSQL1. 下载 PostgreSQL 安装包2.

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用