Невозможно обновить EntitySet - потому что у него есть DefiningQuery и отсутствует элемент <UpdateFunction>

411

Я использую Entity Framework 1 с .net 3.5.

Я делаю что-то простое:

var RoomDetails = context.Rooms.ToList();

foreach (var Room in Rooms)
{        
   Room.LastUpdated = DateTime.Now;
}

Я получаю эту ошибку, когда пытаюсь сделать:

 context.SaveChanges();

Я получаю сообщение об ошибке:

Невозможно обновить EntitySet - поскольку у него есть DefiningQuery и no <UpdateFunction> элемент существует в <ModificationFunctionMapping> элемент для поддержки текущей операции.

Я делаю много обновлений в контексте и не имею никаких проблем, только когда я пытаюсь обновить этот конкретный объект.

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

  • 53
    Я сделал ошибку, на столе не было первичного ключа, спасибо за ваше время! Приносим извинения за неудобства!
  • 1
    Только что случилось со мной - вероятно, создал 1000 таблиц с первичными ключами и забыл одну - сообщение об исключении мало помогает
Показать ещё 1 комментарий
Теги:
entity-framework
primary-key

15 ответов

832
Лучший ответ

Обычно это происходит из-за одной из следующих причин:

  • Набор объектов сопоставляется с представлением базы данных
  • Пользовательский запрос базы данных
  • В таблице базы данных нет первичного ключа

После этого вам все равно придется обновлять конструктор Entity Framework (или, альтернативно, удалить объект и затем добавить его), прежде чем вы перестанете получать ошибку.

  • 2
    Не забудьте также изменить store: Schema на Schema для этого EntitySet, если у вас все еще есть проблемы.
  • 0
    Итак, решение состоит в том, чтобы добавить первичный ключ тогда?
Показать ещё 19 комментариев
66

Просто добавьте первичный ключ в таблицу. Это. Проблема решена.

ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
  • 10
    и не забудьте нажать кнопку «Обновить модель из базы данных» в своем файле .edmx
  • 0
    @BasharAbuShamaa этот ответ недействителен без этой детали.
35

Это для меня. Простое удаление привело к другой ошибке. Я следовал за шагами этого поста, кроме последнего. Для вашего удобства я скопировал 4 шага из сообщения, которое я выполнил, чтобы решить проблему следующим образом:

  • Щелкните правой кнопкой мыши на файле edmx, выберите Open with, XML editor
  • Найдите объект в элементе edmx: StorageModels
  • Полностью удалить DefiningQuery
  • Переименуйте store:Schema="dbo" в Schema="dbo" (иначе код будет генерировать ошибку, указав, что имя недействительно)
  • 0
    Большое спасибо - это именно то, что исправило мою проблему. Довольно неприятно, что это не было исправлено в EF. И, довольно удивительно, что ты понял это!
  • 0
    Я попытался удалить объект и добавить его заново. Перекомпиляция. Очистка. У меня ничего не получалось, кроме этого.
Показать ещё 5 комментариев
34

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

  • 1
    Как побороть, если мы не можем изменить таблицу базы данных?
  • 0
    @KaiHartmann попробуйте удалить первичный ключ вашей сущности в EF.
Показать ещё 1 комментарий
24

ОБНОВЛЕНИЕ: В последнее время у меня появилось несколько изменений, поэтому я решил, что я знаю, что совет, который я даю ниже, не самый лучший. Поскольку я изначально начал работать с Entity Framework на старых базарах без ключа, я понял, что лучшее, что вы можете сделать, FAR - это сделать это с помощью обратного кода. Есть несколько хороших статей о том, как это сделать. Просто следуйте им, а затем, когда вы хотите добавить к нему ключ, используйте аннотации данных, чтобы "подделать" ключ.

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

    [Key, Column(Order = 0)]
    public Int32? OrderNumber { get; set; }

    [Key, Column(Order = 1)]
    public String Customer { get; set; }

Таким образом, вы в основном подделываете EF, полагая, что есть кластерный ключ, состоящий из OrderNumber и Customer. Это позволит вам делать вставки, обновления и т.д. В таблице без ключа.

Если вы не слишком хорошо знакомы с обратным кодом Code First, пойдите и найдите хороший учебник по Entity Framework Code First. Затем найдите один из них в обратном коде First (который выполняет Code First с существующей базой данных). Тогда просто возвращайся сюда и снова посмотри на мой главный совет.:)

Оригинальный ответ:

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

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

