【问题标题】:EF 5.0 Trouble updating entity which is already trackedEF 5.0 更新已被跟踪的实体时出现问题
【发布时间】:2013-02-28 10:02:42
【问题描述】:

我将用以下内容作为这个问题的开头:我知道互联网上有一百万篇关于“ObjectStateManager 中已经存在具有相同键的对象”问题的旧帖子。我想我的场景有点复杂。

我有一个 UnitOfWork 类,它创建一个 DbContext 并将其传递给任何被调用的存储库。我使用的模式与 ASP.NET 站点上的 Unit of Work 教程密切相关。与教程不同,我的存储库接收业务实体,将它们映射到数据实体,并执行一些 CRUD 操作。我的业务逻辑仅适用于业务实体。这是我在示例 Business Manager 类中尝试做的事情:

_unitOfWork.Repository.Add(entity);
_unitOfWork.Save(); // context.SaveChanges() under the hood

...Perform some operations on the model...

_unitOfWork.Repository.Update(entity);
_unitOfWork.Save();

这是来自存储库的示例更新方法:

public virtual void Update(entity)
{
  var dataEntity = // map from business entity to data;

  _context.Entry(dataEntity).State = EntityState.Modified;
}

它显然在最后一行失败了。这是我的困惑所在:

  • 实体的状态已分离
  • 当我尝试将状态更改为已修改或未更改时,它给了我上面的 ObjectStateManager 异常。
  • 当我尝试从上下文中分离实体时 (((IObjectContextAdapter)_context).ObjectContext.Detach(entity);) 我得到一个关于实体未附加到上下文的异常,因此它无法分离它.非常混乱(我肯定错过了一些基本的东西)。
  • 许多其他帖子建议我进行数据库调用,更新存储库中的实体,然后 _unitOfWork.Save()。我不喜欢这种方法。我不需要进行不必要的网络调用来更新实体。

存储库中的 Update 方法需要处理两种情况:1) 更新当前未被上下文跟踪的实体,以及 2) 更新当前被上下文跟踪的实体。第二部分是我正在努力解决的问题。

感谢任何帮助或见解。

谢谢!

【问题讨论】:

    标签: asp.net entity-framework entity-framework-5


    【解决方案1】:

    这意味着已经有一个对象附加到上下文中,其键与新的dataEntity 相同。现有对象和新实体都表示数据库中的相同条目,但它们是两个不同的对象。

    这可能表明你的_context 的生命周期太长了,但是从你的代码中很难判断。可以肯定的是,该上下文先前用于从数据库中获取实体,该实体随后被 var dataEntity = ... 复制。

    你可能不得不缩短上下文的生命周期,我不知道。如果您认为没问题,您可能需要使用Local 集合来检查实体是否已经存在。这将节省 Find 仍可能进行的数据库往返。

    【讨论】:

      【解决方案2】:

      我找到了一个似乎可行的混合解决方案:

      public virtual void Update(TB entity)
              {
                  var dataEntity = Mapper.Map<TB, TD>(entity);
      
                  var pkey = _dbSet.Create().GetType().GetProperty("Id").GetValue(dataEntity);
                  var entry = _context.Entry(dataEntity);
      
                  if (entry.State == EntityState.Detached)
                  {
                      var attachedEntity = _dbSet.Find(pkey);
      
                      if (attachedEntity != null)
                      {
                          var attachedEntry = _context.Entry(attachedEntity);
                          attachedEntry.CurrentValues.SetValues(dataEntity);
                      }
                      else
                      {
                          entry.State = EntityState.Modified;
                      }
                  }
                  else
                  {
                      entry.State = EntityState.Modified;
                  }
              }
      

      【讨论】:

        猜你喜欢
        • 2021-08-13
        • 2018-12-24
        • 1970-01-01
        • 1970-01-01
        • 2015-05-08
        • 1970-01-01
        • 2021-08-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多