当前位置: 首页 > 知识库问答 >
问题:

将实体附加到上下文失败,因为它已经存在

廖鸿达
2023-03-14

我使用CodeCamper的统一工作和通用存储库。

要更新实体,通用回购具有:

    public virtual void Update(T entity)
    {
        DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
        if (dbEntityEntry.State == EntityState.Detached)
        {
            DbSet.Attach(entity);
        }  
        dbEntityEntry.State = EntityState.Modified;
    }

web api方法:

    public HttpResponseMessage Put(MyEditModel editModel)
    {
        var model = editModel.MapToMyEntity();
        _myManager.Update(model);
        return new HttpResponseMessage(HttpStatusCode.NoContent);
    }

更新方法:

    public void Update(MyEntity model)
    {
        Uow.MyEntities.Update(model);
        Uow.Commit();
    }

在工作单位中:

IRepository<MyEntity> MyEntities { get; }

更新实体时,我收到以下错误:

附加信息:附加“X”类型的实体失败,因为另一个相同类型的实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则使用“附加”方法或将实体的状态设置为“未更改”或“修改”时可能会发生这种情况。这可能是因为某些实体是新的并且尚未收到html" target="_blank">数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态来跟踪图,然后根据需要将非新实体的状态设置为“未更改”或“修改”。

>

  • 当它是您调用存储库的第一个方法时,更新工作正常。(我创建了一个id已经在DB中的实体并调用了Update。)

    如果在更新实体之前获取实体,则更新不起作用。(例如,我获取一个实体X,将其转换为DTO,然后更改UI中的一些值,然后调用一个web api,该api使用新值创建实体X,并调用存储库的更新。)

    有什么办法避免这种情况吗?当你有一个CRUD应用程序时,你总是在更新之前调用get。

  • 共有2个答案

    敖硕
    2023-03-14

    我也有同样的问题。问题的背景是复杂的。当您在context1中从DB读取实体时。然后,如果可以使用contex2(具有自己实体缓存的相同上下文的其他实例)更新此实体。这可能引发异常。

    请检查参考资料:

    按上下文1:从DB读取引用了entity2的entity1

    通过context2:从DB读取entity2。然后更新entity1(使用context1中引用的entity2)。

    当您尝试将引用了entity2的entity1附加到context2时,会引发异常,因为context2中已经存在entity2。

    解决方案是对此操作仅使用一个上下文。

    段曦
    2023-03-14

    我正在使用自己的附加方法:

    public void Attach<E>(ref E entity)
    {
        if (entity == null)
        {
            return;
        }
    
        try
        {
            ObjectStateEntry entry;
            bool attach = false;
            if (ObjectStateManager.TryGetObjectStateEntry(CreateEntityKey(entitySetName, entity), out entry))
            {
                attach = entry.State == EntityState.Detached;
    
                E existingEntityInCache = (E)entry.Entity;
                if (!existingEntityInCache.Equals(entity))
                {
                    existingEntityInCache.SetAllPropertiesFromEntity(entity);
                }
                entity = existingEntityInCache;
            }
            else
            {
                attach = true;
            }
            if (attach)
                objectContext.AttachTo(entitySetName, entity);
        }
        catch (Exception ex)
        {
            throw new Exception("...");
        }
    }
    
     类似资料:
    • 我在代码中偶然发现了一个奇怪的bug。以前是有效的,但现在有时也有效。 我正在使用EF6编辑具有某些关系的实体。为了不编辑关系,我“附加”了它们(参见示例代码)。 我编辑了这些名字以保持简单。 以下行 抛出此错误: 附加类型为“C”的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Mo

    • 我想在我的流量管道中使用,以绕过过滤。 这是我所拥有的: 这是对此的输入: 我可以在没有失败,我甚至可以访问映射,但是当第一次迭代完成时,我得到: 用户断开连接。 所以我的问题是,我是否正确使用了它,这里会有什么问题? 编辑: 我曾尝试当我使用value out of it时: 并将设置为订阅端的上下文,当我需要上游的信号时,只需更改此变量引用中的值,但它根本不会更改: 至少重复不会断开连接,但我

    • 错误消息:附加类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。 问题:我如何以类似于下面代码中AttachActivity方法所示的方式附加实体? 我必须假设上面错误消息的“另一个实体”部分指的是内存中存在但超出范围的对象(?)。我之所以注意到这一点,是因为我尝试附加的实体类型的DBSet的本地属性返回零。 我有理由相信实体不存在于上下文中,因为我遍历代码并在创建上下文时观察上下文。实

    • 错误消息: 正在附加“FaridCRMData”类型的实体。模型。“Customer”失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的 我的代码: FactorService. BaseService.cs:

    • 我的WebApi应用程序有一个小问题。当我将新实体添加到我的数据库时,会出现这个问题。 实体: 要在其中向数据库中添加新赌注实体的代码: 在此位置,将我的实体添加到DB中(DB:我的SQL) 调用save方法时,代码会引发以下异常: 附加“WebCar. Domain. Entities. Lot”类型的实体失败,因为另一个相同类型的实体已经具有相同的主键值。如果图形中的任何实体具有冲突的键值,则

    • 让我快速描述一下我的问题。 我有5个客户的5个数据库,每个数据库都有一个名为SubnetSettings的表。 我已经创建了一个下拉列表来选择一个客户,并将显示属于所选客户的SubnetSSet表,并允许我创建、编辑和删除。 我可以毫无问题地创建、删除,但当我想编辑数据时,它会带来错误: /运输管理系统应用程序中的服务器错误。 附加“CFS”类型的实体。领域实体。SubnetSettings“失败