本篇文章将会剖析为什么会出现这一现象、以及解决的办法

先来看一下代码

  public static TResult AddTest()
{
TestDAL testdal = DALFactory.CreateDAL<TestDAL>();
TResult t;
Transaction.BeginTransaction();
try
{
testdal.Insert(new Test { ID= });
testdal.ExecuteSqlCommand("update test set name='111' where id=1");
//Test test = testdal.GetSingle(m => m.ID == 1);
//test.Name1 = "asdafaff";
testdal.Update(m => m.ID == , m => { m.Name1 = "asdafaff"; });
Transaction.Commit();
}
catch(Exception ex)
{
Transaction.Rollback();
}
finally
{
t= new TResult();
}
return t;
}

按照代码的逻辑,在事务提交完毕的时候应该ID NAME NAME1都应该有值得,但是结果却是NAME为NULL。令人大跌眼镜

并不是事务出现了问题,

问题出现在ExecuteSqlCommand是通过sql来更新数据库的,没有更新缓存中的实体实例上下文,当再次Update的时候,就会用到缓存中的实体实例,EF根据其状态进行更新或者删除等操作,所以自然就会把之前更新的又全部冲销覆盖了。

因此要解决这个问题,先看看UPDATE代码是怎么写的

 public TResult Update(Expression<Func<TEntity, bool>> predicate, Action<TEntity> updateAction)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
if (updateAction == null)
throw new ArgumentNullException("updateAction");
MyDbContext dbContext = this.GetDbContext();
//dbContext.Configuration.AutoDetectChangesEnabled = true;
var _model = dbContext.Set<TEntity>().Where(predicate).ToList();
if (_model == null) return new TResult(false, "参数为NULL");
_model.ForEach(p =>
{
updateAction(p);
dbContext.Entry<TEntity>(p).State = EntityState.Modified;
});
return Save(EntityState.Modified);
}

原来dbContext.Set<TEntity>().Where(predicate).ToList();EF会像数据库中做一次查询,查询出来后通过对象上下文根据主键去映射缓存对象,如果存在了,就用上下文中的缓存对象,因为还是旧的实例对象,所以这个值没有更新,就会冲销覆盖掉原来的数据。

因此如果要获取最新的值就必须不需要映射缓存对象

  var _model = dbContext.Set<TEntity>().AsNoTracking().Where(predicate).ToList();

下面是AsNoTracking()的注释
        // 摘要:
        //     Returns a new query where the entities returned will not be cached in the System.Data.Entity.DbContext.
        //
        // 返回结果:
        //     A new query with NoTracking applied.

返回一个新的查询,获得的实体对象不会被缓存在数据上下文中,所以不难理解,既然不会去缓存在上下文中,肯定就不会去做映射匹配的判断。否则必然会根据主键去匹配以避免重复的数据示例对象出现在缓存中,这也就不难理解EF实体对象中为什么一定要求有主键的原因了。

现在已经解决了实体是最新的实体了。可是接下来会出现问题

Attaching an entity of type '' failed because another entity of the same type already has the same primary key value.

因为缓存中有主键相同的实体对象了,所以再附加的时候要将旧的示例分离掉

  public TResult Update(Expression<Func<TEntity, bool>> predicate, Action<TEntity> updateAction)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
if (updateAction == null)
throw new ArgumentNullException("updateAction");
MyDbContext dbContext = this.GetDbContext();
//dbContext.Configuration.AutoDetectChangesEnabled = true;
var _model = dbContext.Set<TEntity>().AsNoTracking().Where(predicate).ToList();
if (_model == null) return new TResult(false, "参数为NULL");
_model.ForEach(p =>
{
updateAction(p);
DetachExistsEntity(p);
dbContext.Entry<TEntity>(p).State = EntityState.Modified;
});
return Save(EntityState.Modified);
}
private Boolean DetachExistsEntity(TEntity entity)
{
var objContext = ((IObjectContextAdapter)this.GetDbContext()).ObjectContext;
var objSet = objContext.CreateObjectSet<TEntity>();
var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity); Object foundEntity;
var exists = objContext.TryGetObjectByKey(entityKey, out foundEntity); if (exists)
{
objContext.Detach(foundEntity);
} return (exists);
}

解决方案到此结束,就不详细说明了。

