zoukankan      html  css  js  c++  java
  • ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。

    出现问题的显示:

    一,我们来探究下这问题出现的原因:

    报错代码块,如下

    UserInfo us = _iuserInfoBll.GetById("E501BE1F-07CA-4B5F-9801-02862B41AD8B");
    us.NickName = "123132";
    _iuserInfoBll.Update(us);

    查询方法

     public virtual T GetById(string id)
    {
          return _dbset.Find(id);
    }

    更新方法:

        public virtual void Update(T entity)
            {
                _dbset.Attach(entity); //这里报错
                DataContext.Entry(entity).State = EntityState.Modified;
                _dataContext.SaveChanges();
            }

    根据上面我们发现,出现的原因是:我们先执行了查询操作,然后再执行更新操作,那为什么这样会出现问题?

    查找下资料发现:这是由于查询之后的数据,EF默认帮我们缓存了起来,放在了DbContext上下文中,我们在修改的时候,执行dbset.Attach(entity);,发现缓存中已存在同一键值,所以会报这个错。

    那我们的解决方法是什么呢?

    一,在查询的方法中添加AsNoTracking(),不跟踪

    List<Alldetails> all = db.Alldetails.AsNoTracking().Where(m => m.Brand == alldetails.Brand).ToList();

    二,我们可以重写update方法,看我仓储中的update方法,是以虚方法定义的,则我们可以重写:

           ///Entity Framework中编辑时错误ObjectStateManager 中已存在具有同一键的对象
            /// <summary>
            /// 由于出现ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象,重写Update解决
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            public override void Update(UserInfo entity)
            {
                var query = DataContext.Set<UserInfo>().Find(entity.UserID);
                if (query != null)
                {
                    DataContext.Entry<UserInfo>(query).State = EntityState.Detached; //这个是在同一个上下文能修改的关键
                }
                query.Mobile = entity.Mobile;
                query.TrueName = entity.TrueName;
                query.Remark = entity.Remark;
    
                DataContext.Set<UserInfo>().Attach(query);
                DataContext.Entry(query).State = EntityState.Modified;
                DataContext.SaveChanges();
            }

     三,根据上面的逻辑,我们是不是可以修改仓储的GetById方法?代码如下:

         public virtual T GetById(Guid id)
            {
                 T t = _dbset.Find(id);
                DataContext.Entry<T>(t).State = EntityState.Detached;
                return t;
            }
        public virtual T Get(Expression<Func<T, bool>> where)
            {
                return _dbset.AsNoTracking().Where(where).FirstOrDefault<T>();
            }

    而这也是通过的,通过查询状态和修改为不跟踪

    综上:三种方法都可以结果这个问题

  • 相关阅读:
    Go Revel
    Go Revel
    Go Revel
    Go Revel
    deployment:声明式的升级应用
    Kubernetes架构及相关服务详解
    Docker 安装MySQL
    日志收集-Elk6
    Jenkins-Multijob plugin多任务串并行
    ansible创建vmware虚拟机
  • 原文地址:https://www.cnblogs.com/May-day/p/5379246.html
Copyright © 2011-2022 走看看