EF Attach時已存在的處理方式

來源:互聯網
上載者:User

標籤:

如果我們在先前的步驟中讀取過資料,如

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時已存在的處理方式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.