Свойство " Id " является частью ключевой информации объекта и не может быть изменено
Я использую Entity Framework 4.0 и у меня есть глупая проблема, которую я не могу решить.
У меня есть две таблицы:
- Контакте: идентификатор (первичный ключ), стоимость, ContactTypeId (внешний ключ к ContactType)
- тип контакта: Id (первичный ключ), тип (домашний, сотовый, Рабочий и т. д.)
Entity Framework создал следующие две сущности:
- Контакт: Id, Значение, ContactType (Свойство Навигации)
- 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 путем запроса базы данных и назначения его контакту.Контактный тип. Например:
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" />
Обратите внимание, что ответ Юргена Финка-это работа вокруг