关于c#:无法更新EntitySet – 因为它有一个DefiningQuery而没有< UpdateFunction>

Unable to update the EntitySet - because it has a DefiningQuery and no <UpdateFunction> element exist

我正在使用带有.NET 3.5的实体框架1。

我正在做这样简单的事情:

1
2
3
4
5
6
var RoomDetails = context.Rooms.ToList();

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

当我尝试执行以下操作时,会收到此错误:

1
 context.SaveChanges();

我得到错误:

Unable to update the EntitySet - because it has a DefiningQuery and no element exists in the element to support the current operation.

我对上下文进行了大量的更新,没有任何问题,只有当我尝试更新这个特定的实体时。

我所有的搜索都显示了相同的事情,即在我试图更新的实体上没有声明主键。但是,我确实声明了一个主键…


通常是因为以下原因之一:

  • 实体集从数据库视图映射
  • 自定义数据库查询
  • 数据库表没有主键

这样做之后,在停止获取错误之前,您可能仍然需要在实体框架设计器中更新(或者删除实体,然后添加它)。


只需向表中添加主键即可。就这样。问题解决了。

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


我就是这样。简单地删除会导致另一个错误。除了最后一个,我遵循了这篇文章的步骤。为了您的方便,我从文章中复制了以下4个步骤来解决问题:

  • 右键单击EDMX文件,选择"用XML编辑器打开"
  • 在edmx:storagemodels元素中定位实体
  • 完全删除定义查询
  • store:Schema="dbo"重命名为Schema="dbo"(否则,代码将生成一个错误,说明名称无效)

  • 请注意,您的实体可能有主键,但数据库中的表没有主键。


    最新消息:我最近在这个问题上得到了一些支持,所以我想我会让人们知道我下面给出的建议不是最好的。自从我开始在旧的无键数据库上做实体框架的工作以来,我逐渐意识到,到目前为止,你能做的最好的事情就是先反向代码。有几篇关于如何做到这一点的好文章。只需遵循它们,然后当您想要向它添加一个键时,使用数据注释来"伪造"该键。

    例如,假设我知道我的表Orders,虽然它没有主键,但可以保证每个客户只有一个订单号。因为这是表中的前两列,所以我将代码第一类设置为如下所示:

    1
    2
    3
    4
    5
        [Key, Column(Order = 0)]
        public Int32? OrderNumber { get; set; }

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

    通过这样做,您基本上被假装成相信有一个由ordernumber和customer组成的集群密钥。这将允许您在无键表上执行插入、更新等操作。

    如果您不太熟悉如何先执行逆向代码,请先去寻找一个关于实体框架代码的好教程。然后,首先在逆向代码上找到一个(这是对现有数据库进行代码优先)。然后再回来看看我的建议。:)

    原始答案:

    第一:正如其他人所说,最好的选择是向表中添加主键。完全停止。如果你能做到这一点,请不要再读下去。

    但是如果你不能,或者只是恨你自己,那么有一种方法可以不用主键来完成它。

    在我的例子中,我使用的是一个遗留系统(最初是移植到Access的AS400上的平面文件,然后移植到T-SQL)。所以我不得不想办法。这是我的解决方案。以下是使用Entity Framework 6.0(本文撰写时Nuget的最新版本)为我工作的。

  • 右键单击解决方案资源管理器中的.edmx文件。选择"打开方式…",然后选择"XML(文本)编辑器"。我们将在这里手工编辑自动生成的代码。

  • 找一条这样的线:江户十一〔一〕号

  • 从端部拆下store:Name="table_name"

  • store:Schema="whatever"改为Schema="whatever"

  • 看那条线下面,找到标签。它将包含一个很大的ol'select语句。移除标签及其内容。

  • 现在您的行应该如下所示:埃多克斯1〔6〕

  • 我们还有别的事情要改变。浏览您的文件并找到:江户十一〔七〕号

  • 在附近,您可能会看到一些注释文本,警告您它没有标识主键,因此已推断出该键,并且定义是只读表/视图。您可以保留或删除它。我删除了它。

  • 下面是标签。这是实体框架将用于执行插入/更新/删除的操作。所以要确保你做的对。该标记中的属性(或属性)需要指示唯一可标识行。例如,假设我知道我的表Orders,虽然它没有主键,但可以保证每个客户只有一个订单号。

  • 所以我的看起来是:

    1
    2
    3
    4
    5
    <EntityType Name="table_name">
                  <Key>
                    <PropertyRef Name="order_numbers" />
                    <PropertyRef Name="customer_name" />
                  </Key>

    说真的,别做错了。让我们假设,即使不应该有重复的内容,但是有两行以相同的订单号和客户名称进入我的系统。哎呀!这就是我不使用钥匙的原因!所以我用实体框架来删除一个。因为我知道副本是今天唯一的订单,所以我这样做:

    1
    2
    var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
    myModel.orders.Remove(duplicateOrder);

    你猜怎么着?我刚刚删除了副本和原件!这是因为我告诉实体框架,订单号/客户名称是我的主键。所以当我告诉它删除DuplicateOrder时,它在后台所做的就是:

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

    有了这个警告…你现在该走了!


    如果数据模型过时,也可能发生这种情况。

    希望这能让其他人免遭挫折:)


    我收到了相同的错误消息,但在我的场景中,我试图使用pjt(纯联接表)更新从多对多关系派生的实体。

    通过阅读其他文章,我想我可以通过在联接表中添加一个额外的pk字段来修复它…但是,如果将pk列添加到联接表中,它将不再是pjt,并且您将失去所有实体框架的优势,如实体之间的自动关系映射。

    所以在我的例子中,解决方案是更改数据库上的join表,以生成包含两个外部ID列的pk。


    如果您的表没有主键,则可能会发生错误,在这种情况下,表是"只读的",db.savechanges()命令将始终带来错误


    所以这是真的,只需添加一个主键

    注意:请确保当您从指向正确数据库的数据库更新EF图时,在我的示例中,连接字符串指向本地数据库,而不是最新的dev db,schoolboy错误,我知道,但我想发布此消息,因为如果您确信添加了主键和你还是会犯同样的错误吗?


    设置主键,然后保存表并刷新,然后转到model.edmx删除表并再次获取。


    我也有同样的问题。正如这个线程所说,我的表没有pk,所以我设置pk并运行代码。但不幸的是,错误又出现了。接下来,我删除了数据库连接(在解决方案资源管理器的模型文件夹中删除.edmx文件),并重新创建了它。之后错误就消失了。感谢大家分享你的经历。它节省了很多时间。


    这不是一个新的答案,但可以帮助那些不确定如何设置表的主键的人。在新查询中使用它并运行。这将把uniqueid列设置为主键。

    1
    2
    3
    4
    5
    6
    USE [YourDatabaseName]
    GO

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

    我之所以会遇到这个问题,是因为我是从现有的数据库(由其他人设计的,我在这里松散地使用术语"designed")生成EDMX的。

    结果这张桌子根本没有钥匙。EF正在生成具有多个键的模型。我必须在SQL中向db表添加主键,然后在vs中更新我的模型。

    那是给我修的。


    添加主键对我也很有用!

    完成后,下面介绍如何在不删除数据模型的情况下更新数据模型。-

    右键单击EDMX实体设计器页和"从数据库更新模型"。


    我也有同样的问题,不幸的是,添加主键并不能解决这个问题。下面是我如何解决我的问题:

  • 确保您在表上有一个primary key,这样我就修改了表并添加了一个主键。
  • Delete the ADO.NET Entity Data Model文件,用于映射和连接数据库。
  • 用于连接我的数据库和映射我的模型属性。
  • 埃多克斯1〔5〕
  • 问题解决了。


    只需向表中添加主键,然后重新创建EF


    我只需要从模型中删除表,然后再次更新模型,使表返回。我猜主键是在表被拉入模型之后创建的。


    我发现了这个问题,认为是因为我删除了表主键上的索引,并用表中其他一些字段上的索引替换了它。

    删除主键索引并刷新EDMX后,插入操作停止工作。

    我刷新了旧版本的表,刷新了EDMX,一切都重新工作了。

    我应该注意,当我打开EDMX对这个问题进行故障排除时,检查是否定义了主键。所以上面的建议都没有帮助我。但是刷新主键上的索引似乎可以工作。


    在XML编辑器中打开.edmx文件,然后从标记中删除标记,并将store:schema="dbo"更改为schema="dbo",然后立即重建解决方案错误将得到解决,您将能够保存数据。