2011-09-28 76 views
416

我正在使用Entity Framework 1和.net 3.5。无法更新EntitySet - 因为它有一个DefiningQuery并且不存在<UpdateFunction>元素

我做一些简单的像这样:

var RoomDetails = context.Rooms.ToList(); 

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

我得到这个错误,当我尝试做:

context.SaveChanges(); 

我得到的错误:

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

我我在上下文上做了很多更新,没有任何问题,只是在我尝试更新这个特定的实体时。

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

+40

我犯了一个错误,桌子上没有设置主键,谢谢你的时间! 不便之处! – iKode

+1

刚刚发生在我身上 - 可能是用主键创建了1000个表,并且忘记了一个 - 这个例外消息对于很好的 –

+1

没有太大的帮助。真的我忘了添加主键到表。让我们试着小心) – AEMLoviji

回答

822

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

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

这样做后,您可能仍然需要在实体框架设计器(或删除实体,然后添加它)之前更新顶部得到错误。

+2

如果您还有问题,请确保也将store:Schema更改为该EntitySet的Schema。 – Geoff

+0

那么,解决方案是添加一个主键呢? –

+2

@DanielAllenLangdon:是的。 –

18

如果数据模型过期,也会发生这种情况。

希望这将节省别人的挫折:)

71

只需添加一个主键表。而已。问题解决了。

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

,不要忘记在您的.edmx文件上点击“从数据库更新模型” –

36

只要注意,也许你实体主键你的数据库表没有主键

6

我得到了同样的错误信息,但在我的方案中,我试图使用PJT(纯联接表)更新从多对多关系派生的实体。

从阅读其他帖子,我想我可以通过添加一个额外的PK字段到连接表来解决它...但是,如果你添加一个PK列到连接表,它不再是一个PJT,你失去了所有的实体框架优势,如实体之间的自动关系映射。

所以在我的情况下,解决方案是改变数据库上的连接表,使一个包含外部ID列的PK。

+0

这是如何生成EDMX一直工作?我习惯于使用Code First,它不需要纯连接表上的PK。 –

26

更新:我最近得到了一些赞扬,所以我想我会让人们知道我给出的建议不是最好的。由于我最初开始关注在旧的无钥匙数据库上使用Entity Framework,我逐渐意识到,BY 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与现有的数据库)。然后回到这里再看看我的重要建议。 :)

原来的答案

第一:正如其他人所说,最好的选择是一个主键添加到表。句号。如果你能做到这一点,请不要再阅读。

但是,如果你不能,或只是恨自己,有没有办法做到这一点,主键。

在我的情况下,我正在使用遗留系统(AS400上的最初平面文件移植到Access,然后移植到T-SQL)。所以我必须找到一个方法。这是我的解决方案。以下内容适用于我使用Entity Framework 6.0(NuGet截至撰写本文时的最新版本)。

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

  2. 查找这样一行:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. 从最终删除store:Name="table_name"

  4. 变化store:Schema="whatever"Schema="whatever"

  5. 的外观,线下,找到<DefiningQuery>标签。它会有一个很大的选择陈述。删除标签和它的内容。现在

  6. 你行应该是这个样子:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. 我们还有别的改变。通过你的文件,去寻找这样的:
    <EntityType Name="table_name">

  8. 最近你可能会看到一些评论文字警告你,它没有一个主键识别,从而键已被推断和定义是读 - 仅表/视图。您可以保留或删除它。我删了它。

  9. 以下是<Key>标签。这是Entity Framework将用于插入/更新/删除的内容。所以请确保你做到了这一点。该标签中的属性(或属性)需要指明一个唯一可识别的行。例如,假设我知道我的表orders,虽然它没有主键,但确保每个客户只有一个订单号。

所以我的样子:

<EntityType Name="table_name"> 
       <Key> 
       <PropertyRef Name="order_numbers" /> 
       <PropertyRef Name="customer_name" /> 
       </Key> 

严重的是,不这样做是错误的。假设即使不应该有重复,但有两行以相同的订单号和客户名称进入我的系统。 Whooops!这就是我不使用密钥所得到的结果!所以我使用实体框架来删除一个。因为我知道重复是今天唯一的订单,所以我这样做:

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's order number) 
AND customer_name = (duplicateOrder's customer name) 

有了这样的警告......你现在应该好走!

+0

找到问题的相同解决方案后找到了这个答案。绝对是正确的答案!在其他答案中只定义一个主键,在许多情况下都无济于事。 –

3

所以它的真实,只需添加一个主键

注:可以肯定的是,当你从数据库中更新您的EF图,你指向数据库,在我如果连接字符串指向本地数据库而不是最新的开发数据库,​​我知道小学生的错误,但是我想发布这个,因为如果你确信你已经添加了主键,这可能会非常令人沮丧而你仍然得到相同的错误

+0

我觉得很蠢 - 错误的DB连接 –

1

我得到这个问题,因为我是从现有的数据库中生成我的EDMX(由其他人设计,我在这里松散地使用术语'设计')。

原来表没有钥匙。 EF正在生成具有多个键的模型。我不得不在SQL中添加一个主键到数据库表中,然后在VS中更新我的模型。

已经为我修好了。

40

这是我的情况。简单地删除导致另一个错误。除了最后一个,我跟着这篇文章的步骤。为方便起见,我复制从我跟着来解决问题后的4个步骤如下:

  1. 右键单击EDMX文件,选择打开方式,XML编辑器
  2. 找到实体的EDMX :StorageModels元件
  3. 卸下DefiningQuery完全
  4. 重命名store:Schema="dbo"Schema="dbo"(否则,代码将产生一个错误说的名称是无效的)
+0

非常感谢 - 这正是解决了我的问题。相当令人不安的是,这在EF中尚未得到解决。而且,你真明白这一点! –

+0

我尝试删除实体并重新添加它。重新编译。清洁。除此之外,没有任何工作。 – vintastic

+1

这解决了我的问题,但我不知道你是如何提出的答案,为什么你的建议解决了这个问题。 –

4

可能会发生错误,如果您的表没有主键,在这种情况下表是“只读”,并且db.SaveChanges()命令总是会带来错误

2

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

0

添加主键也适用于我!

一旦做到这一点,这里是如何而不删除它更新数据模型 -

右键单击EDMX实体设计页面和“从数据库更新模式”。

0

我有完全相同的问题,不幸的是,添加主键不能解决问题。因此,这里是我如何解决我的:

  1. 确保你在桌子上有一个primary key所以我改变我的表,并添加主键。
  2. Delete the ADO.NET Entity Data Model(edmx文件)我用它来映射和连接我的数据库。
  3. Add again a new file of ADO.NET Entity Data Model与我的数据库连接并映射我的模型属性。
  4. Clean and rebuild the solution.

问题解决了。

0

只需添加一个主键的表,然后重新创建EF

0

我不得不从模型中删除表和更新模型再次将表背。我猜主键是在表被拉入模型后创建的。

0

设置主键然后保存表和刷新然后去Model.edmx删除表并重新获取。

相关问题