无法更新 EntitySet - 因为它有 DefiningQuery 并且没有元素存在

发布于 2024-12-06 20:00:10 字数 630 浏览 0 评论 0原文

我正在使用 Entity Framework 1 和 .net 3.5。

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

var roomDetails = context.Rooms.ToList();

foreach (var room in roomDetails)
{        
   room.LastUpdated = DateTime.Now;
}

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

 context.SaveChanges();

我收到错误:

无法更新 EntitySet - 因为它有 DefiningQuery 并且没有元素存在于中。支持当前操作的元素。

我正在对上下文进行大量更新,并且没有任何问题,只有当我尝试更新这个特定实体时才会出现问题。

我所有的搜索都显示相同的内容,即我尝试更新的实体上没有声明主键。但可惜的是,我确实声明了一个主键......

I am using Entity Framework 1 with .net 3.5.

I am doing something simple like this:

var roomDetails = context.Rooms.ToList();

foreach (var room in roomDetails)
{        
   room.LastUpdated = DateTime.Now;
}

I am getting this error when I try to do:

 context.SaveChanges();

I get the error:

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

I am doing lots of updates on the context and not having any issues, it's only when I try to update this particular entity.

All my searching shows up the same thing, that there is no primary key declared on the entity that I'm trying to update. But alas, I do have a Primary key declared...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(22

£烟消云散 2024-12-13 20:00:10

它通常是由于以下原因之一而发生的:

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

执行此操作后,您可能仍然需要在实体框架设计器中进行更新(或者删除实体,然后添加它),然后再停止出现错误。

It usually happens because one of the following reasons:

  • Entity Set is mapped from Database view
  • A custom Database query
  • Database table doesn't have a primary key

After doing so, you may still need to update in the Entity Framework designer (or alternatively delete the entity and then add it) before you stop getting the error.

追我者格杀勿论 2024-12-13 20:00:10

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

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

Just Add a primary key to the table. That's it. Problem solved.

ALTER TABLE <TABLE_NAME>
ADD CONSTRAINT <CONSTRAINT_NAME> PRIMARY KEY(<COLUMN_NAME>)
爱人如己 2024-12-13 20:00:10

我的情况就是这样。简单地删除会导致另一个错误。除了最后一个之外,我按照这篇文章的步骤进行操作。为了您的方便,我复制了帖子中解决问题的 4 个步骤,如下所示:

  1. 右键单击​​ edmx 文件,选择“打开方式”、XML 编辑器
  2. 在 edmx:StorageModels 元素中找到实体
  3. 完全删除 DefiningQuery 重
  4. 命名store:Schema="dbo"Schema="dbo" (否则,代码将生成错误,指出名称无效)

This is the case for me. Simply removing resulted in another error. I followed the steps of this post except the last one. For your convenience, I copied the 4 steps from the post that I followed to solve the problem as following:

  1. Right click on the edmx file, select Open with, XML editor
  2. Locate the entity in the edmx:StorageModels element
  3. Remove the DefiningQuery entirely
  4. Rename the store:Schema="dbo" to Schema="dbo" (otherwise, the code will generate an error saying the name is invalid)
还如梦归 2024-12-13 20:00:10

请注意,也许您的实体主键,但数据库中的表没有主键

Just note that maybe your Entity have primary key but your table in database doesn't have primary key.

绮烟 2024-12-13 20:00:10

更新:最近我对此得到了一些支持,所以我想我应该让人们知道我在下面给出的建议并不是最好的。自从我最初开始在旧的无密钥数据库上做实体框架以来,我开始意识到到目前为止你能做的最好的事情就是通过反向代码优先来完成它。有一些关于如何执行此操作的好文章。只需遵循它们,然后当您想为其添加密钥时,使用数据注释来“伪造”密钥。

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

    [Key, Column(Order = 0)]
    public Int32? OrderNumber { get; set; }

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

通过这样做,您基本上会伪造 EF 相信存在由 OrderNumber 和 Customer 组成的聚集键。这将允许您在无钥匙表上进行插入、更新等操作。

如果您不太熟悉反向代码优先,请查找有关实体框架代码优先的好教程。然后去 Reverse Code First 上找到一个(即使用现有数据库执行 Code First)。然后回到这里再次查看我的关键建议。 :)

原始答案

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

但如果你不能,或者只是讨厌自己,有一种方法可以在没有主键的情况下做到这一点。

