除了多个上下文之外,“不能被多个IEntityChangeTracker实例引用”的原因

时间:2014-09-09 11:15:03

标签: c# entity-framework

我有一个基础对象,它在创建时创建一个新的存储库:

    protected static RecRepository rep
    {
        get
        {
            if (_rep == null)
                _rep = new RecRepository();
            return _rep;
        }
    }

从这个继承的对象然后有一个统一的rep对象,我可以使用它,从单个数据库上下文。

到目前为止,此工作正常。但是,我刚刚添加了一个添加新对象的新代码块。存储库代码如下所示:

    public void Counts_Add(Count count)
    {
        if (db.Counts.Any(m => m.CountID == count.CountID))
        {
            db.Entry(count).State = System.Data.EntityState.Modified;
        }
        else
        {
            db.Counts.Add(Count);
        }
    }

调用它的ViewModel继承自我的基础对象,因此有一个可用的代表,它使用该代表 - 因此相同的上下文 - 用于所有数据库操作。到目前为止一切正常。

但是,添加我的新Count对象和SaveChanges()时,我最终会收到错误

An entity object cannot be referenced by multiple instances of IEntityChangeTracker

在我尝试使用多个数据库上下文之前,我才看到过这种情况。但在这种情况下,我无法看到这可能是问题的根源。

所以 - 我认为我的基础对象静态属性将确保子对象上的所有操作都使用相同的上下文吗?如果是这样,那么有什么其他可能的错误原因呢?谷歌只是不断提出不同情况下同一个对象被操纵的情况,因为这是最常见的原因。

1 个答案:

答案 0 :(得分:0)

只是为了检查,你能试试这段代码:

private static Object thisLock = new Object();

protected static RecRepository rep
{
    get
    {
        lock ( thisLock ) {
            if (_rep == null)
                _rep = new RecRepository();
        }
        return _rep;
    }
}

===== ===== ===== ===== ===== =====

imho代码触发如下:

    // <summary>
    // When attaching we need to check that the entity is not already attached to a different context
    // before we wipe away that context.
    // </summary>
    private void VerifyContextForAddOrAttach(IEntityWrapper wrappedEntity)
    {
        if (wrappedEntity.Context != null
            && wrappedEntity.Context != this
            && !wrappedEntity.Context.ObjectStateManager.IsDisposed
            && wrappedEntity.MergeOption != MergeOption.NoTracking)
        {
            throw new InvalidOperationException(Strings.Entity_EntityCantHaveMultipleChangeTrackers);
        }
    }

我最好的猜测是:count参数对应于现有实体。 Count对象在具有相同CountID的上下文中。 db.Entry(count)添加一个新的Count实体,该实体应该会混淆跟踪器。

所以试试:

public void Counts_Add(Count count)
{
    if (db.Counts.Any(m => m.CountID == count.CountID))
    {
        Count c = db.Counts.Local.Where(m => m.CountID == count.CountID).FirstOrDefault();
        if ( c!= null ) {
            ((IObjectContextAdapter)db).ObjectContext.Detach(c);
        }
        db.Entry(count).State = System.Data.EntityState.Modified;
    }
    else
    {
        db.Counts.Add(Count);
    }
}

===== ===== ===== ===== ===== ===== =====

触发此异常的唯一另一点是来自此代码:

    // <summary>
    // When attaching we need to check that the entity is not already attached to a different context
    // before we wipe away that context.
    // </summary>
    private void VerifyContextForAddOrAttach(IEntityWrapper wrappedEntity)
    {
        if (wrappedEntity.Context != null
            && wrappedEntity.Context != this
            && !wrappedEntity.Context.ObjectStateManager.IsDisposed
            && wrappedEntity.MergeOption != MergeOption.NoTracking)
        {
            throw new InvalidOperationException(Strings.Entity_EntityCantHaveMultipleChangeTrackers);
        }
    }