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

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

springboot security验证码的登录实例

《springbootsecurity验证码的登录实例》:本文主要介绍springbootsecurity验证码的登录实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录前言代码示例引入依赖定义验证码生成器定义获取验证码及认证接口测试获取验证码登录总结前言在spring

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

springboot报错Invalid bound statement (not found)的解决

《springboot报错Invalidboundstatement(notfound)的解决》本文主要介绍了springboot报错Invalidboundstatement(not... 目录一. 问题描述二.解决问题三. 添加配置项 四.其他的解决方案4.1 Mapper 接口与 XML 文件不匹配