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

先来看一下代码

  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. QQ战场形势图

    真是没什么可说,全面开战,无坚不摧,活脱脱一个中央帝国.只有极少的方向处于守势.本来对腾讯也没什么特别的感觉,但是看了这张图,真是让人热血沸腾. 如果美国的公司能像腾讯做的这么大相当于:faceboo ...

  2. sublime 配置jade高亮显示

    1.下载 Package Control.sublime-package 文件放入Packages文件目录下 2.control + shift + p   输入install package 3. ...

  3. 文件名保存为.wsf文件即可分析文件夹中每个文件的行数

    <job id="HowManyLines"> <script language="VBScript"> Const ForReadin ...

  4. Docker应用程序容器技术_转

    转自:百度百科 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相 ...

  5. Windows Server 2008 R2组策略创建用户桌面快捷方式

    问题: 如何让所有域用户桌面有一个公司共享的快捷方式,让所有域用户直接双击就能打开公司共享. 解决办法: 1.创建一个zhuyu组织单元 ----- 在zhuyu组织单元创建一个域用户user1. 2 ...

  6. I’m Sure It Will Only Take You A Few Days To Code

    from:http://danshipper.com/non-technical-people-cant-estimate-developmen “So the site’s pretty simpl ...

  7. 使用HTTPS网站搭建iOS应用内测网站(OTA分发iOS应用)

    为什么要搭建应用内测网站呢? 1.AppStore的审核速度比较慢,万一被拒,还得等,而且一旦发布,任何人都可以下载,而有些时候只有老板想知道最新的修改是否符合要求,万一不符合要求呢?又要修改了. 2 ...

  8. Url获取图片流并打包~

    因为公司项目需求,做一个所有数据以excle的格式汇出,其中包括了图片. 而数据库保存的是图片的url,虽然不知道为什么....如果数据量大的话, 那么所有数据汇出,包括图片的话... 额.. 不知道 ...

  9. pycharm licenseserver 注册方法

    pycharm5.0之后,以前的很多注册码都无法使用,可以选择使用license server 方式进行注册,方法如下: 注册方法:    在 注册时选择 License server ,填 http ...

  10. ubuntu16.04部署RED5流媒体服务器

    前提:jdk已经安装 1,下载RED5(https://github.com/Red5/red5-server/releases)选择red5-server-X.X.X-MXX.tar.gz 2,解压 ...