【发布时间】:2015-05-20 06:10:58
【问题描述】:
我正在使用实体框架。我想加载一个实体,对其进行编辑,然后将更改保存回数据库中。但是无论我编辑的是外键属性还是简单属性,EF都会给我以下错误:
附加“ClassX”类型的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后将非新实体的状态设置为“未更改”或“已修改”。
请注意,ClassX 不是我要更新的类的直接虚拟属性,而是我的类具有导航属性的其他一些类中的虚拟属性。
我已阅读 some related 问题。但我并没有真正明白如何将它们应用于我自己的问题,因为我使用的是下面发布的通用存储库。
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
}
我遇到过与虚拟属性相关的another problem,建议我使用ViewModels 和对象到对象的映射。
据我所知,有 3 个选项:
- 使用
ViewModels和对象到对象的映射。这个我就不说了,因为o2o映射库有很多bug,真的很痛苦。 - 不知何故使用
reference。但我不能这样做,因为存储库是通用的。也许我应该为此使用反射 API? - 删除所有虚拟属性。这实际上是一种选择,因为他们制造的问题多于解决的问题。
谁能解释一下为什么会出现这个问题以及解决这个问题的最简单方法是什么?
【问题讨论】:
-
听起来您在更新对象图时遇到了问题。看看 GraphDiff 寻求帮助:blog.brentmckendrick.com/…“映射库有很多错误”——我不同意。 Automapper 和视图模型模式是相当可靠的技术。 lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models
-
"请注意,如果被附加的实体引用了其他尚未被跟踪的实体,那么这些新实体将附加到处于未更改状态的上下文中——它们不会自动被修改。如果您有多个实体需要标记为已修改,您应该分别为每个实体设置状态。” msdn.microsoft.com/en-us/data/jj592676.aspx
-
感谢您的 cmets 和有用的链接,但我仍然不知道如何解决我的问题。如果您能解释一下,我将不胜感激。我应该如何更改我的更新方法?除非绝对必要,否则我不会使用 ViewModels。我不想更改或修改关联实体,我只想让 EF 忽略它们!
标签: c# entity-framework ef-code-first entity-framework-6