Не удалось обновить EntitySet 'InstanceObjectName', потому что у него есть DefiningQuery, и в элементе нет элемента для поддержки текущей операции
Элемент DefiningQuery и no <DeleteFunction> существует в элементе <ModificationFunctionMapping> для поддержки текущей операции
Ответ 1
Убедитесь, что в вашей таблице есть ключ-ключ!
Ответ 2
Entity Framework не знает, является ли данное представление обновляемым или нет, поэтому он добавляет элемент для safegaurd против того, что фреймворк пытается генерировать запросы к невосстанавливаемому виду.
Если ваше представление является обновляемым, вы можете просто удалить элемент из определения EntitySet для вашего представления внутри раздела StorageModel вашего .edmx, и нормальная обработка обновлений будет работать так же, как и в любой другой таблице.
Если ваше представление не является обновляемым, вам нужно будет предоставить логику обновления самостоятельно с помощью "Сопоставления функций модификации". Функция Modification Function Mapping вызывает функцию, определенную в разделе StorageModel вашего .edmx. Эта функция может содержать имя и аргументы в хранимой процедуре в вашей базе данных или вы можете "определить команду", чтобы написать инструкцию insert, update или delete непосредственно в определении функции в разделе StorageModel вашего .edmx.
Из двух вариантов, если ваше представление является обновляемым (что похоже на то, что оно может быть), проще всего удалить вставленный конструктором.
Ответ 3
ОБНОВЛЕНИЕ: В последнее время у меня появилось несколько изменений, поэтому я решил, что я знаю, что совет, который я даю ниже, не самый лучший. Поскольку я изначально начал работать с 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. Затем, как только вам понравится это, найдите один из них в обратном кодовом коде (который выполняет Code First с существующей базой данных). Тогда просто возвращайся сюда и снова посмотри на мой главный совет.:)
Оригинальный ответ:
Сначала: как говорили другие, лучшим вариантом является добавление первичного ключа в таблицу. Полная остановка. Если вы можете это сделать, не читайте дальше.
Но если вы не можете или просто ненавидите себя, есть способ сделать это без первичного ключа. В принципе, то, что мы собираемся сделать, это ложь в Entity Framework и указать там первичный ключ.
В моем случае я работал с устаревшей системой (первоначально плоские файлы на 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)
И с этим предупреждением... теперь вам будет хорошо идти!