Не удалось обновить EntitySet - поскольку он содержит элемент DefiningQuery и no <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 и no <UpdateFunction> элемент существует в <ModificationFunctionMapping> элемент для поддержки текущей операции.

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

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

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

  • Щелкните правой кнопкой мыши на файле edmx, выберите Open with, XML editor
  • Найдите объект в элементе edmx: StorageModels
  • Полностью удалить DefiningQuery
  • Переименуйте store:Schema="dbo" в Schema="dbo" (иначе код будет генерировать ошибку, указав, что имя недействительно)

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

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

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

Ответ 8

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

Ответ 9

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

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

Ответ 10

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

Ответ 11

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

Ответ 12

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

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

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

Ответ 13

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

USE [YourDatabaseName]
GO

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

Ответ 14

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

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

Щелкните правой кнопкой мыши на странице дизайнера Entm Designer и "Обновить модель из базы данных".

Ответ 15

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

  • Убедитесь, что у вас есть 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.

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

Ответ 16

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

Ответ 17

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

Ответ 18

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

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

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

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

Ответ 19

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

Ответ 20

Я нашел оригинальный ответ обновления файла .edmx лучше всего в моей ситуации. Я просто не был рад изменению модели каждый раз, когда она обновлялась из базы данных. Вот почему я написал дополнительный файл текстовых шаблонов, который автоматически вызывается после изменения модели - точно так же, как объекты создаются заново. Я размещаю это здесь в этом комментарии. Чтобы это работало, убедитесь, что вы назвали его как {имя модели}.something.tt, и сохраните его в той же папке, что и ваша папка .edmx. Я назвал это {имя модели}.NonPkTables.tt. Он не создает файл сам по себе из-за неверного определения расширения файла во второй строке. Не стесняйтесь использовать.

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ output extension="/" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq"#>
<#@ assembly name="%VS120COMNTOOLS%..\IDE\EntityFramework.dll" #>
<#@ assembly name="%VS120COMNTOOLS%..\IDE\Microsoft.Data.Entity.Design.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Windows.Forms" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Data.Entity.Core.Metadata.Edm" #>
<#@ import namespace="System.Data.Entity.Core.Mapping" #>
<#@ import namespace="System.CodeDom" #>
<#@ import namespace="System.CodeDom.Compiler" #>
<#@ import namespace="Microsoft.CSharp"#>
<#@ import namespace="System.Text"#>
<#@ import namespace="System.Diagnostics" #>

<#
    string modelFileName= this.Host.TemplateFile.Split('.')[0] + ".edmx";
    string edmxPath = this.Host.ResolvePath( modelFileName );

    // MessageBox.Show( this.Host.TemplateFile + " applied." );
    var modelDoc = XDocument.Load(edmxPath);
    var root = modelDoc.Root;
    XNamespace nsEdmx = @"http://schemas.microsoft.com/ado/2009/11/edmx";
    XNamespace ns = @"http://schemas.microsoft.com/ado/2009/11/edm/ssdl";

    var runtime = root.Elements(nsEdmx + "Runtime").First();
    var storageModels = runtime.Elements(nsEdmx + "StorageModels").First();
    XNamespace nsStore = @"http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator";

    var schema = storageModels.Elements(ns + "Schema").First();
    XNamespace nsCustomAnnotation = @"http://schemas.microsoft.com/ado/2013/11/edm/customannotation";

    var entityTypes = schema.Nodes().OfType<XComment>().Where(c => c.Value.Contains("warning 6002: The table/view"));
    bool changed = false;

    foreach (var node in entityTypes)
    {
        var element = node.ElementsAfterSelf().First();
        string entityName = element.Attribute("Name").Value;

        // Find EntitySet in EntityContainer.
        var entityContainer = schema.Elements(ns + "EntityContainer").First();
        var entitySet = entityContainer.Elements(ns + "EntitySet").First(s => s.Attribute("Name").Value == entityName);

        // Change "store:Schema" attribute to "Schema" attribute.
        var attribute = entitySet.Attribute(nsStore + "Schema");

        if (attribute != null)
        {
            string schemaName = entitySet.Attribute(nsStore + "Schema").Value;
            entitySet.Attribute(nsStore + "Schema").Remove();
            entitySet.Add(new XAttribute("Schema", schemaName));
            changed |= true;
        }

        // Remove the DefiningQuery element.
        var definingQuery = entitySet.Element(ns + "DefiningQuery");

        if (definingQuery != null)
        {
            definingQuery.Remove();
            changed |= true;        
            Debug.WriteLine(string.Format("Removed defining query of EntitySet {0}.", entityName));
        }
    }

    if (changed)
        modelDoc.Save(edmxPath);
#>