Как обновить поле первичного ключа с помощью linq to SQL?

#asp.net #linq-to-sql

#asp.net #linq-to-sql

Вопрос:

У меня есть tbl_names со следующими полями:

 Id  int
Name nvarchar(10)
family nvarchar(20)


Id    Name    Family
 1     John     Smith
  

и предположим, что Id и name являются первичным ключом вместе (составной первичный ключ).
и я хочу обновить name поле в соответствии со значением Id поля.

 DataclassesContext dac=new DataClassesContext();
var query=from record in Dac.tbl_name where record.id=1 select record;
query.name="Raymond";
Dac.Submitchanges();
  

но я сталкиваюсь со следующей ошибкой:

 Value of member 'co_Workshop' of an object of type 'Tbl_Workshop' changed.
A member defining the identity of the object cannot be changed.
Consider adding a new object with new identity and deleting the existing one instead.
  

Это из-за того, что name поле является первичным ключом? почему я не могу обновить поле первичного ключа с помощью linq?

Комментарии:

1. Я не могу вспомнить, когда я когда-либо обновлял первичный ключ. Не говорю, что у вас нет причин для этого… У меня просто никогда не было. Интересно, что это вам не позволит. Возможно, это потому, что это единственный идентификатор, который он может связать с базой данных? Таким образом, вам пришлось бы создать его копию с обновленным ключом, добавить его и удалить старый.

2. Зачем вам объединенный идентификатор {id, name} ? Почему бы просто не сохранить id уникальность?

3. Я работаю над старой базой данных и не могу изменить ее структуру. да, вы правы, нет причин, но мне это нужно

4. @Micjecito не могли бы вы привести мне пример?

Ответ №1:

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

В вашем случае вы должны удалить и воссоздать PK, чтобы это было просто поле «Id», а затем, если вам нужно повысить производительность при фильтрации запросов по «имени», просто добавьте индекс в поле «имя». Тот факт, что вы используете только поле «Id» для поиска записи, подтверждает эту идею.

РЕДАКТИРОВАТЬ: я ответил до того, как появились комментарии к вопросу. Теперь, когда я вижу комментарий из OP о «это старая база данных и не могу изменить ее структуру», я бы сказал, что если нет FKS, указывающих на этот PK, то это должно быть довольно простым изменением (удалить и воссоздать PK только с полем «Id», как я упоминал выше). Если на него указывают какие-то FKS, то вариант (хотя и не самый лучший вариант, и он может работать не на всех СУБД) заключается в:

  1. Удалите FKS
  2. Удалите PK
  3. Создайте новый PK только в поле «Id»
  4. Создайте УНИКАЛЬНЫЙ ИНДЕКС для «Id» и «Name»
  5. Воссоздайте FK, чтобы указать на УНИКАЛЬНЫЙ ИНДЕКС

Это будет работать на Microsoft SQL Server, и как бы мне не нравилась идея, когда FK указывает на УНИКАЛЬНЫЙ ИНДЕКС, она должна допускать ту же структуру, что и у вас сейчас, плюс LINQ просто увидит единственное поле PK в «Id» и разрешит обновление.

Ответ №2:

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

Ответ №3:

Похоже, что есть способы обойти это, как я упоминал выше. Linq не позволит вам изменить первичный ключ.

http://social.msdn.microsoft.com/Forums/en/linqprojectgeneral/thread/64064c2d-1484-4a00-a2c4-764bcb6b774a

Комментарии:

1. Я пробовал, но нет метода Remove (). DAC.tbl_names.remove()

Ответ №4:

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

Простым решением было не использовать Linq в этом случае, а использовать T_SQL и выполнить простое обновление.

 update tbl_name set name = 'Raymond' where id = 1