Невозможно обновить EntitySet - потому что у него есть DefiningQuery и нет элемента <UpdateFunction> - PullRequest
499 голосов
/ 28 сентября 2011

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

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

var RoomDetails = context.Rooms.ToList();

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

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

 context.SaveChanges();

Я получаю ошибку:

Невозможно обновить EntitySet - потому что он имеет DefiningQuery и в элементе нет элемента для поддержки текущей операции.

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

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

Ответы [ 19 ]

956 голосов
/ 28 сентября 2011

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

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

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

84 голосов
/ 28 марта 2013

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

ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
58 голосов
/ 21 января 2015

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

  1. Щелкните правой кнопкой мыши по файлу edmx, выберите Открыть с помощью, редактор XML
  2. Найдите объект в элементе edmx: StorageModels
  3. Полностью удалить DefiningQuery
  4. Переименуйте store:Schema="dbo" в Schema="dbo" (в противном случае код выдаст ошибку о том, что имя неверно)
38 голосов
/ 13 сентября 2013

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

29 голосов
/ 14 февраля 2014

ОБНОВЛЕНИЕ: В последнее время я получил несколько голосов по этому поводу, поэтому я решил, что дам людям знать, что совет, который я даю ниже, не самый лучший.С тех пор как я начал заниматься созданием Entity Framework со старыми базами данных без ключей, я пришел к выводу, что лучшее, что вы можете сделать BY 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.Затем найдите один из них в Reverse Code First (который выполняет Code First с существующей базой данных).Тогда просто возвращайся сюда и посмотри на мой ключевой совет снова.:)

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

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

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

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

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

  2. Найдите строку, подобную этой:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. Снимите store:Name="table_name" с конца.

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

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

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

  7. У нас есть что-то ещеизменить.Просмотрите ваш файл и найдите:
    <EntityType Name="table_name">

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

  9. Ниже тег <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's order number)
AND customer_name = (duplicateOrder's customer name)

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

19 голосов
/ 21 августа 2012

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

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

6 голосов
/ 23 января 2014

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

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

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

4 голосов
/ 25 января 2015

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

3 голосов
/ 12 января 2018

Установить первичный ключ, затем сохранить таблицу и обновить, затем перейти к Model.edmx удалить таблицу и получить снова.

3 голосов
/ 25 февраля 2014

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

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

...