В моем случае я работал с устаревшей системой (первоначально плоские файлы на AS400 портировали на Access, а затем портировали на T-SQL). Поэтому я должен был найти способ. Это мое решение. Следующее работало для меня с помощью Entity Framework 6.0 (последняя из NuGet на момент написания этой статьи).

  • Щелкните правой кнопкой мыши файл .edmx в обозревателе решений. Выберите "Открыть с...", а затем выберите "XML (Text) Editor". Мы собираемся вручную редактировать автоматически сгенерированный код.

  • Ищите такую ​​строку:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  • Удалите store:Name="table_name" с конца.

  • Измените store:Schema="whatever" на Schema="whatever"

  • Посмотрите ниже этой строки и найдите тег <DefiningQuery>. В нем будет большой ол-выбор. Удалите тег и его содержимое.

  • Теперь ваша строка должна выглядеть примерно так:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  • У нас есть что-то другое для изменения. Пройдите через свой файл и найдите это:
    <EntityType Name="table_name">

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

  • Ниже тег <Key>. Это то, что Entity Framework собирается использовать для вставки/обновления/удаления. ТАК УБЕДИТЕСЬ, ЧТО ВЫ СДЕЛАЛИ ЭТО ПРАВО. Свойство (или свойства) в этом теге должно указывать однозначно идентифицируемую строку. Например, допустим, что я знаю свою таблицу Orders, в то время как у нее нет первичного ключа, гарантируется, что у каждого клиента будет только один номер заказа.

Итак, мой выглядит следующим образом:

<EntityType Name="table_name">
              <Key>
                <PropertyRef Name="order_numbers" />
                <PropertyRef Name="customer_name" />
              </Key>
Серьезно, не делайте этого неправильно. Скажем, что, хотя никогда не должно быть дубликатов, как-то две строки попадают в мою систему с тем же номером заказа и именем клиента. Whooops! Это то, что я получаю за то, что не использовал ключ! Поэтому я использую Entity Framework для его удаления. Поскольку я знаю, что дубликат - это единственный порядок, поставленный сегодня, я делаю это:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);

Угадайте, что? Я просто удалил и дубликат И оригинал! Это потому, что я сказал Entity Framework, что order_number/cutomer_name был моим основным ключом. Поэтому, когда я сказал ему удалить duplicateOrder, то, что он сделал в фоновом режиме, было что-то вроде:

DELETE FROM orders
WHERE order_number = (duplicateOrder order number)
AND customer_name = (duplicateOrder customer name)

И с этим предупреждением... теперь вам будет хорошо идти!

  • 0
    Нашел этот ответ после того, как нашел такое же решение проблемы. Определенно правильный ответ! Только определение первичного ключа, как указано в других ответах, не поможет во многих случаях.
18

Это также может случиться, если модель данных устарела.

Надеюсь, это спасет кого-то еще от разочарования:)

6

Я получал такое же сообщение об ошибке, но в своем сценарии я пытался обновлять объекты, полученные из отношения "многие ко многим", используя PJT (Pure Join Table).

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

Таким образом, решение в моем случае состояло в том, чтобы изменить таблицу соединений в БД, чтобы сделать PK, который включает BOTH столбцов иностранных идентификаторов.

  • 0
    Это как генерация EDMX всегда работал? Я привык работать с Code First, который не требует PK на чистой таблице соединений.
4

может произойти ошибка, если в вашей таблице нет первичного ключа, в этом случае таблица "только для чтения", а команда db.SaveChanges() всегда будет вызывать ошибку

3

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

Примечание. Убедитесь, что при обновлении диаграммы EF из базы данных, указывающей на базу данных справа, в моем случае строка подключения указывала на локальную БД вместо обновленный Dev DB, ошибка школьника, которую я знаю, но я хотел опубликовать это, потому что это может быть очень неприятно, если вы уверены, что добавили первичный ключ, и вы все равно получаете ту же ошибку

  • 0
    Я чувствую себя глупо - неправильное соединение с БД
2

У меня была такая же проблема. Как сказал этот поток, в моей таблице не было ПК, поэтому я установил ПК и запустил код. Но, к сожалению, ошибка пришла снова. То, что я сделал дальше, было удалено из соединения DB (удалить .edmx файл в папке Model Solution Solution) и воссоздать его. Ошибка исчезла после этого. Спасибо всем за то, что поделились своими впечатлениями. Это экономит много времени.

1

Я получал эту проблему, потому что я создавал свой EDMX из существующей базы данных (разработанной кем-то еще, и я использую здесь термин "конструированный" ).

Оказывается, в таблице нет никаких ключей. EF генерировал модель со многими несколькими ключами. Мне пришлось добавить первичный ключ в таблицу db в SQL, а затем обновить мою модель в VS.

Это исправило это для меня.

0

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

0

просто добавьте первичный ключ в таблицу и затем заново создайте EF

0

У меня была такая же проблема, к сожалению, добавление первичного ключа не решает проблему. Итак, вот как я решаю шахту:

  • Убедитесь, что у вас есть primary key в таблице, поэтому я изменяю свою таблицу и добавляю первичный ключ.
  • Delete the ADO.NET Entity Data Model (файл edmx), где я использую карту и подключаюсь к моей базе данных.
  • Add again a new file of ADO.NET Entity Data Model для подключения к моей базе данных и для сопоставления свойств моей модели.
  • Clean and rebuild the solution.

Проблема решена.

0

Добавление первичного ключа для меня тоже!

Как только это будет сделано, здесь, как обновить модель данных, не удаляя ее -

Щелкните правой кнопкой мыши на странице дизайнера Entm Designer и "Обновить модель из базы данных".

Ещё вопросы

Сообщество Overcoder
Наверх
Меню