ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象

时间:2011-04-15 04:02:50

标签: entity-framework asp.net-mvc-3

我有以下代码来添加或更新Entity对象。根据我添加或更新对象的响应,通过主键查找对象。

添加记录有效,但在更新期间,它给出了此错误消息“ ObjectStateManager中已存在具有相同键的对象.ObjectStateManager无法使用相同的键跟踪多个对象”

在我的MSSQL数据库中,我只有一条记录。

var v = db.Envelopes.Find(model.ReportDate, model.Service);
if (v == null)
{
    db.Envelopes.Add(model);
    db.SaveChanges();
    ViewBag.status = "Record Add successfully";
    ModelState.Clear();
}
else
{
    db.Entry(model).State = EntityState.Modified;
    db.SaveChanges();
}

如何修复此错误消息?

6 个答案:

答案 0 :(得分:88)

如@anon所述,一旦使用相同的密钥加载实体,就无法附加模型。必须将更改应用于附加实体。而不是:

db.Entry(model).State = EntityState.Modified;

使用它:

db.Entry(v).CurrentValues.SetValues(model);

答案 1 :(得分:9)

如果先前的查询读取了要更新的实体,并且这就是您收到错误的原因,则可以将该查询更改为AsNoTracking。请参阅AsNoTracking示例: http://www.asp.net/entity-framework/tutorials/advanced-entity-framework-scenarios-for-an-mvc-web-application

答案 2 :(得分:7)

我假设你说你的错误发生在这里:

db.Entry(model).State = EntityState.Modified;

执行Find()后,您的信封已被您的上下文跟踪。这意味着如果您需要更改属性,只需在v上更改它,然后调用SaveChanges()。不要担心将状态设置为Modified。

答案 3 :(得分:5)

如果您将上下文设置为AsNoTracking(),则会停止aspmvc跟踪内存中实体的更改(这是您在Web上无论如何)。不要忘记使用声明。

using System.Data.Entity;

db.Envelopes.AsNoTracking().Find(model.ReportDate, model.Service);

我从这篇论坛帖子中得到了这个 - > http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/advanced-entity-framework-scenarios-for-an-mvc-web-application

答案 4 :(得分:3)

我正在使用它,因为我已经创建了一个新实例,并填充了我需要更新的属性。

var key=this.CreateEntityKey("Envelopes",model); 
        ObjectStateEntry ose;
        if(this.ObjectStateManager.TryGetObjectStateEntry(key, out ose)){
            var entity=(Page)ose.Entity;
            Envelopes.Detach(entity);
        }
            this.Envelopes.Attach(model);

答案 5 :(得分:0)

另一种解决问题的方法是分离跟踪实体并重新附加修改后的实体。请参阅我的解决方案here