Свойство "Id" является частью ключевой информации объекта и не может быть изменено

Я использую Entity Framework 4.0 и имею глупую проблему, которую я не могу понять.

у меня есть две таблицы:

  1. контакт: Id (первичный ключ), значение, ContactTypeId (внешний ключ к ContactType)
  2. ContactType: Id (первичный ключ), тип (дом, ячейка, работа и т. д.)

Entity Framework создал следующие две сущности:

  1. Контакт: Id, Значение, ContactType (Свойство Навигации)
  2. ContactType: Id, Тип, Контакт (Свойство Навигации)

Я использую следующий код, чтобы получить контакт и обновить тип контакта для этого конкретного контакта:

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.

это выглядит так просто! Я не понимаю!

12 ответов


эта проблема происходит, потому что вы ссылаетесь на один и тот же объект более одного раза. Это не ограничение EF, а скорее функция безопасности, чтобы убедиться, что вы не вставляете один и тот же объект с двумя разными идентификаторами. Поэтому для достижения того, что вы пытаетесь сделать, это просто создать новый объект и добавить созданный объект в базу данных.

* * эта проблема часто возникает внутри циклов. Если вы используете цикл while или foreach, убедитесь, что новый созданный объект находится внутри тело цикла.

попробуйте это:

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

сущность, созданная платформой, не имеет контакта.ContactTypeId свойство. Он автоматически удалил его и создал ассоциацию 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;

попробовать

contact.ContactType = differentContactType;

или

contact.ContactTypeId = 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();

мой случай был немного более запутанным (так как это, очевидно, довольно глупо), но по сути это вызывало ошибку в моем случае.


Я использую EF 4.0 и WPF, и у меня была аналогичная проблема, и .... нашел вопрос, который решил его (по крайней мере, для меня) очень простым способом.

потому что, как и вы, я думал, что должно быть просто обновить поле в таблице (т. е. в вашем случае:контакты), на который ссылается foreignkey из другой таблицы (т. е. в вашем случае:ContactType).

однако сообщение об ошибке: ".... является частью ключевой информации объекта и не может быть изменен." появляется только при попытке обновить первичный ключ (что совсем не входило в мои намерения).

присмотрелся к XML-коду моей EntityModel и нашел его:

<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 из моей базы данных, она добавила в эту самую таблицу (контакты), где я хотел обновить поле (ContactTypeID) a второй PropertyRef (вторая строка).

я только что удалил эту секунду PropertyRef:

<PropertyRef Name="contactTypeID" />

как модели магазине и концептуальная модель и .... вопрос был решен: -)

таким образом, остается, как:

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

обновления и вставки теперь гладко, как ребенок .... :-)

следовательно, хорошая идея проверить XML datamodel, чтобы проверить, что только ваш ПК указан как PropertyRef. Работал на меня ... :-)


другое странное поведение в моем случае у меня есть таблица без первичного ключа.EF сам создает составной первичный ключ, используя все столбцы, т. е.:

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

и всякий раз, когда я делаю любую операцию обновления, она выдает это исключение:

свойство 'Code' является частью ключевой информации объекта и не может быть изменен.

решение: удалите таблицу из диаграммы EF и перейдите в свою БД, добавьте первичный ключ в таблицу, которая создает проблему и повторно добавьте таблицу в диаграмму EF, теперь у нее будет один ключ, т. е.

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

существует два типа ассоциаций. Независимая ассоциация, где связанный ключ будет отображаться только как свойство навигации. Во-вторых, ассоциация внешнего ключа, где связанный ключ может быть изменен с помощью внешнего ключа и свойства навигации. Таким образом, вы можете сделать следующее.

/ / Вариант 1 общий вариант

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

опция 2 внешний ключ опция

contact.ContactTypeId = 3;

//generic option работает с внешним ключом и независимой ассоциацией

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

в моем случае я хочу дублировать объект, но изменить идентификатор, поэтому я использую это

Common.DataContext.Detach(object);

работает


удалить далее добавить

простые

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

просто надеюсь, что это поможет кому-то еще, после борьбы в течение нескольких часов с этим, потому что я знал, что не обновляю ПК, и у меня определенно был ПК. У меня была база данных значения PK в строке меню, чтобы показать текущее значение PK, и это вызывало проблему.


в моем случае я просто установил первичный ключ в таблицу, которая отсутствовала, повторно сделал mappind edmx, и это сработало когда у вас есть первичный ключ, у вас будет только это

<PropertyRef Name="id" />

однако, если первичный ключ не установлен, у вас будет

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

отметим, что Юрген ответил Финк обойти


в моем случае, я создавал объект объявлен и инициализирован вместе. Я просто инициализировал в конструкторе или что вы можете инициализировать объект, когда это необходимо.