EF之ExecuteSqlCommand更新出现无效的解决方案的更多相关文章

  1. Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案

    Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案 1. IE8.0 显示本地图片 img.src=本地图片路径无效的解决方案1 1.1. div来完成  ...

  2. 由于物化视图定义为on commit导致update更新基表慢的解决方案

    由于物化视图定义为on commit导致update更新基表慢的解决方案 以下是模拟和解决测试过程: (模拟update慢的过程) 1.首先基于基表创建物化视图日志: create materiali ...

  3. Android查缺补漏(View篇)--自定义 View 中 wrap_content 无效的解决方案

    自定义 View 中 wrap_content 无效的解决方案 做过自定义 View 的童鞋都会发现,直接继承 View 的自定义控件需要重写 onMeasure() 方法,并设置 wrap_cont ...

  4. EF Code First列名 'Discriminator' 无效的问题

    新建了一个类继承EF  Model类,运行报错 EF Code First列名 'Discriminator' 无效 EF会把项目中在DbContext中引用的所有的Model类及这些Model类对应 ...

  5. EF Code First更新数据库时报错:provider: SQL Network Interfaces, error: 26

    在使用EF Code First更新数据库时报如下错误: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Serv ...

  6. JavaScript日历控件开发 C# 读取 appconfig文件配置数据库连接字符串,和配置文件 List<T>.ForEach 调用异步方法的意外 ef 增加或者更新的习惯思维 asp.net core导入excel 一个二级联动

    JavaScript日历控件开发   概述 在开篇之前,先附上日历的代码地址和演示地址,代码是本文要分析的代码,演示效果是本文要实现的效果代码地址:https://github.com/aspwebc ...

  7. iOS7.1企业版发布后用户通过sarafi浏览器安装无效的解决方案

    关于iOS7.1企业版发布后,用户通过sarafi浏览器安装无效的解决方案: 通过测试,已经完美解决. 方案一: iOS7.1企业应用无法安装应用程序 因为证书无效的解决方案 http://blog. ...

  8. 虚拟机安装 ubuntu 后,更新源无效,以及无法联网安装软件的问题

    问题: 虚拟机安装 ubuntu 后,更新源无效,以及无法联网安装软件: 错误提示: Err http://security.ubuntu.com/ubuntu/ trusty-security/un ...

  9. cad.net 复制图元的时候按下多次esc导致复制中断的bug,令REGEN,REGENALL更新图元无效.

    浩辰没有这个bug !!!!!!! 如上述动图所示,cad在复制一个多图元的操作时候,多次按下esc键中断复制操作, **注意例子要有足够多的图元(大概一万个图元),才能很好展示这个bug,而且这个b ...

随机推荐

  1. 真机测试及布署Code Sign error问题总结

    Code Sign error: Certificate identity 'iPhone Developer: idf (XR9HN3TD7E)' appears more than once in ...

  2. node-webkit 使用requirejs 小结

    1. node-webkit 启动页使用requrejs 将webapp中的require改为requirejs,因为requirejs本来就应该用requirejs的,require只是requir ...

  3. IOS手动添加CoreData

    手动添加coreData: 1.在target-build phrase-Link binary with libraries里增加CoreData Framework 2.加入数据模型:comman ...

  4. 《奥威Power-BI案例应用:带着漫画看报告》腾讯课程开课啦

    元旦小假期过去了,不管是每天只给自己两次下床机会的你,还是唱K看电影逛街样样都嗨的你,是时候重振旗鼓,重新上路了!毕竟为了不给国家的平均工资水平拖后腿,还是要努力工作的.话说2016年已经过去了,什么 ...

  5. [CC]获取ScalarField的值

    //根据字段滤波void MainWindow::doActionFilterByValue() ReferenceCloud* ManualSegmentationTools::segment(Ge ...

  6. sql异步执行

    /// <summary> /// 按钮事件 异步执行 /// </summary> /// <param name="sender">< ...

  7. git tag — 标签相关操作

    标签可以针对某一时间点的版本做标记,常用于版本发布. 列出标签 $ Git tag # 在控制台打印出当前仓库的所有标签$ git tag -l 'v0.1.*' # 搜索符合模式的标签 打标签 gi ...

  8. 浅析angular,react,vue.js jQuery使用区别

    前端越来越混乱了,当然也可以美其名曰:繁荣.当新启动一个前端项目,第一件事就是纠结:使用什么框架,重造什么轮子? PS:大牛留言讨论那么,希望看完此篇,能够给你一个清晰的认识,或者让你更加地纠结和无所 ...

  9. (一)Nand FLASH 原理讲解

    NAND FLASH  优势 : 可以用当硬盘   这里好像型号是 K9F2G08 基本结构: 不是很难自己看看,暂时不要看

  10. VB中键盘每个按键所对应的具体数值是?

    键码常数 值 描述 vbKeyLButton 1 鼠标左键 vbKeyRButton 2 鼠标右键 vbKeyCancel 3 CANCEL 键 vbKeyMButton 4 鼠标中键 vbKeyBa ...