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

先来看一下代码

  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. vert.x学习(六),动态模板与静态文件的结合

    这篇学习在动态模板里面引入css,把动态模板与静态文件结合起来使用. 编写DynamicReference.java package com.javafm.vertx.helloworld; impo ...

  2. 使用POWERDESIGNER设计数据库的20条技巧(转)

    1.PowerDesigner使用MySQL的auto_increment ◇问题描述: PD怎样能使主键id使用MySQL的auto_increment呢? ◇解决方法: 打开table prope ...

  3. TortoiseGit安装详解

    一:写该文章目的 最近换了一份新工作,新公司的源码管理都是使用GIT,习惯了之前的TFS和SVN进行项目源码管理和团队开发,第一次使用GIT进行团队开发和源码管理,颇有一些不习惯,花了一天时间终于把G ...

  4. centos7 使用systemd 自定义关机前脚本

    systemd (centos7) 需求,关机前执行脚本 关机脚本vi /usr/bin/shutdown_cust.sh#!/bin/bashecho "zhengchangguanji& ...

  5. buildroot--uboot&kernel&rootfs全编译工具

    参考: http://www.crifan.com/files/doc/docbook/buildroot_intro/release/html/buildroot_intro.html https: ...

  6. Windows Server 2008 R2域控组策略设置禁用USB

    问题: Windows Server 2008 R2域控服务器如何禁用客户端使用USB移动存储(客户端操作系统需要 Windows Vista以上的操作系统,XP以下的操作系统不能禁用USB移动存储) ...

  7. [CC]点云密度计算

    包括两种计算方法:精确计算和近似计算(思考:local density=单位面积的点数 vs  local density =1/单个点所占的面积) 每种方法可以实现三种模式的点云密度计算,CC里面的 ...

  8. varnish4.0 流程图以及说明

    varnish 中的内置变量 req repos client server bereq beresp bereq bereq.http.HEADER 由varnish发往backend server ...

  9. ios结构体语法

  10. git用.gitignore忽略指定文件

    .gitignore 配置文件用于配置不需要加入版本管理的文件,配置好该文件可以为我们的版本管理带来很大的便利,以下是个人对于配置 .gitignore 的一些心得. 1.配置语法: 以斜杠“/”开头 ...