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