1

我将用以下内容作为这个问题的开头:我知道互联网上有一百万篇关于旧的“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)更新当前被上下文跟踪的实体。第二件是我正在努力解决的问题。

任何帮助或见解表示赞赏。

谢谢!

4

2 回答 2

1

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

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

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

于 2013-03-13T07:51:38.200 回答
0

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

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;
            }
        }
于 2013-03-12T18:36:14.840 回答