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

以上。
时间: 2024-10-13 05:25:00

EF Attach时已存在的处理方式的相关文章

EF Codefirst生成数据库的三种方式

1.写在前头 不是什么高大上的东西,也不是完全原创的,大多是自己学习时去网上查的各种资料.只是发现学东西还是要写点东西,不然前边写着后边忘了,花的时间都浪费了,写写增加记忆吧.如果是有人刚开始学看到这个相信会有帮助的. 2.开搞 前几天写了篇小文章搞了下EF生成数据库时获取连接字符串的方式,发布时不小心勾选了发布到首页,秒秒钟就被管理员给撤销了( ⊙ o ⊙ ),确实太低端了,博客园锅锅撤销也是可以理解的,废话不多说,今天继续搞一搞获取完连接字符串后EF怎么生成数据库呢,有哪些方式呢? 第一种:

请确保在编译时已将“AjaxControlToolkit.Properties.Resources.NET4.resources”正确嵌入或链接到程序集“AjaxControlToolkit”

原文:请确保在编译时已将"AjaxControlToolkit.Properties.Resources.NET4.resources"正确嵌入或链接到程序集"AjaxControlToolkit" 未能找到任何适合于指定的区域性或非特定区域性的资源.请确保在编译时已将 "AjaxControlToolkit.Properties.Resources.NET4.resources"正确嵌入或链接到程序集"AjaxControlToolk

学习aiax(javascript)--页面无刷新用ajax检查用户名是否已注册(POST方式)

1.jsp代码 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"

EF的三种数据加载方式

EF中有3种数据加载方式,具体如下: 延迟加载(默认): 设置导航属性为virtual 贪婪加载:不设置导航属性为virtual,并且对导航属性使用Include 显示加载:不设置导航属性为virtual,并且对导航属性使用Reference(单个对象).Load()或Collection(对象集).Load() public class Programm { public static void Main() { TestDbContext db = new TestDbContext();

linux文件名乱码时删除或改名的方式(转载)

转自:http://www.linuxsa.cn/when-linux-file-name-topsy-turvy-deleted-or-renamed.html linux文件名乱码时删除或改名的方式 当......一堆......文件出现乱码时,你想用脚本把他们改名,结果又发现字符处理工具awk等都对这些玩意没有办法,无比蛋疼啊,怎么办泥,我有办法: 1.ls -i 查找到这些乱码文件的inode号,比如说22588202.find . -inum 2258820 -exec mv {} n

关于MVC4-5 添加EF controller时 EF为同级类库时,报错时的问题解决。

关于MVC4-5 添加EF controller时 EF为同级类库时,报错时的问题解决.. unable to retrieve metadata No connection string named 'MyEntities' could be found in the application config file. 这地方是说EF类库中的App.config配置了 链接串,web.config中没有配置.所以会报上面这个错,查了20多分钟 才搞定.哎.怎么会有这种问题呢.

Cognos隐藏报表运行时提示选择报表发送方式

cognos8.3 隐藏报表运行时提示选择报表发送方式 (2010-11-21 12:06:02) 转载▼ 标签: cognos 杂谈 分类: Cognos 找到c8\webapps\p2pd\WEB-INF\classes下的viewer_XX.properties文件,XX是指区域,EN指英文地区,CN指中国,所以先备份viewer_CN.properties,把RV_BUSY_OPTIONS_SELECTED .RV_BUSY_OPTIONS_UNSELECTED.RV_BUSY_OPTI

MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式

通过上一篇的学习 我们把demo的各种关系终于搭建里起来 以及处理好了如何映射到数据库等问题 但是 只是搭建好了关系 问题还远没有解决 这篇就来写如何查找导航属性 和查找导航属性的几种方式 已经跟踪生成的SQL来检测是否满意 通过这节学习 来明白什么时候用哪个~~ 一.三种加载 1.延迟加载 这是原文中的图 大家可以去看下  我模仿上面的做了个测试  出现了  已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭. 我的解决办法是    var departments

出纳贪污公款逃21年 落网时已买房生子当&quot;老总&quot;yw

前几年,他拿出20多万积蓄在大厂买了一套房."中国购物中心处于过剩期,对选择店铺是非常有利的,特别是在租金交涉方面都处于非常有利的地位.为减轻负担,并确保免费医疗体系可以更好地运转,政府决定向海外移民和访客收取费用.今晚22点,江苏卫视<全能星战>进入制作人之夜,歌手要与制作人同台演绎制作人的代表作品.初见魏尚清,他身着一身迷彩衣,面带笑容,脸上的皱纹充满了岁月的印记.而现行检察权对侦查权规制的制度设计有一定局限性:局限于静态层面,局限于局部环节,对整个侦查活动缺乏全程的.动态的规制