如何使用edmx文件更新数据库更改?

56

我有一个.edmx文件,我更改了我的数据库中的一张表。我知道有“从数据库更新模型”的向导,但在许多情况下这是无用的。

例如,如果我将字段从非空更改为可空,或者如果我删除字段,则更新模型不会反映更改。我必须删除实体并将其添加回来才能让更改出现在我的模型中。

根据以下问题:如何将数据库更改传播到我的.edmx文件?

其中一个答案似乎也是这样说的,你需要删除实体并将其添加回来。

这是最终答案还是有更好的方法可以做到这一点?


可能是[更新您的edmx以反映在您的db中所做的更改(.net linq-to-entities)]的重复问题(https://dev59.com/jnRB5IYBdhLWcg3wNk53) - Tim Abell
6个回答

65

以安全的方式更新EDMX:

正如您所发现的,从数据库更新不总是正确更改现有属性。

根据我们在日常使用中对EDMX更新(24个月内进行了数百次更新)的经验,我建议按照以下顺序更新EDMX。

删除现有模型,然后更新:

  1. 打开EDMX设计器
  2. Ctrl-A选择全部
  3. 按Delete键删除设计器中的所有模型
  4. 重要提示:如果您正在使用TFS进行源代码控制,请不要在此时保存EDMX!*
  5. 现在右键单击并选择“从数据库更新模型”以重新创建整个模型。
  6. 重新构建项目以传播更改

这显然会丢失您对模型所做的任何手动调整,但应尽可能避免手动调整。这使整个过程可以在任何时间重现(这是一件好事)。

重要提示:

  • 如果在Visual Studio中打开自动保存功能,则需要快速选择更新(上述第5步),以避免自动保存保存所有内容。
  • 如果您正在使用TFS进行源代码控制,并恰好在清空EDMX之后保存了EDMX,则TFS将标记所有生成的文件为“已删除”,并且再次更新EDMX可能会导致未连接到源代码控制的文件!
  • 此过程将不会更新任何存储过程。此外,我发现刷新EDMX也不会更新存储过程,即使只是返回类型已更改(截至EF 6.1.1)。

其他建议:

将您的EDMX保留在一个单独的库中。这也成为添加附加TT文件和部分类(例如,扩展EDMX模型的功能)的绝佳位置。我还将数据库上下文的所有扩展方法放在此库中。 迁移文件也在库中生成,使其整洁有序。

2015年4月更新

最新的Visual Studio 2013 Release 4似乎解决了许多TFS问题。我们现在可以看到Visual Studio检出生成的文件,然后如果它们未更改,则撤消操作。上述步骤仍然是最安全的方法。

更新于2015年9月

使用最新的VS2013 Release 5,在EDMX更新期间发生保存仍会出现问题。您仍可能处于待删除状态,在更新期间从源代码控制中删除tt文件。秘诀是在步骤4和5之间快速更新! :)


在从数据库更新模型后,是否有一种好的方法始终将StoreGeneratedPattern设置为Identity,因为我们的Ids在SQL Server上默认为newid()? - OKEEngine
@JerryLiang:如前所述,执行此操作将丢失对EDMX的所有自定义调整。您只能使用默认的SQL设置,或在每次EDMX更新后重复自定义更改。默认的newid()应仅适用于新插入的记录,因此我不确定StoreGeneratedPattern = Identity实际上会有什么区别。也许您可以澄清一下? - iCollect.it Ltd
在更新edmx时,是否有一种方法可以将数据库结构导出到sql文件中? - Bakudan
@Bakudan:它并不是设计为来回使用的,但理论上你可以通过在edmx生成类上生成代码优先数据库。通常需要使用 SQL Server Management Studio 等工具创建一个数据库创建脚本。 - iCollect.it Ltd
@Gone Coding 感谢您分享这个详细的步骤。对于像我这样的人,如果读了 Gone Coding 的答案太晚并成功地从源代码控制中删除/断开文件,我所做的是在 edmx 文件(最好是整个数据层)上执行 撤消待处理更改。然后我获取了最新版本。发生的事情是我的 tt 文件现在回到了 SC 中。然后按照上面提到的步骤进行操作。希望有所帮助。 - Annie Lagang
@AnnieLagang:很高兴能帮到你。我们早已转而使用GIT存储库,因为TFS对我们来说变得太慢了(无论是本地还是云端)。干杯! - iCollect.it Ltd

46
一个重要的第一步是了解使用更新模型向导时发生了什么。
MSDN Library中:

