'附加类型的实体失败…在尝试更新EF中的类并使用通用存储库时,会出现` `异常
本文关键字:存储 异常 EF 类型 实体 失败 更新 | 更新日期: 2023-09-27 17:50:00
我使用实体框架。我想加载一个实体,编辑它,并将更改保存回数据库中。但是,无论我编辑了外键属性还是简单属性,EF都会给我以下错误:
附加类型为"ClassX"的实体失败,因为另一个相同类型的实体已经具有相同的主键值。当使用"Attach"方法或将实体的状态设置为"Unchanged"或"Modified"(如果图中的任何实体具有冲突的键值)时,可能会发生这种情况。这可能是因为一些实体是新的,还没有接收到数据库生成的键值。在这种情况下,使用"添加"方法或"添加"实体状态来跟踪图形,然后根据需要将非新实体的状态设置为"未更改"或"修改"。
请注意,ClassX
不是我试图更新的类的直接虚拟属性,相反,它是我的类具有导航属性的其他一些类中的虚拟属性。
我读了一些相关的问题。但是我真的不知道我应该如何将它们应用到我自己的问题中,因为我使用的是下面发布的通用存储库。
public class GenericRepository<T> where T : class
{
private EFDbContext context = new EFDbContext();
public IEnumerable<T> GetAll()
{
return context.Set<T>();
}
public void Insert(T entity)
{
context.Set<T>().Add(entity);
context.SaveChanges();
}
public void Update(T entity)
{
context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
}
//removed for brevity
}
我遇到了另一个与虚拟属性相关的问题,我被建议使用ViewModels
和对象到对象映射。
就我所知,有3个选项:
- 使用
ViewModels
和对象到对象映射。我不打算用这个,它真的很痛苦,因为o2o地图库有很多bug。 - 以某种方式使用
reference
。但我不能这样做,因为存储库是通用的。也许我应该使用反射API ? - 删除所有虚拟属性。这实际上是一种选择,因为他们制造的问题比他们解决的要多。
当你将一个实体的State
设置为Modified
时,它也会将State == EntityState.Unchanged
附加到所有子实体(由导航属性引用的实体)。如果你的上下文已经有具有相同键的实体,它将抛出该错误。
如果您希望忽略这些实体,我可以想到以下几个选项:
- 在
Update
中创建一个新的数据上下文,不要担心EntityState.Unchanged
的子实体,因为当您调用SaveChanges
时,它们将被忽略。如果您正在使用某种存储库模式,那么这可能没有意义。 - 在设置
State = EntityState.Modified
之前,先查看不想附加的导航属性并将其设置为null
- 设置
State = EntityState.Modified
后,对于想要忽略的子实体,设置State = EntityState.Detached
编辑
还可以弄清楚为什么上下文首先会有多个具有相同键的子实体。