Не удалось обновить EntitySet-потому что он имеет DefiningQuery и не существует элемента

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

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

var RoomDetails = context.Rooms.ToList();

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

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

 context.SaveChanges();

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

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

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

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

18 ответов


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

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

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


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

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

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

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

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


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

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

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

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

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

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

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

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

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

в моем случае я работал с устаревшей системой (первоначально плоские файлы на as400 портировались для доступа, а затем портировались на 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" to Schema="whatever"

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

  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);

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

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

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


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

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


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

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

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


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


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

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


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


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

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

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


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


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

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

щелкните правой кнопкой мыши на странице edmx Entity designer и "обновить модель из базы данных".


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

  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.

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


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


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


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

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

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

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


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