Свойство Id является частью ключевой информации объекта и не может быть изменено - PullRequest
37 голосов
/ 06 июля 2010

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

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

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

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

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

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

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.

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

Ответы [ 14 ]

24 голосов
/ 13 сентября 2012

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

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

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

Contact contact = dbContext.Contacts.Single(c => c.contactTypeId == 1234);
contact.contactTypeId = 4;
dbContext.AddObject(contact);
dbContext.SaveChanges();
15 голосов
/ 06 июля 2010

У сущности, созданной платформой, нет свойства contact.ContactTypeId. Он автоматически удалил его и создал связь ContactType внутри сущности Contact.

Способ заставить его работать, как вы предлагали, состоит в создании объекта ContactType путем запроса базы данных и назначения его для contact.ContactType. Например:

Contact contact = dbContext.Contacts.Single(c => c.Id == 12345);
ContactType contactType = dbContext.ContactType.Single(c => c.Id == 3);
contact.ContactType = contactType;
5 голосов
/ 06 июля 2010

Попробуйте

contact.ContactType = differentContactType;

или

contact.ContactTypeId = 3;

Вы пытаетесь установить Id для ContactType (контакта) на 3.

3 голосов
/ 21 ноября 2012

Это происходило, когда я редактировал связанные объекты в двух разных контекстах одновременно.Пример:

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 голосов
/ 22 октября 2017

сначала удалить следующее добавление

для простого

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 голосов
/ 03 июня 2017

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

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

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

Свойство «Код» является частью ключевой информации объекта и не может быть изменено.

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

<Key>
        <PropertyRef Name="ID" />
</Key>
2 голосов
/ 18 января 2012

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

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

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

<PropertyRef Name="contactTypeID" />

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

Следовательно, остается как:

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

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

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

1 голос
/ 08 февраля 2018

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

<PropertyRef Name="id" />

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

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

обратите внимание, что ответ Юргена Финка - работа вокруг

1 голос
/ 21 июня 2016

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

Common.DataContext.Detach(object);

Работай как шарм

1 голос
/ 11 июля 2010

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

// опция 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);
...