我正在使用.net 3.5的实体框架1。
我正在做这样简单的事情:
var RoomDetails = context.Rooms.ToList();
foreach (var Room in Rooms)
{
Room.LastUpdated = DateTime.Now;
}
我在尝试时遇到此错误:
context.SaveChanges();
我收到错误:
无法更新EntitySet - 因为它有一个DefiningQuery而没有< UpdateFunction>元素存在于< ModificationFunctionMapping>中元素支持当前操作。
我正在对上下文进行大量更新而没有任何问题,只有在我尝试更新此特定实体时才会这样做。
我所有的搜索都显示了同样的事情,即我正在尝试更新的实体上没有声明主键。但是,我确实有一个主键声明......
答案 0 :(得分:948)
通常是因为以下原因之一:
执行此操作后,您可能仍需要在停止获取错误之前在Entity Framework设计器中更新(或者删除实体然后添加它)。
答案 1 :(得分:82)
只需向表中添加主键即可。而已。问题解决了。
ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
答案 2 :(得分:55)
对我来说就是这种情况。简单地删除导致另一个错误。我按照这篇文章的步骤,除了最后一个。为方便起见,我复制了我所遵循的帖子中的4个步骤来解决问题,如下所示:
store:Schema="dbo"
重命名为Schema="dbo"
(否则,代码会生成错误,说明名称无效)答案 3 :(得分:38)
请注意,您的实体可能主键,但您的数据库中的表没有主键。
答案 4 :(得分:29)
更新:我最近得到了一些赞成票,所以我想我会让人们知道我给出的建议不是最好的。由于我最初开始在旧的无钥匙数据库上做实体框架,我已经意识到你可以做的最好的事情是通过反向代码优先做到这一点。关于如何做到这一点,有一些很好的文章。只需按照它们,然后当您想要添加密钥时,使用数据注释来“伪造”密钥。
例如,假设我知道我的表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的好教程。然后在Reverse Code First(使用现有数据库执行Code First)上找到一个。然后回到这里再看看我的主要建议。 :)
原始答案:
首先:正如其他人所说,最好的选择是向表中添加主键。完全停止。如果你能这样做,请不要再读了。
但是如果你不能,或者只是讨厌自己,那么就可以在没有主键的情况下做到这一点。
在我的情况下,我正在使用遗留系统(最初在AS400上的平面文件移植到Access,然后移植到T-SQL)。所以我必须找到一种方法。这是我的解决方案。以下是使用Entity Framework 6.0(在撰写本文时最新的NuGet)中为我工作的。
在解决方案资源管理器中右键单击.edmx文件。选择“打开方式...”,然后选择“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"
在该行下方找到<DefiningQuery>
标记。它将有一个很大的选择声明。删除标签及其内容。
现在你的行应该是这样的:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
我们还有其他一些需要改变的地方。浏览您的文件并找到:
<EntityType Name="table_name">
在附近你可能会看到一些评论文本警告你它没有识别出主键,因此推断了密钥并且定义是只读表/视图。您可以保留或删除它。我删除了它。
以下是<Key>
标记。这是实体框架将用于执行插入/更新/删除的内容。所以请你确实这样做。该标记中的属性(或属性)需要指示唯一可识别的行。例如,假设我知道我的表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);
猜猜是什么?我刚刚删除了副本和原始版本!那是因为我告诉实体框架,order_number / cutomer_name是我的主键。所以当我告诉它删除duplicateOrder时,它在后台做的是:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
有了这个警告......你现在应该好好去!
答案 5 :(得分:19)
如果数据模型已过期,也会发生这种情况。
希望这可以挽救别人的挫败感:)
答案 6 :(得分:6)
我收到了相同的错误消息,但在我的场景中,我试图使用PJT(纯连接表)更新从多对多关系派生的实体。
通过阅读其他帖子,我想我可以通过在连接表中添加额外的PK字段来修复它...但是,如果你将一个PK列添加到连接表,它就不再是PJT而你输了所有实体框架优势,如实体之间的自动关系映射。
因此,我的解决方案是改变数据库上的连接表,使PK包含外部ID列的两个。
答案 7 :(得分:4)
如果您的表没有主键,则可能发生错误,在这种情况下,表是&#34;只读&#34;,并且db.SaveChanges()命令总是会带来错误< / p>
答案 8 :(得分:3)
所以它是真的,只需添加一个主键
注意:请确保当您从数据库更新EF图表时指向正确数据库时,在我的情况下,连接字符串指向本地数据库而不是最新的Dev DB,我知道小学生的错误,但我想发布这个,因为如果你确信你已经添加了主键并且你仍然得到相同的错误,那会非常令人沮丧
答案 9 :(得分:2)
我有同样的问题。正如这个主题所说,我的表没有PK,所以我设置PK并运行代码。但不幸的是,错误又来了。我接下来做的是删除数据库连接(删除解决方案资源管理器的Model文件夹中的.edmx文件)并重新创建它。之后错误消失了。感谢大家分享您的经验。它节省了很多时间。
答案 10 :(得分:2)
答案 11 :(得分:2)
设置主键,然后保存表和刷新,然后转到Model.edmx删除表并重新获取。
答案 12 :(得分:1)
我遇到了这个问题,因为我是从现有的数据库生成我的EDMX(由其他人设计,我在这里使用的术语&#39;松散地)。
原来桌子没有任何钥匙。 EF正在生成具有许多多个键的模型。我不得不在SQL中向db表添加主键,然后在VS中更新我的模型。
为我修好了。
答案 13 :(得分:1)
这不是一个新的答案,但可以帮助不确定如何为其表设置主键的人。在新查询中使用它并运行。这会将UniqueID列设置为主键。
USE [YourDatabaseName]
GO
Alter table [dbo].[YourTableNname]
Add Constraint PK_YourTableName_UniqueID Primary Key Clustered (UniqueID);
GO
答案 14 :(得分:0)
我只是通过删除和重建 EF 项目及其所有类来修复它。请参阅下面的详细信息:
我在这个问题上折腾了一个小时,然后删除了包含错误的 EF 项目,保存了我所有的自定义代码,然后重建了整个项目。由于只是生成一个新的EF图及其内部代码,所以这个修复问题的过程大约需要10分钟。
问题,我怀疑,在两三个“更新”之后,用于生成 EF 类和属性的数据库优先方法变得有点奇怪。基本上,我在代码行为中发现了一个问题,去修复了数据库表属性,然后一次更新了太多的EF图。然后我尝试摆弄代码,但没有用。
重新开始工作。
答案 15 :(得分:0)
我发现更新.edmx文件的原始答案在我的情况下效果最好。每次从数据库更新模型时,我只是不太满意更改模型。这就是为什么我编写了一个附加的文本模板文件的原因,该文件在模型更改后会自动调用-就像新生成的实体一样。我在此发表评论。 要使其正常工作,请确保将其命名为{model name} .something.tt,并将其存储在与.edmx文件夹相同的文件夹中。我将其命名为{model name} .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);
#>
答案 16 :(得分:0)
在XML编辑器中打开.edmx文件,然后从Tag中删除标签,然后将store:Schema =“ dbo”更改为Schema =“ dbo”并重建解决方案,现在错误将解决,您将能够保存数据
答案 17 :(得分:0)
我遇到了这个问题,并认为这是因为我删除了我的表主键上的索引,并将其替换为表中某些其他字段的索引。
删除主键索引并刷新edmx后,插入停止工作。
我将表刷新到旧版本,刷新了edmx,一切都恢复正常。
我应该注意,当我打开EDMX来解决这个问题时,检查是否有定义的主键,有。所以上述建议都没有帮助我。但刷新主键上的索引似乎有效。
答案 18 :(得分:0)
我只需要从模型中删除表格并再次更新模型,将表格带回来。我猜主键是在将表拉入模型后创建的。
答案 19 :(得分:0)
只需在表格中添加一个主键,然后重新创建您的EF
答案 20 :(得分:0)
我有完全相同的问题,遗憾的是,添加主键并不能解决问题。所以这就是我如何解决我的问题:
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.
问题解决了。
答案 21 :(得分:0)
添加主键也适用于我!
完成后,这里是如何更新数据模型而不删除它 -
右键单击edmx实体设计器页面和“从数据库更新模型”。