ObjectStateManager中已存在具有相同键的对象

时间:2013-02-26 10:29:42

标签: c# entity-framework

我有一个无法找到解决方案的场景,需要一些帮助 我怎样才能做到这一点, 我想获取客户的当前记录修改它而不是更新我想将新记录添加到表中以获取历史更改信息

    client c = new client();
    using (DBEntities db = new DBEntities())
    {
        // get current records in the client table for client
        IQueryable<client> co = from p in db.client where p.CUS_NUMBER == scd.cus_number && p.isCurrent == true select p;

        c = co.First();

        //update email and and address
        c.EMAIL = Helper.CleanInput("mymail@mm.com");
        c.ADDRESS = Helper.CleanInput("123 Sheppard");

        //instead of updating current record I'd like to add new record to the table to keep historical changes
        db.AddToclient(c);
        db.SaveChanges();
        //I get error that 
        //An object with the same key already exists in the ObjectStateManager. 
        //The existing object is in the Modified state. An object can only be added to 
        //the ObjectStateManager again if it is in the added state.

完成错误

  

ObjectStateManager中已存在具有相同键的对象。现有对象处于Modified状态。如果对象处于添加状态,则只能再次将其添加到ObjectStateManager。

4 个答案:

答案 0 :(得分:1)

删除此代码db.AddToclient(c);,休息一切正常,您已经通过其引用访问该对象,因此无需再次添加它。当您调用savechanges()

如果要添加新对象c = co.First().Clone();

,请使用克隆

答案 1 :(得分:0)

db.AddToclient(c);给出错误的原因是因为对象上下文正在跟踪此对象,可能是在数据库中。

完成您要做的事情的最佳方法如下:

var newClient = new client()
{
    EMAIL = Helper.CleanInput("mymail@mm.com"),
    ADDRESS = Helper.CleanInput("123 Sheppard"),
};

db.AddToclient(newClient);
db.SaveChanges();

答案 2 :(得分:0)

看起来你正在向数据库中添加相同的行,并且由于添加了同一行,而且具有DB不允许的相同主键,所以会出现错误。

尝试添加新行并创建另一个表,将旧行和引用的历史信息保存为外键。您可以添加一个布尔字段,用于保存有关删除的信息,让它为IsDeleted。

希望它会有所帮助 谢谢

答案 3 :(得分:0)

在Entity Framework中,ObjectContext实例会跟踪从数据库默认检索的所有对象。实体框架在内部映射由其密钥跟踪的所有对象。此pattern称为Identity Map。这意味着每个键只有一个实体实例。因此,您不需要再次调用Add,因为该实体已经在EF地图上。您只需要调用SaveChanges来保留修改后的实体。

在你的情况下,你是:

1 - 创建EF ObjectContext的新实例;
2 - 在LINQ查询中检索实体;
3 - 更改检索到的实体的属性值;
4 - 再次添加到ObjContext;的 //错误!
5 - 调用SaveChanges()

步骤4不是必需的,因为ObjectContext已经知道检索到的对象。