就我而言,我正在使用旧系统(最初将 AS400 上的平面文件移植到 Access,然后移植到 T-SQL)。所以我必须想办法。这是我的解决方案。以下内容对我使用 Entity Framework 6.0(截至撰写本文时 NuGet 的最新版本)有用。

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

  2. 寻找这样的行:

  3. 从末尾删除 store:Name="table_name"

  4. store:Schema="whatever" 更改为 Schema="whatever"

  5. 查看该行下方并找到 标记。它将有一个大的 ol' select 语句。删除该标记及其内容。

  6. 现在你的行应该看起来像这样:

  7. 我们还有其他需要更改的内容。浏览您的文件并找到以下内容:

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

  9. 下面是标签。这就是实体框架将用来执行插入/更新/删除的操作。所以请确保您做得正确。该标记中的一个或多个属性需要指示唯一可识别的行。例如,假设我知道我的表 orders,虽然它没有主键,但保证每个客户只有一个订单号。

所以我的看起来是这样的:

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

说真的,别做错事。假设即使永远不应该有重复项,但不知何故,有两行具有相同的订单号和客户名称进入我的系统。哎呀!这就是我不使用钥匙所得到的结果!所以我使用Entity Framework删除一个。因为我知道重复的订单是今天提交的唯一订单,所以我这样做:

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

你猜怎么着?我刚刚删除了重复的和原始的!那是因为我告诉实体框架 order_number/cutomer_name 是我的主键。因此,当我告诉它删除重复订单时,它在后台执行的操作类似于:

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

有了该警告...您现在应该可以开始了!

UPDATE: I've gotten a few upvotes on this lately, so I figured I'd let people know the advice I give below isn't the best. Since I originally started mucking about with doing Entity Framework on old keyless databases, I've come to realize that the best thing you can do BY FAR is do it by reverse code-first. There are a few good articles out there on how to do this. Just follow them, and then when you want to add a key to it, use data annotations to "fake" the key.

For instance, let's say I know my table Orders, while it doesn't have a primary key, is assured to only ever have one order number per customer. Since those are the first two columns on the table, I'd set up the code first classes to look like this:

    [Key, Column(Order = 0)]
    public Int32? OrderNumber { get; set; }

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

By doing this, you're basically faked EF into believing that there's a clustered key composed of OrderNumber and Customer. This will allow you to do inserts, updates, etc on your keyless table.

If you're not too familiar with doing reverse Code First, go and find a good tutorial on Entity Framework Code First. Then go find one on Reverse Code First (which is doing Code First with an existing database). Then just come back here and look at my key advice again. :)

Original Answer:

First: as others have said, the best option is to add a primary key to the table. Full stop. If you can do this, read no further.

But if you can't, or just hate yourself, there's a way to do it without the primary key.

In my case, I was working with a legacy system (originally flat files on a AS400 ported to Access and then ported to T-SQL). So I had to find a way. This is my solution. The following worked for me using Entity Framework 6.0 (the latest on NuGet as of this writing).

  1. Right-click on your .edmx file in the Solution Explorer. Choose "Open With..." and then select "XML (Text) Editor". We're going to be hand-editing the auto-generated code here.

  2. Look for a line like this:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. Remove store:Name="table_name" from the end.

  4. Change store:Schema="whatever" to Schema="whatever"

  5. Look below that line and find the <DefiningQuery> tag. It will have a big ol' select statement in it. Remove the tag and it's contents.

  6. Now your line should look something like this:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. We have something else to change. Go through your file and find this:
    <EntityType Name="table_name">

  8. Nearby you'll probably see some commented text warning you that it didn't have a primary key identified, so the key has been inferred and the definition is a read-only table/view. You can leave it or delete it. I deleted it.

  9. Below is the <Key> tag. This is what Entity Framework is going to use to do insert/update/deletes. SO MAKE SURE YOU DO THIS RIGHT. The property (or properties) in that tag need to indicate a uniquely identifiable row. For instance, let's say I know my table orders, while it doesn't have a primary key, is assured to only ever have one order number per customer.

So mine looks like:

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

Seriously, don't do this wrong. Let's say that even though there should never be duplicates, somehow two rows get into my system with the same order number and customer name. Whooops! That's what I get for not using a key! So I use Entity Framework to delete one. Because I know the duplicate is the only order put in today, I do this:

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

Guess what? I just deleted both the duplicate AND the original! That's because I told Entity Framework that order_number/cutomer_name was my primary key. So when I told it to remove duplicateOrder, what it did in the background was something like:

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

And with that warning... you should now be good to go!