ADO.NET实体数据模型设计器(实体设计器)使用更新模型向导将.edmx文件从对数据库所做的更改中进行更新。更新模型向导作为这个过程的一部分覆盖存储模型。当向数据库添加对象时,更新模型向导还会对概念模型和映射进行一些更改,但只有在向数据库添加对象时才会进行这些更改。例如,将表添加到数据库时,新实体类型将添加到概念模型中,并且将列添加到表时,实体类型将添加新属性。有关更新模型向导对.edmx文件进行的更改的详细信息,请参见Changes Made to an .edmx File by the Update Model Wizard

当您使用更新模型向导更新数据库时,它会更新.edmx文件中的存储模型而不是概念模型。对于已有对象定义的更改,只会更新存储模型而不会更新概念模型。有关更新模型向导所做更改的完整说明,请参见上面的“通过更新模型向导修改.edmx文件所做的更改”链接。
以下是如何更新未被更新模型向导更新的对象的一些选项(基于您修改列定义的情况):
  1. 使用更新模型向导(更新存储模型),使用设计器(默认设置)打开.edmx文件,找到所需的标量属性,并在“属性”窗口中编辑所需属性。
  2. 使用更新模型向导(更新存储模型),使用XML编辑器打开.edmx文件,在CSDL(概念模型)部分中找到所需的属性并更改所需属性。这与选项1基本相同,但您直接编辑XML(此处可能有用的是查找和替换)。
  3. 从“模型浏览器”中,删除概念模型的“实体类型”部分中的所需实体以及存储模型的“表/视图”部分中的所需表。然后使用更新模型向导将其添加回来。

最佳方案取决于给定的情况。例如,如果您只更改了一个列的定义,则选项1可能是最佳选择。如果您更改了单个表中多个列的定义,则选项3可能是最佳选择。如果您更改了在多个表中使用的列(例如主键/外键),则直接编辑.edmx XML可能是最佳选择。


1
太棒了!非常精准! - Pramod Sharma
1
这真是金子般的价值!谢谢! - Ben
谢谢这个……我学会了它的工作原理……大多数情况下,从EDMX中删除表格,然后从数据库更新对我来说是有效的……现在我知道为什么了。 - A3006
“概念模型”是什么?它除了作为一个模型的概念之外还有其他含义吗? - Gerry

4

步骤1: 双击.edmx文件。(图表窗口将打开)

步骤2: 在图表窗口上,右键单击并选择从数据库更新模型... (现在它只会在更新存储中更新,而不是在模型中)

步骤3: 右键单击Model.tt文件并点击运行自定义工具 (现在它也会在模型中进行更新)

就这样!


2

假设我已经在现有的表格中添加了一个新列(c1)。然后为了更新现有的实体模型,我会执行以下操作:

我会使用notepad ++打开.edmx文件。

我会在.edmx文件中添加c1属性,在每个c0节点下面加入c1节点。

    <EntityType Name="table">
      <Key>
        <PropertyRef Name="Id" />
      </Key>
      <Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
      <Property Name="c0" Type="nvarchar(max)" />
      <Property Name="c1" Type="nvarchar(max)" />
    </EntityType> 

重新在Visual Studio中加载项目。
最后,在模型中添加属性c1。

1

如果我理解你的问题和示例,一旦你完成了从数据库更新模型的步骤并且你正在Model.edmx图表上,你可以突出显示你想要更改的类中的属性,并显示其属性,将其Nullable属性更改为Nullable: True。这至少是一种方法。

我认为这里的想法是概念模型(从非空到可空不会被更改)实际上可能与底层数据库表不同,因此它不会更改该部分,而这种差异可能正是你想要的。我处理这个问题的两种方式是要么像你提到的那样进行删除和添加,要么更通常地手动设置我提到的属性。


是的,我想我明白你的意思。在我的情况下,我有一个非空字段,创建了我的edmx文件。然后我将实体更改为可为空。然后它抱怨数据库不可为空,而实体是可为空的。所以我也更新了数据库为可为空,并使用“从数据库更新模型”。但是,正如您所指出的那样,它不会更改null / not null属性。在这种情况下,我不能只更改实体而不生成错误。所以我删除并重新添加了实体,一切都好了。这不是什么大问题,但我想知道是否有更好的方法来解决这个问题。 - dtc

-1
  1. 首先,双击.edmx文件
  2. 其次,在空白处右键单击,并选择“从数据库更新模型”
  3. 第三步,在菜单栏上选择刷新选项卡。
  4. 最后,选择要刷新的表并选择完成。

2
错误。没有选择要刷新的表格 - 所有表格都将根据接受答案中描述的流程进行刷新。 - Niklas Wulff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接