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

本文关键字:对象 存在 ObjectStateManager | 更新日期: 2023-09-27 18:01:15

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

    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中已存在具有相同键的对象。现有对象处于"已修改"状态。只有处于已添加状态的对象才能再次添加到ObjectStateManager中。

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

删除此代码db.AddToclient(c);,其余都可以,您已经通过引用访问了对象,因此无需再次添加。当你调用savechanges() 时,它会被修改

或者,如果要添加新对象c = co.First().Clone(); ,请使用克隆

看起来您正在向数据库中添加同一行,但由于再次添加具有相同主键的同一行而出现错误,而DB不允许这样做。

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

希望能有所帮助感谢

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

完成你想做的事情的最好方法如下:

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

在实体框架中,默认情况下从数据库检索的所有对象都由ObjectContext实例跟踪。实体框架在内部映射由其密钥跟踪的所有对象。这种模式被称为身份映射。这意味着每个键将只有一个实体实例。因此,您不需要再次调用Add,因为实体已经在EF映射上了。您只需要调用SaveChanges就可以持久化修改后的实体。

在您的情况下,您是:

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

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