属性“Id”是对象的关键信息的一部分,无法修改

问题描述 投票:37回答:14

我正在使用Entity Framework 4.0并且有一个我无法弄清楚的愚蠢问题。

我有两张桌子:

  1. 联系人:Id(主键),Value,ContactTypeId(ContactType的外键)
  2. ContactType:Id(主键),类型(Home,Cell,Work等)

实体框架创建了以下两个实体:

  1. 联系方式:Id,Value,ContactType(导航属性)
  2. ContactType:Id,Type,Contact(Navigation Property)

我正在使用以下代码获取联系人并更新该特定联系人的联系人类型:

Contact contact = dbContext.Contacts.Single(c => c.Id == 12345);
contact.ContactType.Id = 3;

引发以下异常:

The property 'Id' is part of the object's key information and cannot be modified.

看起来很简单!我不明白!

entity-framework-4 foreign-key-relationship
14个回答
24
投票

出现此问题的原因是您多次引用同一对象。这不是EF的限制,而是一种安全功能,可确保您不会插入具有两个不同ID的同一对象。因此,要实现您要执行的操作,只需创建一个新对象并将新创建的对象添加到数据库中。

**这个问题经常发生在循环中。如果您使用while或foreach循环,请确保将新创建的对象INSIDE循环体。

试试这个:

Contact contact = dbContext.Contacts.Single(c => c.contactTypeId == 1234);
contact.contactTypeId = 4;
dbContext.AddObject(contact);
dbContext.SaveChanges();

1
投票

在我的情况下,我只是将主键设置为缺少的表,重新完成mappind edmx并且当你有主键tou时它确实有效只有这个

Common.DataContext.Detach(object);

但是如果未设置主键,则可以

<PropertyRef Name="id" />

请注意,Juergen Fink的答案是一个解决方案


0
投票

只是希望这有助于其他人,经过几个小时的努力,因为我知道我没有更新PK,我肯定有一个PK。我将PK值数据绑定到菜单栏以显示当前的PK值,这导致了问题。


0
投票

在我的情况下,错误出现,因为我删除了ID字段的KEY属性。

<PropertyRef Name="id" />
<PropertyRef Name="col1" />
<PropertyRef Name="col2" />

所以只需将属性放回原位,让一切都恢复正常!

// [Key]
public long Id { get; set; }

0
投票

你应该添加

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }

在.SaveChanges()之后;


-2
投票

就我而言,我正在创建一个声明并一起初始化的对象。我只是在构造函数中初始化或者在需要时可以初始化对象。


15
投票

框架创建的实体没有contact.ContactTypeId属性。它会自动删除它并在Contact实体中创建ContactType关联。

正如您所建议的那样,让它工作的方法是通过查询数据库并将其分配给contact.ContactType来创建ContactType对象。例如:

Contact contact = dbContext.Contacts.Single(c => c.Id == 12345);
ContactType contactType = dbContext.ContactType.Single(c => c.Id == 3);
contact.ContactType = contactType;

5
投票

尝试

contact.ContactType = differentContactType;

要么

contact.ContactTypeId = 3;

您正尝试将ContactType(联系人)的ID设置为3。


3
投票

当我同时从两个不同的上下文编辑相关对象时,我发生了这种情况。例:

DataContext ctxA = new DataContext();
DataContext ctxB = new DataContext();

Author orwell = new Author {Name = "George Orwell" };
ctxA.Add(orwell);
ctxB.Add(new Book {Name = "1984", Author = orwell});

ctxA.SaveChanges();
ctxB.SaveChanges();

我的情况有点复杂(因为这显然是非常愚蠢的)但实际上这导致了我的错误。


2
投票

我正在使用EF 4.0和WPF,我遇到了类似的问题,....发现问题以一种非常简单的方式解决了它(至少对我而言)。

因为,就像你一样,我认为更新表中的字段(例如在你的情况下:Contact)必须很简单,该字段由另一个表中的外键引用(例如在你的情况下:ContactType)。

但是,错误消息:“....是对象的密钥信息的一部分,无法修改。”仅在您尝试更新主键时出现(根本不是我的意图)。

仔细看看我的EntityModel的XML代码并找到它:

<EntityType Name="Contact">
    <Key>
        <PropertyRef Name="ID" />
        <PropertyRef Name="contactTypeID" />   <!-- This second line caused my problem -->
    </Key>
    <Property Name="ID" Type="int" Nullable="false" />
    ...
    ...
</EntityType>

出于某种原因(也许我在我的数据库中犯了一些愚蠢的错误),当Visual Studio从我的数据库为我自动生成DataModel时,它添加在那个表(Contact)中,我想要更新字段(ContactTypeID)第二个PropertyRef (第二行)。

我刚刚删除了第二个PropertyRef

<PropertyRef Name="contactTypeID" />

在两者中,商店模型和概念模型......问题解决了:-)

因此,仍然像:

<EntityType Name="Contact">
    <Key>
        <PropertyRef Name="ID" />
    </Key>
    <Property Name="ID" Type="int" Nullable="false" />
    ...
    ...
</EntityType>

更新和插入现在像婴儿一样顺利运行.... :-)

因此,最好检查数据模型的XML,以验证只有你的PK被列为qazxsw poi。为我工作...... :-)


2
投票

在我的情况下另一个奇怪的行为我有一个没有任何主键的表.EF本身使用所有列创建复合主键,即:

PropertyRef

每当我执行任何更新操作时,它都会抛出此异常:

属性“代码”是对象的关键信息的一部分,不能修改。

解决方案:从EF图中删除表并转到创建问题的表上的数据库添加主键并将表重新添加到EF图表现在它将具有单个键,即

 <Key>
        <PropertyRef Name="ID" />
        <PropertyRef Name="No" />
       <PropertyRef Name="Code" />
   </Key>

2
投票

首先删除下一个添加

为了简单

<Key>
        <PropertyRef Name="ID" />
</Key>

1
投票

有两种类型的关联。独立关联,其中相关键仅表示为导航属性。第二个是外键关联,其中可以使用外键和导航属性来改变相关键。所以你可以做到以下几点。

//选项1通用选项

public static IEnumerable UserIntakeFoodEdit(FoodIntaked data)
        {
            DBContext db = new DBContext();
            var q = db.User_Food_UserIntakeFood.AsQueryable();
            var item = q.Where(f => f.PersonID == data.PersonID)
                  .Where(f => f.DateOfIntake == data.DateOfIntake)
                  .Where(f => f.MealTimeID == data.MealTimeIDOld)
                  .Where(f => f.NDB_No == data.NDB_No).FirstOrDefault();

            item.Amount = (decimal)data.Amount;
            item.WeightSeq = data.WeightSeq.ToString();
            item.TotalAmount = (decimal)data.TotalAmount;


            db.User_Food_UserIntakeFood.Remove(item);
            db.SaveChanges();

            item.MealTimeID = data.MealTimeID;//is key

            db.User_Food_UserIntakeFood.Add(item);
            db.SaveChanges();

            return "Edit";
        }

选项2外键选项

var contacttype = new ContactType{Id = 3};
db.ContactTypes.Attach(contacttype);
customer.ContactType = contacttype;

// generic选项适用于外键和独立关联

contact.ContactTypeId = 3;

1
投票

在我的情况下,我想复制对象,但更改id,所以我使用它

contact.ContactReference.EntityKey = new EntityKey("container.contactset","contacttypeid",3);

像魅力一样工作

© www.soinside.com 2019 - 2024. All rights reserved.