无法使用已在使用的密钥添加实体

时间:2010-01-11 14:12:41

标签: linq-to-sql

我有这个奇怪的错误Cannot add an entity with a key that is already in use 但是,对于这个错误而言,非常烦躁的是,用户没有被剥夺 - 谁?什么?什么表?什么记录是这个错误的罪魁祸首?

如果你在.Submit()

之前对LINQ对象进行了很多操作,确定它会非常复杂

有没有办法确定导致此错误的原因?

4 个答案:

答案 0 :(得分:10)

当您在具有外键关系且外键记录已存在的MetaTable中创建新记录时,通常会发生此错误。

例如,假设您有一个Contact表和一个Address表,每个Contact可以包含多个Addresses。创建新的联系人记录并尝试手动将现有地址记录与该新联系人关联时,会发生此错误。

假设传递的地址ID表示现有的地址记录,则不起作用:

public class Contact
{
    public int Contact_ID { get; set; }
    public string Name { get; set; }
    public Address ContactAddress { get; set; }
    public string Phone { get; set; }
}

public class Address
{
    public int Address_ID { get; set; }
    public string Street { get; set; }
    public string CityState { get; set; }
    public string ZIP { get; set; }
}

public void CreateNewContact(int addressID)
{
    Contact contact = new Contact();

    contact.Name = "Joe Blough";
    contact.ContactAddress.Address_ID = addressID;
    contact.Phone = "(555) 123-4567";

    DataContact.SubmitChanges();
}

从历史上看,SQL开发人员经过培训只需传递ID值即可实现魔术。使用LINQ-to-SQL,因为数据库活动是抽象的,所以我们必须传递整个对象,以便LINQ引擎能够正确地反映ChangeSet中的必要更改。在上面的示例中,LINQ引擎假定您要求创建一个新的Address记录,因为在创建SubmitChanges时它没有一个可以使用它,并且它必须遵守由外键关系建立的合同。它使用传递的ID值创建一个空白的地址记录。发生此错误的原因是该ID值已存在于数据表中,并且ChangeSet未将地址增量标记为更新。

修复是传递整个记录,而不仅仅是ID值:

contact.ContactAddress = DataContext.Addresses.Where(a => a.Address_ID == addressID).Single();

现在,LINQ引擎可以正确地将传入的地址记录标记为现有记录,而不是尝试重新创建它。

答案 1 :(得分:1)

您尝试Attach()Remove()Add()DeleteOnSubmit()的列可能是主键,您尝试再次添加或附加相同的值

此外,您可能正在使用其他方法访问主键或外键值列,并且在尝试调用上述方法时它尚未关闭。

在这些方法Attach()Remove()Add()DeleteOnSubmit()之上,尝试再次创建datacontext的新实例并运行。

答案 2 :(得分:0)

听起来你正在做一个Table.Attach(),你附加的实体有一个L2S已经跟踪的键值。这与物理数据库中的重复密钥无关。

答案 3 :(得分:0)

正如上面的一个答案所解释的,此错误更可能是由于尝试将记录插入到主ID ID字段上具有重复值的表中。您可以通过选择/创建不同的主键来解决问题。