Обновление значения первичного ключа с использованием структуры сущностей

Я пытаюсь обновить одно значение составного первичного ключа изнутри структуры сущности, и я получаю эту ошибку: "Свойство CustomerID является частью информации о ключе объекта и не может быть изменено".

Вот мой код:

Dim customer As Customer = (From c In db.Customer Where c.CustomerID = "xxx" AndAlso c.SiteKey = siteKey).FirstOrDefault
customer.CustomerID = "fasdfasdf"
db.SaveChanges()

Это кажется слишком простым. Верно ли, что вы не можете обновить первичный ключ в рамках сущности? Я не могу найти документацию по этой теме. Спасибо!

Ответ 1

Вы не можете и не зря. См. Комментарии KM.

Одна вещь, которую я могу сказать, это сделать две таблицы с анонимными данными и одну, которая хранит реальные пользовательские данные после входа в систему.

Или ваш способ (не проверенный или когда-либо сделанный мной) имеет такой вид таблицы:

---Customers----
AutoNumber PK <- This links to all other tables in your database, and does NOT change.
CustomerID  <- This can change.
CustomerType <- Anonymous or logged in.  

И при входе в систему вы меняете CustomerType и CustomerID на то, что вам нужно.

Таким образом, ваш запрос может выглядеть так:

Dim customer As Customer = (From c In db.Customer _
                            Where c.CustomerID = {Some temp ID} _
                            AndAlso c. CustomerType = "Anonymous").FirstOrDefault
// After user logs in.
customer.CustomerID = {Make a new user ID here}
customer.CustomerType = "LoggedIn" {or what ever}
db.SaveChanges()

Обратите внимание, что первичный ключ autonumber никогда не изменяется. Это так, что все таблицы, которые у вас есть в отношениях с таблицей Customers, по-прежнему работают, и не нужно делать каскадные обновления первичного ключа (что похоже на то, что вы наносили карандаш себе в глаза).

Ответ 2

У меня есть доктор философии. в cs - в области баз данных, поэтому этот ответ будет немного отличаться от перспективы программистов. При всем уважении к Оливеру Ханаппи, ключ может и изредка меняться, если он не является суррогатным ключом. Например. Естественный ключ или композитный ключ. Например. В США можно изменить ваш SSN. Но многие программисты на протяжении многих лет считают это неизменным ключом и используют его как таковой. Гораздо чаще происходит изменение составного первичного ключа, состоящего из внешних ключей.

Я имею дело с базой данных, которая имеет тройственные отношения. В частности, три объекта (с внешними ключами, являющимися суррогатными первичными ключами в соответствующих таблицах). Однако для сохранения взаимосвязи между двумя объектами при изменении третьего объекта требуется изменить часть таблицы пересечений (также называемой чистой таблицей соединений в MSDN). Это допустимая конструкция и может быть улучшена только путем удаления таблицы пересечений тройных отношений и замены ее двумя бинарными таблицами отношений (которые могут иметь свои собственные суррогатные ключи). EF справится с этим штрафом. Это изменение дизайна сделало бы модель (Many- > many) → many или Parent1-Parent2 → Child-grandchild (если это не ясно, прочтите пример ниже). Структура Entity будет хорошо работать с этим, поскольку каждая взаимосвязь действительно является одной из многих отношений. Но это сумасшедший дизайн с точки зрения БД. Позвольте мне показать вам пример.

Считайте, что курс, класс и инструктор связаны друг с другом в классе. Класс может включать в себя: CourseID, ClassroomID, InstructorID как внешние ключи и содержать составной первичный ключ, включая все три. Хотя ясная, краткая троичная модель (трехсторонние отношения), мы можем разбить ее на двоичные отношения. Это даст две таблицы пересечений. Добавление суррогатных ключей будет удовлетворять EF следующим образом:

Класс ( SurrogateKeyClass, InstructorID, CourseID)

ClassRoomUsed ( SurrogateKeyClassroomUsed, SurrogateKeyClass, ClassRoomID)

Проблема с этим дизайном заключается в том, что мы могли бы иметь один и тот же курс и инструктор, связанные несколько раз, которые предыдущая модель избегает. Чтобы избежать этой проблемы, вы можете добавить ограничение в базе данных для уникальности двух полей ID, но почему вы хотите сделать это, когда имеете дело только с суррогатными ключами? Однако это решение будет работать как можно лучше. Однако это не логическая база данных из-за уникального уникального ограничения, требуемого в БД.

НО, если вы не хотите менять свою базу данных или не можете изменить свою базу данных, вот второе решение: таблицы Intersection/association - это только ссылки, связывающие две сущности или более вместе. Если кто-то изменится, удалите ассоциацию и заново создайте новую, у которой есть соответствующие внешние ключи (свойства навигации). Это означает, что вам не будет позволено требовать дочерние объекты в любых отношениях, но это чрезвычайно распространено.

Я бы предположил, что Entity Framework (в будущем) позволит тем из нас, кто может проектировать элегантную модель БД, чтобы изменить части ключей в таблицах пересечения/ассоциации, когда мы хотим!

Другой пример бесплатно:

Рассмотрим студенческую, курсную, классную ассоциацию. Студенты связаны с курсом через класс. Обычно это многозначная связь между Студентом и Курсом с дополнительным полем в таблице ассоциаций, называемой оценкой (таблицы ассоциаций содержат данные полезной нагрузки, такие как оценка, таблицы пересечений, не имеют полезной нагрузки и в MSDN указаны как чистые таблицы объединений в аренда в одном месте):

Студент ( StudentID,....)

Курс ( CourseID,...)

Взятие ( StudentID, CourseID, оценка)

Если кто-то делает ошибку ввода данных из раскрывающегося списка и ставит ученика в неправильный класс, вам нравится, чтобы он впоследствии его менял, выбирая выпадающее меню и выбрав другой курс. В фоновом режиме вам нужно будет удалить объект EF из таблицы "Захват" и воссоздать его, не теряя оценку, если таковой имеется. Простое изменение внешнего ключа CourseID кажется лучшей альтернативой. Придумайте свою собственную ассоциацию, если это кажется надуманным, но, как профессор, это было естественно для меня.

Заключение. Если у вас есть последовательность отношений, лучше не разрешать каскадирование и/или изменение FK, но существуют резонансные/логические сценарии, где это необходимо, даже если они не рекомендуются в качестве наилучшей практики в целом.

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

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

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

Ответ 3

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

Однако, если вам действительно нужно это сделать, вы можете написать хранимую процедуру, которая обновляет первичный ключ, а затем выполнить хранимую процедуру из фреймворка сущности.

Ответ 4

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

Итак, просто не делайте этого, есть другие способы выполнить то, что вы пытаетесь сделать.