ObjectStateManager 中已存在具有相同键的对象.ObjectStateManager 无法跟踪具有相同键的多个对象 [英] An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

查看:38
本文介绍了ObjectStateManager 中已存在具有相同键的对象.ObjectStateManager 无法跟踪具有相同键的多个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用具有通用存储库模式的 EF5 和 ninject 进行依赖注入,并在尝试使用我的 edmx 的存储过程将实体更新到数据库时遇到问题.

Using EF5 with a generic Repository Pattern and ninject for dependency injenction and running into an issue when trying to update an entity to the database utilizing stored procs with my edmx.

我在 DbContextRepository.cs 中的更新是:

my update in DbContextRepository.cs is:

public override void Update(T entity)
{
    if (entity == null)
        throw new ArgumentException("Cannot add a null entity.");

    var entry = _context.Entry<T>(entity);

    if (entry.State == EntityState.Detached)
    {
        _context.Set<T>().Attach(entity);
        entry.State = EntityState.Modified;
    }
}

从我的 AddressService.cs 返回到我的存储库:

From my AddressService.cs which goes back to my repository I have:

 public int Save(vw_address address)
{
    if (address.address_pk == 0)
    {
        _repo.Insert(address);
    }
    else
    {
        _repo.Update(address);
    }

    _repo.SaveChanges();

    return address.address_pk;
}

当它遇到 Attach 和 EntityState.Modified 时,它会因为错误而呕吐:

When it hits the Attach and EntityState.Modified it pukes with the error:

ObjectStateManager 中已存在具有相同键的对象.ObjectStateManager 无法跟踪具有相同键的多个对象.

我浏览了堆栈和互联网上的许多建议,但没有提出任何解决方案.任何解决方法将不胜感激.

I have looked through many of the suggestions in stack and on the Internet and not coming up with anything that resolves it. Any work arounds would be appreciated.

谢谢!

推荐答案

Edit:原始答案使用 Find 而不是 Local.SingleOrDefault.它与@Juan 的 Save 方法结合使用,但它可能导致对数据库进行不必要的查询,并且 else 部分可能从未执行过(执行 else 部分会导致异常,因为 Find 已查询数据库,但没有找到实体,因此无法更新).感谢@BenSwayne 发现问题.

Edit: Original answer used Find instead of Local.SingleOrDefault. It worked in combination with @Juan's Save method but it could cause unnecessary queries to database and else part was probably never executed (executing the else part would cause exception because Find already queried the database and hadn't found the entity so it could not be updated). Thanks to @BenSwayne for finding the issue.

您必须检查具有相同键的实体是否已被上下文跟踪并修改该实体而不是附加当前实体:

You must check if an entity with the same key is already tracked by the context and modify that entity instead of attaching the current one:

public override void Update(T entity) where T : IEntity {
    if (entity == null) {
        throw new ArgumentException("Cannot add a null entity.");
    }

    var entry = _context.Entry<T>(entity);

    if (entry.State == EntityState.Detached) {
        var set = _context.Set<T>();
        T attachedEntity = set.Local.SingleOrDefault(e => e.Id == entity.Id);  // You need to have access to key

        if (attachedEntity != null) {
            var attachedEntry = _context.Entry(attachedEntity);
            attachedEntry.CurrentValues.SetValues(entity);
        } else {
            entry.State = EntityState.Modified; // This should attach entity
        }
    }
}  

如您所见,主要问题是 SingleOrDefault 方法需要知道找到实体的键.您可以创建公开密钥的简单接口(在我的示例中为 IEntity),并在您希望以这种方式处理的所有实体中实现它.

As you can see the main issue is that SingleOrDefault method needs to know the key to find the entity. You can create simple interface exposing the key (IEntity in my example) and implement it in all your entities you want to process this way.

这篇关于ObjectStateManager 中已存在具有相同键的对象.ObjectStateManager 无法跟踪具有相同键的多个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