EF Attach时已存在的处理方式
如果我们在先前的步骤中读取过数据,如
var list = db.Model.ToList();
之后再,附加
var o = new Model { Id = 1 };
db.Model.Attach(o);
就会报,类似这样的错误
Attaching an entity of type 'efAutoDetach.Model' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
意思是说,在上下文中,已经有一个同样主键的东西了。
这样的错误通常在直接更新时遇到,不是先查出来再更新,而是直接new一个出来,附加上去更新
第一次查询后,本地的local中就已经有相应的实体了。如果我们把local中的实体detach了,那我们新new的对象就可以attch上去了。
Detach的扩展方法
public static void Detach<T>(this DbContext db, T obj) where T : class
{
ObjectContext oc = ((IObjectContextAdapter)db).ObjectContext;
oc.Detach(obj);
}
获取主键信息的扩展方法
public static IEnumerable<string> GetEntityKeys<T>(this DbContext db) where T : class
{
ObjectContext oc = ((IObjectContextAdapter)db).ObjectContext;
var keys = oc.CreateObjectSet<T>().EntitySet.ElementType.KeyProperties.Select(x => x.Name);
return keys;
}
我们需要通过主键信息构建一个表达式树,用于从local中获取实体
private static Expression<Func<T, bool>> GetFindExp<T>(T obj, IEnumerable<string> keys) where T : class
{
var p = Expression.Parameter(typeof(T), "x"); var keyexps = keys.Select(x =>
{
var member = Expression.PropertyOrField(p, x);
var objV = typeof(T).GetProperty(x).GetValue(obj);
var eq = Expression.Equal(member, Expression.Constant(objV));
return eq;
}).ToList(); if (keys.Count() == 1)
{
return Expression.Lambda<Func<T, bool>>(keyexps[0], new[] { p });
} var and = Expression.AndAlso(keyexps[0], keyexps[1]);
for (var i = 2; i < keyexps.Count; i++)
{
and = Expression.AndAlso(and, keyexps[i]);
}
return Expression.Lambda<Func<T, bool>>(and, new[] { p });
}
于是可以找到local中的
public static T FindLocal<T>(this DbContext db, T obj) where T : class
{
var keys = db.GetEntityKeys<T>();
var func = GetFindExp<T>(obj, keys).Compile();
return db.Set<T>().Local.FirstOrDefault(func);
}
最后综合使用上面的几个方法
public static void DetachOther<T>(this DbContext db, T obj) where T : class
{
var local = db.FindLocal(obj);
if (local != null)
{
db.Detach(local);
}
}
使用
var o = new Model { Id = 1 };
db.DetachOther(o);
db.Model.Attach(o);
在attach之前,先detachother
以上。
EF Attach时已存在的处理方式的更多相关文章
- C# EF Attach 与 Entry
先了解一下 EF 框架的 EntityState 在使用EF框架时, 我们通常都是通过调用 SaveChanges() 方法把增加/修改/删除的数据提交到数据库,但是上下文是如何知道实体对象是增加.修 ...
- webapi 控制器接收POST参数时必须以对象的方式接收
webapi 控制器接收POST参数时必须以对象的方式接收
- 未能找到任何适合于指定的区域性或非特定区域性的资源。请确保在编译时已将“xxx.Resources.resources”正确嵌入或链接到程序集
今天在测试一个工程的时候,突然遇到了这样一个问题: 错误信息:System.Resources.MissingManifestResourceException: 未能找到任何适合于指定的区域或非特定 ...
- 请确保在编译时已将“AjaxControlToolkit.Properties.Resources.NET4.resources”正确嵌入或链接到程序集“AjaxControlToolkit”
原文:请确保在编译时已将"AjaxControlToolkit.Properties.Resources.NET4.resources"正确嵌入或链接到程序集"AjaxC ...
- EF的三种数据加载方式
EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Loading都是延迟加载. (一 ...
- linux文件名乱码时删除或改名的方式(转载)
转自:http://www.linuxsa.cn/when-linux-file-name-topsy-turvy-deleted-or-renamed.html linux文件名乱码时删除或改名的方 ...
- SQLPlus在连接时通常有四种方式
SQLPlus在连接时通常有四种方式 1. ? 1 sqlplus / as sysdba 操作系统认证,不需要数据库服务器启动listener,也不需要数据库服务器处于可用状态.比如我们想要启动数据 ...
- 第十节: EF的三种追踪实体状态变化方式(DBEntityEntry、ChangeTracker、Local)
一. 简介 我们在前面章节介绍EF基本增删改的时候,曾说过EF的SaveChanges()方法,会一次性的将所有的实体的状态变化统一提交到数据库,那么你是否想过EF的实体会有哪些状态变化呢?什么原因会 ...
- MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式
文章索引和简介 通过上一篇的学习 我们把demo的各种关系终于搭建里起来 以及处理好了如何映射到数据库等问题 但是 只是搭建好了关系 问题还远没有解决 这篇就来写如何查找导航属性 和查找导航属性的几种 ...
随机推荐
- Linux 常用命令小结
学习脚本几天了,总结下linux debian下脚本常用命令. Linux 1.添加删除账户 useradd / userdel 2.修改"张三"密码 passwd 张 ...
- php三种基础算法:冒泡,插入和快速排序法
$array = array(2,3,5,6,9,8,1); //冒泡排序思想,前后元素比较 function sort_bulldle($array){ $num = count($array); ...
- 家中Win7 安装 Maven的步骤及参考文章
Maven 实战系列之在Windows上安装Maven cy163注:Path中的值: %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32 ...
- Revit中将倾斜轴线显示为正交模式
Revit建模过程中有时候会遇到某些特殊的建筑不规则建筑或者其轴线视图中并非正交二是倾斜的情况,用Revit建模过程中对于倾斜的建筑不仅不符合人的视觉习惯,而且也会对后期的机电管线的布设造成困扰,稍不 ...
- ASP.NET Core 获取控制器上的自定义属性
/// <summary> /// 参考代码Microsoft.AspNetCore.Mvc.Internal.AuthorizationApplicationModelProvider ...
- [Lua]50行代码的解释器,用来演示lambda calculus
嗯,来写写经过: 在知乎上看见用Belleve牛用javascript写了一个精简的lisp解释器 => 我也想写一个,用lua写,能多简单呢? => 写了一个阉割的scheme解释器,包 ...
- c++算法应用 预备
章 C + +程序设计 大家好!现在我们将要开始一个穿越" 数据结构.算法和程序" 这个抽象世界的特殊旅程,以解决现实生活中的许多难题.在程序开发过程中通常需要做到如下两点:一是高 ...
- SQL SERVER 服务启动后停止,某些服务由其它服务或程序使用时将自动停止
发生症状: 先是服务器挂掉,之后服务器可以登陆,但是实例却不能登陆进去(部分).出现的错误日志如下: :: R2 (SP2) - 10.50.4000.0 (X64) Jun :: Copyright ...
- TWaver Flex开发示例及license下载
做电信项目的朋友一定知道TWaver,而Flex版具有很好的跨平台性,很适合做B/S模式的应用. Flex版的在线DEMO:http://twaver.servasoft.com/demo/twave ...
- MySQL HA方案之MySQL半复制+MHA+Keepalived+Atlas+LVS[转]
MySQL HA方案之MySQL半复制+MHA+Keepalived+Atlas+LVS 简介 目前Mysql高可用的方案有好多,比如MMM,heartbeat+drbd,Cluster等,还有per ...