Я использую 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> элемент для поддержки текущей операции.
Я делаю много обновлений в контексте и не имею никаких проблем, только когда я пытаюсь обновить этот конкретный объект.
Все мои поиски показывают то же самое, что первичного ключа, объявленного в сущности, которую я пытаюсь обновить, не существует. Но, увы, у меня есть основной ключ, объявленный...
Обычно это происходит из-за одной из следующих причин:
После этого вам все равно придется обновлять конструктор Entity Framework (или, альтернативно, удалить объект и затем добавить его), прежде чем вы перестанете получать ошибку.
Просто добавьте первичный ключ в таблицу. Это. Проблема решена.
ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
Это для меня. Простое удаление привело к другой ошибке. Я следовал за шагами этого поста, кроме последнего. Для вашего удобства я скопировал 4 шага из сообщения, которое я выполнил, чтобы решить проблему следующим образом:
store:Schema="dbo"
в Schema="dbo"
(иначе код будет генерировать ошибку, указав, что имя недействительно)Просто помните, что, возможно, ваш Entity имеет первичный ключ, но ваша таблица в базе данных не имеет первичного ключа.
ОБНОВЛЕНИЕ: В последнее время у меня появилось несколько изменений, поэтому я решил, что я знаю, что совет, который я даю ниже, не самый лучший. Поскольку я изначально начал работать с 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)
И с этим предупреждением... теперь вам будет хорошо идти!
Это также может случиться, если модель данных устарела.
Надеюсь, это спасет кого-то еще от разочарования:)
Я получал такое же сообщение об ошибке, но в своем сценарии я пытался обновлять объекты, полученные из отношения "многие ко многим", используя PJT (Pure Join Table).
Из чтения других сообщений, я думал, что могу исправить это, добавив дополнительное поле PK в таблицу соединений... Однако, если вы добавите столбец PK в таблицу соединений, это уже не PJT, и вы проиграете все преимущества инфраструктуры сущности, такие как автоматическое сопоставление отношений между объектами.
Таким образом, решение в моем случае состояло в том, чтобы изменить таблицу соединений в БД, чтобы сделать PK, который включает BOTH столбцов иностранных идентификаторов.
может произойти ошибка, если в вашей таблице нет первичного ключа, в этом случае таблица "только для чтения", а команда db.SaveChanges() всегда будет вызывать ошибку
, поэтому его true, просто добавьте первичный ключ
Примечание. Убедитесь, что при обновлении диаграммы EF из базы данных, указывающей на базу данных справа, в моем случае строка подключения указывала на локальную БД вместо обновленный Dev DB, ошибка школьника, которую я знаю, но я хотел опубликовать это, потому что это может быть очень неприятно, если вы уверены, что добавили первичный ключ, и вы все равно получаете ту же ошибку
У меня была такая же проблема. Как сказал этот поток, в моей таблице не было ПК, поэтому я установил ПК и запустил код. Но, к сожалению, ошибка пришла снова. То, что я сделал дальше, было удалено из соединения DB (удалить .edmx файл в папке Model Solution Solution) и воссоздать его. Ошибка исчезла после этого. Спасибо всем за то, что поделились своими впечатлениями. Это экономит много времени.
Я получал эту проблему, потому что я создавал свой EDMX из существующей базы данных (разработанной кем-то еще, и я использую здесь термин "конструированный" ).
Оказывается, в таблице нет никаких ключей. EF генерировал модель со многими несколькими ключами. Мне пришлось добавить первичный ключ в таблицу db в SQL, а затем обновить мою модель в VS.
Это исправило это для меня.
Мне просто пришлось удалить таблицу из модели и обновить модель, снова вернув таблицу. Я предполагаю, что первичный ключ был создан после того, как таблица была втянута в модель.
просто добавьте первичный ключ в таблицу и затем заново создайте EF
У меня была такая же проблема, к сожалению, добавление первичного ключа не решает проблему. Итак, вот как я решаю шахту:
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.
Проблема решена.
Добавление первичного ключа для меня тоже!
Как только это будет сделано, здесь, как обновить модель данных, не удаляя ее -
Щелкните правой кнопкой мыши на странице дизайнера Entm Designer и "Обновить модель из базы данных".