zoukankan      html  css  js  c++  java
  • 关于Entity Framework中的Attached报错的完美解决方案终极版

    之前发表过一篇文章题为《关于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报错问题了!

  • 相关阅读:
    用Python操纵文件(自动化脚本的第一步)
    关于Numpy Array的使用技巧整理
    有用的在线小工具汇总
    HackerRank刷题之路---Python
    周志华老师《机器学习》复习要点(持续更新)
    Python函数式编程学习笔记
    Supervised Descent Method学习之路(持续更新)
    HackerRank刷题之路之---Algorithm(基于Python2)(持续更新)
    Vim常用命令精简化汇总及Vim的相关配置问题
    在VC++6.0中,如何将多个工程添加到同一个工作区?
  • 原文地址:https://www.cnblogs.com/zuowj/p/4650781.html
Copyright © 2011-2022 走看看