我正在使用EF 5.0来创建一个Web,我在处理我的上下文时遇到了一些问题。我使用上下文的所有时间都在使用句子中,因此上下文应该自动处理,但在特定时刻,当我尝试将实体附加到上下文时,我得到下一个错误:
ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。
确定实体未被处置。如何管理这种情况?我是否必须处置ObjectContext以处置实体,或者有没有办法检查实体是否已附加?
问候。
答案 0 :(得分:1)
执行此操作的一种方法是在附加之前分离现有对象。我面前没有VS,所以如果代码不完全正确,我会道歉。
var existingObject = dbContext.Users.Local
.FirstOrDefault(x => x.id = newObject.id);
if (existingObject != null)
{
// remove object from local cache
dbContext.Entry(existingObject).State = EntityState.Detached;
}
dbContext.Users.Attach(newObject);
如果这不能解决问题,你将不得不采用旧的分离对象的方式。
// remove object from local cache
ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
objectContext.Detach(existingObject);
答案 1 :(得分:0)
如果您这样做:
User u;
using (Entities ent = new Entities())
{
u = ent.Users.Single(a => a.ID == 123);
}
using (Entities ent2 = new Entities())
{
//loading the same user
User user2 = ent2.Users.Single(a => a.ID == 123);
//trying to attach the same object with the same key
ent2.Attach(u);
}
然后你会收到这个错误(我还没有测试过这段代码)。
编辑:其中一个解决方案是更改对象的状态:
ent2.Attach(u);
ent2.ObjectStateManager.ChangeObjectState(u, EntityState.Modified);
另一个解决方案是检查实体是否已经附加:
ObjectStateEntry state = null;
if(!ent2.ObjectStateManager.TryGetObjectStateEntry(((IEntityWithKey)u).EntityKey, out state))
{
ent2.Attach(u);
}
答案 2 :(得分:0)
Dispose
并不意味着“重置为出厂设置”。这是一种清理非托管资源(如数据库连接等)的方法。
答案 3 :(得分:0)
问题与处理上下文无关。它甚至与在某处有多个上下文无关。如果这是问题,你会得到“一个实体对象不能被IEntityChangeTracker的多个实例引用”异常,这与你的异常完全不同。
只需一个上下文即可轻松模拟您的异常:
using (var ctx = new MyContext())
{
var customer1 = new Customer { Id = 1 };
var customer2 = new Customer { Id = 1 }; // a second object with the same key
ctx.Customer.Attach(customer1);
ctx.Customer.Attach(customer2); // your exception will occur here
}
导致此异常的问题通常更隐蔽,特别是如果您记住,附加或设置状态(例如Modified
)也会附加您所在实体的对象图中的所有相关实体连接。如果在此图中有两个具有相同键的对象,您也将获得异常,尽管您没有明确附加这些相关实体。
但如果没有关于代码的更多详细信息,就无法找到确切的原因。