2017-10-11 76 views
1

我正在编写一个asp.net控制台应用程序,该应用程序从.csv文件读取值并相应地更新我们的数据库。 在此代码中,我将根据.csv文件中的值创建Contact的新实例。 如果联系人表包含相同的联系人(与类似的电子邮件联系),则更新现有联系人,但如果联系人不存在,则创建一个新联系人。这里是我的代码: -ObjectStateManager中已存在具有相同键的对象,ObjectStateManager无法使用相同键追踪多个对象

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。它是否正确?

+0

即使固定时,这可能不是最有效的方式。你期望每个文件更新/插入多个联系人吗? –

+0

@johnG这解决了吗? – aaron

+0

@johnG这解决了吗? – aaron

回答

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(); 
} 
+0

所以你的意思是我得到的错误是,当我做'dbcontact = contact'这将迫使两个对象具有相同的密钥? –

+0

不会。当您执行'dbcontact = contact'时,EF仍在跟踪原始的'dbcontact'。当你做'Entity.Entry(dbcontact).State = EntityState.Modified;'时,EF现在也用同一个键跟踪新的'contact'。 – aaron

+0

@johnG这个问题解决了吗? – aaron

相关问题