it-roy-ru.com

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

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

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

var RoomDetails = context.Rooms.ToList();

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

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

 context.SaveChanges();

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

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

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

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

478
iKode

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

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

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

928
Ladislav Mrnka

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

ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
82
Jebastin J

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

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

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

38
Majid

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

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

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

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

В моем случае я работал с устаревшей системой (изначально плоские файлы на 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 будет использовать для вставки/обновления/удаления. SO УБЕДИТЕСЬ, ЧТО ВЫ ДЕЛАЕТЕ ЭТО ПРАВО. Свойство (или свойства) в этом теге должно указывать на уникально идентифицируемую строку. Например, скажем, я знаю, что моя таблица 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)

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

29
Pharylon

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

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

18
mob1lejunkie

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

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

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

6
Kerry Randolph

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

4
Ruben.sar

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

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

3
Spyder

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

2
Namal

Установите Primary Key, затем сохраните Table и Refresh, затем перейдите в Model.edmx, удалите Table и получите снова.

1
Joan Ali

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

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

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

1
Stark

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

0
dangalg

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

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

Задача решена.

0
Willy David Jr

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

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

Щелкните правой кнопкой мыши на странице дизайнера сущностей edmx и выберите «Обновить модель из базы данных».

0
Abhishek Poojary

Откройте файл .edmx в редакторе XML, а затем удалите тег из тега, а также измените store: Schema = "dbo" на Schema = "dbo" и перестройте решение, теперь ошибка устранится, и вы сможете сохранить данные.

0
Sharad Tiwari

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

0
Sulyman

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

После того как я удалил индекс первичного ключа и обновил edmx, вставки перестали работать. 

Я обновил таблицу до более старой версии, обновил edmx, и все снова работает. 

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

0
armstb01

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

USE [YourDatabaseName]
GO

Alter table  [dbo].[YourTableNname]
Add Constraint PK_YourTableName_UniqueID Primary Key Clustered (UniqueID);
GO
0
JessS