Обновить часть первичного ключа Entity Framework 4.0

У меня есть таблица с составлением первичного ключа (3 столбца):

UTP_ID (ITEMId)
UTS_ID (CategoryID)
USS_ID (SubCategoryID)

Когда я пытаюсь изменить SubCategory, например, с EF 4, я получаю следующую ошибку:

utl.USS_ID = Convert.ToInt32(ddlSubSetor.SelectedItem.Value);

the property is part of the object key information and cannot be modified

Любые идеи? Почему я не могу его изменить?

Ответ 1

EF реализует карту идентичности между значениями свойств первичного ключа и ссылками на объекты. Он не позволяет изменять ключ для одного и того же экземпляра объекта.

Я бы сделал это с помощью прямого SQL:

objectContext.ExecuteStoreCommand(
    "UPDATE MyTable SET USS_ID = {0} WHERE UTP_ID = {1} AND UTS_ID = {2} AND USS_ID = {3}",
    Convert.ToInt32(ddlSubSetor.SelectedItem.Value),
    utl.UTP_ID, utl.UTS_ID, utl.USS_ID);

Убедитесь, что ваш объект utl отделен от контекста, потому что этот код непосредственно записывается в таблицу базы данных, и сущность не получает никакой информации об этом изменении. Но это позволяет избежать удаления и воссоздания объекта (что может быть невозможно из-за существующих ограничений внешнего ключа в старой строке в базе данных).

Ответ 2

В результате того, что он является частью ключа сущности, объект должен быть удален из контекста и повторно связан с новым значением первичного ключа.

Структура Entity Framework работает с использованием контекста, который управляет состоянием сущностей, набором сущностей (в основном, таблицы) и самой сущностью (строка данных). По мере чтения данных из базы данных она добавляется в коллекцию сущностей, которая, в свою очередь, управляется контекстом для изменения состояния. Изменение ключа Entity действительно удаляет запись из базы данных и вставляет новую. В результате, чтобы изменить ключ сущности, сначала удалите сущность из нее, отделите объект объекта, чтобы разрешить изменение ключа, измените значение первичного ключа и снова присоедините объект к коллекции. Наконец, вызовите сохранение изменений в контексте, чтобы применить изменения к базе данных.

Следующий код должен давать желаемые результаты:

Context.UTLs.DeleteObject(utl);
Context.UTLs.Detach(utl);
Context.SaveChanges();
utl.USS_ID = Convert.ToInt32(ddlSubSetor.SelectedItem.Value);
Context.UTLs.AddObject(utl).
Context.SaveChanges();