【问题标题】:The property 'Id' is part of the object's key information and cannot be modified属性“Id”是对象的关键信息的一部分,不能修改
【发布时间】:2011-03-12 09:43:39
【问题描述】:

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

我有两张桌子:

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

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

  1. 联系人:Id、Value、ContactType(导航属性)
  2. ContactType:Id、Type、Contact(导航属性)

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

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.

看起来很简单!没看懂!

【问题讨论】:

标签: c# foreign-keys entity-framework-4


【解决方案1】:

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

** 这个问题经常发生在循环内部。如果您使用的是 while 或 foreach 循环,请确保将 New Created Object 置于循环体中。

试试这个:

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

【讨论】:

  • 就我而言,只需在循环内移动对象并相应地增加 ID 即可解决问题。非常感谢!!!!!!
  • new Contact(); 是一个冗余初始化器!
【解决方案2】:

框架创建的实体没有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;

【讨论】:

  • 对不起,我在做 linq-sql 而不是 EF。
【解决方案3】:

试试

contact.ContactType = differentContactType;

contact.ContactTypeId = 3;

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

【讨论】:

    【解决方案4】:

    你应该添加

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

    .SaveChanges();之后

    【讨论】:

    • 当我添加这个时,我似乎得到一个新的错误,“一个实体对象不能被多个 IEntityChangeTracker 实例引用。”,我也只在这种情况下使用 1 个上下文,不确定是什么正在进行中。
    • 非常感谢。
    【解决方案5】:

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

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

    我的案例有点复杂(因为这显然很愚蠢),但本质上这导致了我的案例中的错误。

    【讨论】:

      【解决方案6】:

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

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

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

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

      解决方案:从 EF 图中删除表并转到您的数据库,在产生问题的表上添加主键,然后将表重新添加到 EF 图中,现在它只有一个键,即

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

      【讨论】:

        【解决方案7】:

        我正在使用 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) second PropertyRefsecond line)。

        我刚刚删除了第二个PropertyRef

        <PropertyRef Name="contactTypeID" />
        

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

        因此,仍然是:

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

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

        因此,检查数据模型的 XML 以验证只有您的 PK 被列为 PropertyRef 是个好主意。为我工作... :-)

        【讨论】:

          【解决方案8】:

          首先删除 下一个添加

          简单

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

          【讨论】:

            【解决方案9】:

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

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

            所以只要把属性放回原处,一切就又恢复了!

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

            【讨论】:

              【解决方案10】:

              有两种类型的关联。相关键仅作为导航属性显示的独立关联。第二个是外键关联,可以使用外键和导航属性更改相关键。因此,您可以执行以下操作。

              //选项1通用选项

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

              选项2外键选项

              contact.ContactTypeId = 3;
              

              //通用选项与外键和独立关联一起使用

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

              【讨论】:

                【解决方案11】:

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

                Common.DataContext.Detach(object);
                

                像魅力一样工作

                【讨论】:

                • 我一直在寻找一个星期,这就是答案!这是克隆项目的方法。这也将摆脱所有主键约束。
                【解决方案12】:

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

                <PropertyRef Name="id" />
                

                但是如果没有设置主键,你会有

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

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

                【讨论】:

                  【解决方案13】:

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

                  【讨论】:

                    【解决方案14】:

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

                    【讨论】:

                      【解决方案15】:

                      在我的例子中,我创建了一个一起声明和初始化的对象。我只是在构造函数中初始化了或者你可以在需要的时候初始化对象。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2015-10-01
                        • 2023-03-29
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多