EF之ExecuteSqlCommand更新出现无效的解决方案
本篇文章将会剖析为什么会出现这一现象、以及解决的办法
先来看一下代码
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更新出现无效的解决方案的更多相关文章
- Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案
Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案 1. IE8.0 显示本地图片 img.src=本地图片路径无效的解决方案1 1.1. div来完成 ...
- 由于物化视图定义为on commit导致update更新基表慢的解决方案
由于物化视图定义为on commit导致update更新基表慢的解决方案 以下是模拟和解决测试过程: (模拟update慢的过程) 1.首先基于基表创建物化视图日志: create materiali ...
- Android查缺补漏(View篇)--自定义 View 中 wrap_content 无效的解决方案
自定义 View 中 wrap_content 无效的解决方案 做过自定义 View 的童鞋都会发现,直接继承 View 的自定义控件需要重写 onMeasure() 方法,并设置 wrap_cont ...
- EF Code First列名 'Discriminator' 无效的问题
新建了一个类继承EF Model类,运行报错 EF Code First列名 'Discriminator' 无效 EF会把项目中在DbContext中引用的所有的Model类及这些Model类对应 ...
- EF Code First更新数据库时报错:provider: SQL Network Interfaces, error: 26
在使用EF Code First更新数据库时报如下错误: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Serv ...
- JavaScript日历控件开发 C# 读取 appconfig文件配置数据库连接字符串,和配置文件 List<T>.ForEach 调用异步方法的意外 ef 增加或者更新的习惯思维 asp.net core导入excel 一个二级联动
JavaScript日历控件开发 概述 在开篇之前,先附上日历的代码地址和演示地址,代码是本文要分析的代码,演示效果是本文要实现的效果代码地址:https://github.com/aspwebc ...
- iOS7.1企业版发布后用户通过sarafi浏览器安装无效的解决方案
关于iOS7.1企业版发布后,用户通过sarafi浏览器安装无效的解决方案: 通过测试,已经完美解决. 方案一: iOS7.1企业应用无法安装应用程序 因为证书无效的解决方案 http://blog. ...
- 虚拟机安装 ubuntu 后,更新源无效,以及无法联网安装软件的问题
问题: 虚拟机安装 ubuntu 后,更新源无效,以及无法联网安装软件: 错误提示: Err http://security.ubuntu.com/ubuntu/ trusty-security/un ...
- cad.net 复制图元的时候按下多次esc导致复制中断的bug,令REGEN,REGENALL更新图元无效.
浩辰没有这个bug !!!!!!! 如上述动图所示,cad在复制一个多图元的操作时候,多次按下esc键中断复制操作, **注意例子要有足够多的图元(大概一万个图元),才能很好展示这个bug,而且这个b ...
随机推荐
- 解决Entity Framework中DateTime类型字段异常
从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值 具体的错误原因是:C#中的DateTime类型比SqlServer中的datetime范围大.SqlServe ...
- C# 关键字【转】
C#中的关键字 关键字是对编译器具有特殊意义的预定义保留标识符.它们不能在程序中用作标识符,除非它们有一个 @ 前缀.例如,@if 是有效的标识符,但 if 不是,因为 if 是关键字. 下面是列 ...
- IOS的MVC和MVVM模式简明介绍
iOS中的MVC(Model-View-Controller)将软件系统分为Model.View.Controller三部分,结构图如下: Model: 你的应用本质上是什么(但不是它的展示方式) C ...
- LeetCode Add Strings
原题链接在这里:https://leetcode.com/problems/add-strings/ 题目: Given two non-negative numbers num1 and num2 ...
- android:descendantFocusability用法简析
开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了 ...
- Sublime Text3 以及 SublimeREPL使用Virtualenv执行python
1. SublimeText3 安装Virtualenv插件(Crtl+Shift+P) 2. 新建python虚拟环境: Crtl+Shift+P,选中Virtualenv:New选项,在底部Vir ...
- App.domain http->https
App.domain = `${location.origin}/toa-mgw/rest/gateway`.replace(/http:\/\//, 'https://');
- TIJ——Chapter Seven:Reusing Classes
Reusing Classes 有两种常用方式实现类的重用,组件(在新类中创建存在类的对象)和继承. Composition syntax Every non-primitive object has ...
- 【C#进阶】override new virtual
class Organ { public virtual void Intro() { Console.WriteLine("I'm a organ."); } public st ...
- PHP 返回JSON
有个朋友说PHP不能返回JSON对象,作为.net的我认为应该是可以的,设置一下header 就行了. 果不然,google 一下,备忘如下: <?php $result = array('Na ...