眼中杀气 2024-12-13 20:00:10

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

希望这能避免其他人的挫败感:)

This can also happen if data model is out of date.

Hopefully this will save someone else frustration :)

情域 2024-12-13 20:00:10

如果您的表没有主键,则可能会发生此错误,在这种情况下,表是“只读”的,并且 db.SaveChanges () 命令将始终出错。

The error may have occurred if your table doesn't have a primary key, in this case the table is "read only", and the db.SaveChanges () command will always error.

隔岸观火 2024-12-13 20:00:10

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

通过阅读其他帖子,我认为我可以通过向连接表添加一个额外的 PK 字段来修复它...但是,如果您向连接表添加 PK 列,它就不再是 PJT 并且您会丢失所有实体框架的优点是实体之间的自动关系映射。

因此,我的案例的解决方案是更改数据库上的联接表,以创建包含两个外部 ID 列的 PK。

I was getting the same error message, but in my scenario I was trying to update entities derived from a many-to-many relationship using a PJT (Pure Join Table).

From reading the other posts, I thought I could fix it by adding an additional PK field to the join table... However, if you add a PK column to a join table, it is no longer a PJT and you lose all of the entity framework advantages like the automatic relationship mapping between the entities.

So the solution in my case was to alter the join table on the DB to make a PK that includes BOTH of the foreign ID columns.

纸伞微斜 2024-12-13 20:00:10

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

Set Primary Key then save Table and Refresh then go to Model.edmx delete Table and get again .

才能让你更想念 2024-12-13 20:00:10

确实如此,只需添加一个主键

注意:当您从数据库更新 EF 图表时,请确保您指向右侧数据库,在我的例子中,连接字符串指向本地数据库而不是最新的开发数据库,​​我知道学童错误,但我想发布此内容,因为如果您确信自己已经添加了主键,你仍然得到相同的结果错误

so its true, just add a primary key

Note: be sure that when you're updating your EF diagram from the database that you're pointing to the right database, in my case the connection string was pointing to a local DB instead of the up-to-date Dev DB, schoolboy error i know, but I wanted to post this because it can be very frustrating if you're convinced you've added the primary key and you're still getting the same error

再可℃爱ぅ一点好了 2024-12-13 20:00:10

输入图片此处描述

就我而言,忘记定义表的主键。因此,如图所示进行分配,并通过 .edmx 文件中的“从数据库更新模型”刷新表。
希望它会有所帮助!

enter image description here

In my case, forgot to define Primary Key to Table. So assign like shown in Picture and Refresh your table from "Update model from Database" from .edmx file.
Hope it will help !!!

始终不够 2024-12-13 20:00:10

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

I had the same issue. As this thread said, My table didn't have a PK, so I set the PK and ran the code. But unfortunately error came again. What I did next was, deleted the DB connection (delete .edmx file in Model folder of Solution Explorer) and recreated it. Error gone after that. Thanks everyone for sharing your experiences. It save lots of time.

泪意 2024-12-13 20:00:10

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

USE [YourDatabaseName]
GO

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

This is not a new answer but will help somebody who's not sure how to set primary key for their table. Use this in a new query and run. This will set UniqueID column as primary key.

USE [YourDatabaseName]
GO

Alter table  [dbo].[YourTableNname]
Add Constraint PK_YourTableName_UniqueID Primary Key Clustered (UniqueID);
GO
奢华的一滴泪 2024-12-13 20:00:10

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

结果桌子上没有任何钥匙。 EF 正在生成具有多个键的模型。我必须在 SQL 中向数据库表添加主键,然后在 VS 中更新我的模型。

这为我解决了。

I was getting this issue because i was generating my EDMX from an existing database (designed by somebody else, and i use the term 'designed' loosely here).

Turns out the table had no keys whatsoever. EF was generating the model with many multiple keys. I had to go add a primary key to the db table in SQL and then updated my model in VS.

That fixed it for me.

倦话 2024-12-13 20:00:10

添加主键也对我有用!

完成后,以下是如何更新数据模型而不删除它 -

右键单击​​ edmx 实体设计器页面并选择“从数据库更新模型”。

Adding the primary key worked for me too !

Once that is done, here's how to update the data model without deleting it -

Right click on the edmx Entity designer page and 'Update Model from Database'.

哭了丶谁疼 2024-12-13 20:00:10

