文章出處
文章列表
之前發表過一篇文章題為《關于Entity Framework中的Attached報錯的完美解決方案》,那篇文章確實能解決單個實體在進行更新、刪除時Attached的報錯,注意我這里說的單個實體,指的是要更新或刪除的實體不包含其它實體(比如導航屬性就包含其它實體),也就是簡單POCO對象;但如果不是呢?那么那篇文章里的方法在一定程度上不起作用了,仍會報錯,我開始也想不明白,明明通過IsAttached函數判斷要更新的實體并未Attached,但進行Attaching時但仍然報錯說有相同Key,開始還以為是MS的BUG,后經過多次反復調試發現,報錯是對的,因為他報的錯并不是我當前要更新的實體,而是該實體中關聯的實體,代碼與演示報錯如下:(僅是演示代碼)
public class A { public string a{get;set;} public string b{get;set;} public string c{get;set;} public virtual B b{get;set;} } public class B { public string x{get;set;} public string y{get;set;} public string z{get;set;} } var a1= dbContext.Set<A>().Single(); a1.a="test1"; dbContext.SaveChanges(); dbContext.Detach(a1);//從緩存中移除a1實體; var a2= dbContext.Set<A>().AsNoTracking().Single(); a2.a="test2"; dbContext.Set<A>().Attach(a2); //報錯,說B相同的KEY已經有Attached dbContext.Entry(entity).State = EntityState.Modified; dbContext.SaveChanges();
針對這個報錯,我在想,為何查詢實體A的時候能同時關聯查詢實體B并都同時Attached到內存中,而當我執行Detach實體A時,卻沒能關聯Detach實體B,問題根源就在這里,知道這個原因了,現在就是要解決這個問題,如何解決呢?既然知道是Detach實體不全面造成的,那么我只需要獲取到當前DbContext上下文對象中現有的所有已Attached實體,在執行完相應的CRUD時,再全部依次Detach掉即可,解決方案代碼如下:
/// <summary> /// 清空DB上下文中所有緩存的實體對象 /// </summary> private void DetachedAllEntities() { var objectContext = ((IObjectContextAdapter)this.baseContext).ObjectContext; List<ObjectStateEntry> entries = new List<ObjectStateEntry>(); var states = new[] { EntityState.Added, EntityState.Deleted, EntityState.Modified, EntityState.Unchanged }; foreach (var state in states) { entries.AddRange(objectContext.ObjectStateManager.GetObjectStateEntries(state)); } foreach (var item in entries) { objectContext.Detach(item.Entity); } } public void Commit() //封裝的統一提交方法 { this.baseContext.SaveChanges(); this.DetachedAllEntities();//執行清除 }
在使用的時候配合之前那篇文章的IsAttached函數就能完美解決所有的Attached報錯問題了!
文章列表
全站熱搜