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


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

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

  1. Контакте: идентификатор (первичный ключ), стоимость, ContactTypeId (внешний ключ к ContactType)
  2. тип контакта: 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 31

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 путем запроса базы данных и назначения его контакту.Контактный тип. Например:

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;

Вы пытаетесь установить идентификатор ContactType (контакта) на 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, и у меня была аналогичная проблема, И.... нашел вопрос, который решил его (по крайней мере, для меня) очень простым способом.

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

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

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

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

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

Решение: удалите таблицу из диаграммы 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. У меня была привязка значения PK к строке меню, чтобы показать текущее значение PK, и это было причиной проблемы.

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

<PropertyRef Name="id" />

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

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

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

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