不幸的是,我遇到了完全相同的问题,添加主键并不能解决问题。因此,我是这样解决我的问题的:

  1. 确保表上有一个主键,以便我更改表并添加主键。
  2. 删除我用来映射和连接数据库的 ADO.NET 实体数据模型(edmx 文件)。
  3. 再次添加 ADO.NET 实体数据模型的新文件以连接我的数据库并映射我的模型属性。
  4. 清理并重建解决方案。

问题已解决。

I had the exact same problem, unfortunately, adding the primary key doesn't solve the issue. So here's how I solve mine:

  1. Make sure you have a primary key on the table so I alter my table and add a primary key.
  2. Delete the ADO.NET Entity Data Model (edmx file) where I use to map and connect with my database.
  3. Add again a new file of ADO.NET Entity Data Model to connect with my database and for mapping my model properties.
  4. Clean and rebuild the solution.

Problem solved.

自找没趣 2024-12-13 20:00:10

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

just add a primary key to your table and then recreate your EF

游魂 2024-12-13 20:00:10

我只需从模型中删除表格并再次更新模型以恢复表格。我猜想主键是在将表拉入模型后创建的。

I just had to remove the table from the model and update the model again bringing the table back. I guess the primary key was created after the table was pulled into the model.

温柔少女心 2024-12-13 20:00:10

我遇到了这个问题,并相信这是因为我删除了表主键上的索引并将其替换为表中其他一些字段上的索引而引起的。

在我删除主键索引并刷新 edmx 后,插入停止工作。

我将表刷新到旧版本,刷新了 edmx,一切又恢复正常了。

我应该注意到,当我打开 EDMX 来解决此问题时,检查是否定义了主键,确实存在。所以上述建议都没有帮助我。但刷新主键上的索引似乎有效。

I had this issue come up and believe it was caused because I had deleted the Index on my tables primary key and replaced it with an index on some of the other fields in the table.

After I deleted the primary key index and refreshed the edmx, inserts stopped working.

I refreshed the table to the older version, refreshed the edmx and everything works again.

I should note that when I opened the EDMX to troubleshoot this issue, checking to see if there was a primary key defined, there was. So none of the above suggestions were helping me. But refreshing the index on the primary key seemed to work.

以可爱出名 2024-12-13 20:00:10

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

Open Your .edmx file in XML editor and then remove tag from Tag and also change store:Schema="dbo" to Schema="dbo" and rebuild the solution now error will resolve and you will be able to save the data.

放飞的风筝 2024-12-13 20:00:10

我发现更新 .edmx 文件的原始答案最适合我的情况。我只是不太高兴每次从数据库更新模型时都更改模型。这就是为什么我编写了一个额外的文本模板文件,该文件在模型更改后会自动调用 - 就像新生成的实体一样。我将其发布在这个评论中。
为了使其正常工作,请确保将其命名为 {model name}.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);
#>

I found the original answer of updating the .edmx file work best in my situation. I just wasn't too happy about altering the model every time it was updated from the database. That's why I wrote an additional Text Template file, that is automaticaly invoked when after the model has changed - just like the entities are newly generated. I post it here in this comment.
To make it work, make sure you name it like {model name}.something.tt, and store it in the same folder as your .edmx folder. I named it {model name}.NonPkTables.tt. It does not generate a file on its own due to the invalid file extension definition in the second line. Feel free to use.

<#@ 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);
#>
沉睡月亮 2024-12-13 20:00:10

我通过删除并重建 EF 项目及其所有类来修复它。请参阅下面的详细信息:

我在这个问题上反复研究了一个小时,然后删除了包含错误的 EF 项目,保存了所有自定义代码,然后重建了整个项目。由于这只是生成一个新的 EF 图及其内部代码的问题,因此修复问题的过程大约需要 10 分钟。

我怀疑问题在于,用于生成 EF 类和属性的数据库优先方法在两到三次“更新”后变得有点奇怪。基本上,我发现代码行为存在问题,修复了数据库表属性,然后多次更新了 EF 图。然后我尝试摆弄代码,但没有成功。

重新开始有效。

I fixed it by just deleting and rebuilding the EF project and all its classes. See details below:

I went round and round on this one for an hour, then deleted the EF project containing the error, saving out all my custom code, then rebuilding the whole thing. Since it was just a matter of generating a new EF diagram and its inner code, this process of fixing the problem took about 10 minutes.

The problem, I suspect, is that the database-first method for generating EF classes and properties gets a little weird after two or three "updates". Basically, I found a problem in the code behavior, went and fixed the database table properties, and then updated the EF diagram one time too many. Then I tried fiddling with the code, which didn't work.

Starting over worked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文