EF Linq To Entities ObjectManager 已存在相同键无法再Attach的解决方案

之所以会有这个异常,八成是因为之前在同一个DbContext下已经将这个对象Attach到了Context里,即已经搜索过

而现在要操作的对象八成是new或clone出来的对象,拥有相同的主键值,但不是同一个对象实例。

要解决只有一个思路,就是当这个异常发生时,找到Context里那个同主键值的对象,然后强行更改这个对象的值为你要操作的那个,这样就行了。

所以代码如下,先找到那个同主键值的对象:

public T GetEntityKeyNames<T>(DbContext context,T obj) where T:class
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            var set = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<T>();
            var entitySet = set.EntitySet;
            string[] keyNames = entitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray();
            string precidate = string.Empty;
            foreach(string filter in keyNames)
            {
                precidate+= "it."+filter+"="+context.Entry<T>(obj).Property(filter).CurrentValue.ToString();
            }
            return set.Where(precidate).First();
            
        }
View Code

真正的状态改变则可以调用如下代码:

public void Update<T>(T obj) where T : class
        {
            using (BE50Beta_AdminEntities1 context = new BE50Beta_AdminEntities1())
            {

                try
                {
                    context.Entry<T>(obj);
                }
                catch
                {
                    //context.ChangeTracker.Entries<Patron>().ToList().Remove(GetEntityKeyNames(context, pE);
                    context.Entry<T>(GetEntityKeyNames(context, obj)).CurrentValues.SetValues(obj);
                }
            }

        }
View Code

这样每次SaveChange就不用担心对象是不是已经被加载到Context中了

原文地址:https://www.cnblogs.com/vincentsun1234/p/3087778.html