Элемент DefiningQuery и no <DeleteFunction> существует в элементе <ModificationFunctionMapping> для поддержки текущей операции

Не удалось обновить EntitySet 'InstanceObjectName', потому что у него есть DefiningQuery, и в элементе нет элемента для поддержки текущей операции

Ответ 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)

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