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

时间:2010-07-06 15:58:53

标签: entity-framework-4 foreign-key-relationship

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

我有两张桌子:

  1. 联系人:Id(主键),Value,ContactTypeId(ContactType的外键)
  2. ContactType:Id(主键),类型(主页,单元格,工作等)
  3. 实体框架创建了以下两个实体:

    1. 联系人:Id,Value,ContactType(导航属性)
    2. ContactType:Id,Type,Contact(Navigation Property)
    3. 我正在使用以下代码获取联系人并更新该特定联系人的联系方式:

      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.
      

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

15 个答案:

答案 0 :(得分:24)

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

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

试试这个:

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

答案 1 :(得分: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;

答案 2 :(得分:5)

尝试

contact.ContactType = differentContactType;

contact.ContactTypeId = 3;

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

答案 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();

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

答案 4 :(得分:2)

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

因为,和你一样,我认为更新表格中的字段(例如在你的情况下:联系)必须很简单,这是由另一个表中的外键引用的(即在你的表中) case: 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列为PropertyRef。为我工作......: - )

答案 5 :(得分:2)

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

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

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

  

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

解决方案:从EF图中删除表,然后转到创建问题的表上的DB add主键,并将表重新添加到EF图中,现在它只有单键,即

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

答案 6 :(得分:2)

首先删除 接下来添加

简单

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";
        }

答案 7 :(得分:1)

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

//选项1通用选项

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

选项2外键选项

contact.ContactTypeId = 3;

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

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

答案 8 :(得分:1)

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

Common.DataContext.Detach(object);

像魅力一样工作

答案 9 :(得分:1)

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

{$event->id}

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

<PropertyRef Name="id" />

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

答案 10 :(得分:0)

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

答案 11 :(得分:0)

在我的情况下,当我删除I​​D字段的KEY属性时出现了错误。

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

因此,只需将属性放回原处,即可使所有内容再次正常工作!

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

答案 12 :(得分:0)

您应该添加

 db.Entry(contact).State = EntityState.Detached;

.SaveChanges()之后;

答案 13 :(得分:0)

对我来说,问题是由于我的表缺少主键引起的,为表设置了PK后问题就消失了

答案 14 :(得分:-2)

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