无法更新EntitySet – 因为它有一个DefiningQuery并且不存在<UpdateFunction>元素
我正在使用.net 3.5entity framework1。
我正在做这样简单的事情:
var RoomDetails = context.Rooms.ToList(); foreach (var Room in Rooms) { Room.LastUpdated = DateTime.Now; }
我正在尝试执行时遇到此错误:
context.SaveChanges();
我得到的错误:
无法更新EntitySet – 因为它具有DefiningQuery,并且<ModificationFunctionMapping>元素中不存在<UpdateFunction>元素以支持当前操作。
我在上下文中做了很多更新,没有任何问题,只是当我试图更新这个特定的实体。
我所有的search都显示了同样的事情,即在我试图更新的实体上没有声明主键。 但是,唉,我确实有一个主键声明…
这通常是由于以下原因之一所致:
- 实体集从数据库视图映射
- 自定义数据库查询
- 数据库表没有主键
这样做之后,您可能仍然需要在entity frameworkdevise器中进行更新(或者删除实体,然后添加它),然后再停止获取错误。
只需将一个主键添加到表中。 而已。 问题解决了。
ALTER TABLE <TABLE_NAME> ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
这是我的情况。 简单地删除导致另一个错误。 除了最后一个,我跟着这篇文章的步骤。 为了方便起见,我复制了后面的四个步骤来解决问题,如下所示:
- 右键点击edmx文件,selectOpen with,XML编辑器
- 在edmx:StorageModels元素中find实体
- 完全删除DefiningQuery
- 重命名
store:Schema="dbo"
为Schema="dbo"
(否则,代码将产生一个错误,表明该名称是无效的)
只要注意,也许你的实体有主键,但你的数据库中的表没有主键 。
更新:最近我得到了一些赞扬,所以我想我会让人们知道我给出的build议不是最好的。 由于我最初是在旧的无钥匙数据库上开始使用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组成的集群键。 这将允许您在无钥匙桌上插入,更新等。
如果你不太熟悉逆向代码优先,那么去entity framework代码优先找一个好的教程。 然后去反向代码优先(这是做Code First与现有的数据库)之一。 然后回到这里再看看我的主要build议。 🙂
原始答案 :
首先:正如其他人所说,最好的select是在表中添加一个主键。 句号 如果你能做到这一点,请不要再阅读。
但是,如果你不能,或者只是憎恨自己,就有办法在没有主键的情况下做到这一点。
在我的情况下,我正在使用一个遗留系统(AS400上最初的平面文件,移植到Access,然后移植到T-SQL)。 所以我必须find一个方法。 这是我的解决scheme。 以下是使用Entity Framework 6.0(NuGet的最新版本)编写的。
-
右键单击解决scheme资源pipe理器中的.edmx文件。 select“打开方式…”,然后select“XML(文本)编辑器”。 我们将在这里手动编辑自动生成的代码。
-
寻找这样的一条线:
<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"
-
看下面这行,find
<DefiningQuery>
标签。 它会有一个大的select陈述。 删除标签和它的内容。 -
现在你的行应该看起来像这样:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
-
我们还有其他的东西要改变。 通过你的文件,find这个:
<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 frameworkorder_number / cutomer_name是我的主键。 所以当我告诉它删除duplicateOrder时,它在后台执行的操作如下所示:
DELETE FROM orders WHERE order_number = (duplicateOrder's order number) AND customer_name = (duplicateOrder's customer name)
有了这个警告,你现在应该好好走了!
如果数据模型过期,也会发生这种情况。
希望这会拯救别人无奈:)
我得到了同样的错误信息,但在我的scheme中,我试图使用PJT(Pure Join Table)来更新从多对多关系派生的实体。
从阅读其他post,我想我可以通过添加一个额外的PK字段到连接表来修复它…但是,如果您添加一个PK列连接表,它不再是一个PJT,你失去了所有的entity framework的优势,如实体之间的自动关系映射。
所以在我的情况下,解决scheme是改变数据库上的连接表来做一个包括外部ID列的两个PK。
如果你的表没有主键,在这种情况下表是“只读”,并且db.SaveChanges()命令总是会带来一个错误
所以它的真实,只需添加一个主键
注意:当你从数据库更新你指向正确的数据库的EF图时,在我的情况下,连接string指向本地数据库,而不是最新的开发数据库,学生错误我知道,但我想发布这个,因为它可以是非常令人沮丧,如果你确信你已经添加了主键,你仍然得到相同的错误
我遇到过同样的问题。 正如这个线程所说,我的表没有PK,所以我设置了PK并运行了代码。 但不幸的是错误又来了。 接下来我做了什么,删除了数据库连接(删除解决scheme资源pipe理器的模型文件夹中的.edmx文件)并重新创build它。 错过了之后。 感谢大家分享你的经验。 它节省了大量的时间。
我遇到了这个问题,因为我从一个现有的数据库(由别人devise,我在这里松散地使用术语“devise”)生成我的EDMX。
原来,桌子上没有任何钥匙。 EF正在生成具有多个键的模型。 我不得不去在SQL数据库表中添加一个主键,然后在VS中更新我的模型。
这为我修好了。
添加主键也适用于我!
一旦完成,以下是如何更新数据模型而不删除它 –
右键单击edmx实体devise器页面,然后select“从数据库更新模型”。
我有完全相同的问题,不幸的是,添加主键不能解决问题。 所以这里是我如何解决我的:
- 确保你有一个
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.
问题解决了。
只需将一个主键添加到您的表中,然后重新创build您的EF