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

时间:2017-10-11 11:58:47

标签: c# asp.net entity-framework entity-framework-6

我正在编写一个asp.net控制台应用程序,它从.csv文件读取值并相应地更新我们的数据库。 在这段代码中,我基于.csv文件中的值创建了一个新的Contact实例。 如果Contact表包含相同的联系人(与类似的电子邮件联系),则更新现有联系人,但如果该联系人不存在则创建一个新联系人。这是我的代码: -

Contact contact = new Contact()
{
    RecordId = fields[RecordIdIndex],
    Salutation = fields[SalutationIndex],
    firstName = fields[FirstNameIndex],
    LastName = fields[LastNameIndex],
    Organization = fields[OrganizationIndex],
    Title = fields[TitleIndex],
    Phone = fields[PhoneIndex],
    Email = fields[EmailIndex],
    // Properties go here...
};

if (!String.IsNullOrEmpty(contact.Email) && entities.Contacts.Any(a => a.Email.ToLower() == contact.Email.ToLower()))
{
    // Contact already exists. Remove old.
    var dbcontact = entities.Contacts.FirstOrDefault(a => a.Email.ToLower() == contact.Email.ToLower());
    int contactid = dbcontact.ID;
    dbcontact = contact;
    dbcontact.ID = contactid;
    entities.Entry(dbcontact).State = EntityState.Modified;
}
else 
{
    entities.Contacts.Add(contact);
}

entities.SaveChanges();

Contact.ID是一个数据库ID,在.csv文件中不存在。 上面的代码将引发以下异常: -

  

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

但我不确定为什么会这样。我只有2个Contact对象,一个用ID=0表示.csv文件中的联系信息,另一个是dbcontact。这是对的吗?

1 个答案:

答案 0 :(得分:1)

执行dbcontact = contact并不会更改DbContext中的跟踪参考。

在没有代码重复的情况下处理这两种情况的方法很简单:

private void Update(Contact contact, string[] fields)
{
    contact.RecordId = fields[RecordIdIndex];
    contact.Salutation = fields[SalutationIndex];
    contact.firstName = fields[FirstNameIndex];
    contact.LastName = fields[LastNameIndex];
    contact.Organization = fields[OrganizationIndex];
    contact.Title = fields[TitleIndex];
    contact.Phone = fields[PhoneIndex];
    contact.Email = fields[EmailIndex];
    // Properties go here...

    return contact;
};

public void CreateOrUpdate()
{
    if (!String.IsNullOrEmpty(contact.Email) && entities.Contacts.Any(a => a.Email.ToLower() == contact.Email.ToLower()))
    {
        // Contact already exists
        var dbcontact = entities.Contacts.FirstOrDefault(a => a.Email.ToLower() == contact.Email.ToLower());
        Update(dbcontact, fields);
        entities.Entry(dbcontact).State = EntityState.Modified;
    }
    else 
    {
        var contact = new Contact();
        Update(contact, fields);
        entities.Contacts.Add(contact);
    }

    entities.SaveChanges();
}