Mik*_*ley 8 c# entity-framework database-update ef-code-first
背景:假设我正在使用实体框架,并且映射的实体之一如下:
class Foo
{
public int ID { get; set; }
public string Bar { get; set; }
// other useful properties
}
Run Code Online (Sandbox Code Playgroud)
使用映射:
class FooMap : EntityTypeConfiguration<Foo>
{
// bear me with, I know this is redundant right now
ToTable("Foo");
HasKey(e => e.ID);
Property(e => e.ID).HasColumnName("ID");
Property(e => e.Bar);
}
Run Code Online (Sandbox Code Playgroud)
在某个地方,我们需要更改列名称,Foo
因为我的老板告诉我Foo
需要一个更奢侈的名称ID
,否则我们的客户会不高兴。他告诉我们也将其重命名为“FooID”:
class FooMap : EntityTypeConfiguration<Foo>
{
// bear me with, I know this is redundant right now
ToTable("Foo");
HasKey(e => e.ID);
Property(e => e.ID).HasColumnName("FooID"); // Now you map to FooID
Property(e => e.Bar);
}
Run Code Online (Sandbox Code Playgroud)
就目前而言,如果我运行它,什么都不会改变。该Foo
表仍然会有一个名为的列ID
,它会抛出一个异常,告诉我该列FooID
不存在。
问题:如何让实体框架识别出我现在希望更新Foo
表,以便命名列ID
现在已命名FooID
?
更一般地说,如何让实体框架在不破坏现有数据的情况下自动将更改从我的代码传播到实际数据库中(比如在应用程序启动时)?
我不能只是“删除并重新创建”数据库,因为出于这个问题范围之外的原因,数据库在其中存储了一些不是通过我的代码中映射的模型创建的其他数据。删除它会导致我们丢失不能使用这种机制重新创建的表。
如何从实体框架噩梦中恢复 - 数据库已具有同名表
描述:如果您像我们一样,当您的团队刚接触 EF 时,您最终会处于无法创建新的本地数据库或无法将更新应用到生产数据库的状态。您想要回到干净的 EF 环境,然后坚持基础知识,但您做不到。如果你让它在生产环境中工作,你就无法创建本地数据库,如果你让它在本地环境中工作,你的生产服务器就会不同步。最后,您不想删除任何生产服务器数据。
症状:无法运行Update-Database,因为它正在尝试运行创建脚本并且数据库已具有同名的表。
错误消息:System.Data.SqlClient.SqlException (0x80131904):数据库中已存在名为 '' 的对象。
问题背景:EF 根据数据库中名为 dbo.__MigrationHistory 的表了解当前数据库与代码所在位置的比较。当它查看迁移脚本时,它会尝试将上次所在的位置与脚本进行协调。如果不能,它只是尝试按顺序应用它们。这意味着,它会返回到初始创建脚本,如果您查看 UP 命令中的第一部分,它将是发生错误的表的 CreateTable。
要更详细地了解这一点,我建议观看此处引用的两个视频: https: //msdn.microsoft.com/en-us/library/dn481501 (v=vs.113).aspx
解决方案:我们需要做的是欺骗 EF 认为当前数据库是最新的,而不应用这些 CreateTable 命令。同时,我们仍然希望这些命令存在,以便我们可以创建新的本地数据库。
步骤 1:清理生产数据库 首先,备份生产数据库。在 SSMS 中,右键单击数据库,选择“任务 > 导出数据层应用程序...”,然后按照提示操作。打开生产数据库并删除/删除 dbo.__MigrationHistory 表。
步骤 2:本地环境清理 打开您的迁移文件夹并将其删除。我假设如果有必要你可以从 git 取回这一切。
步骤 3:重新创建初始 在包管理器中,运行“Enable-Migrations”(如果您有多个上下文,EF 将提示您使用 -ContextTypeName)。运行“添加迁移初始-详细”。这将创建初始脚本,以根据当前代码从头开始创建数据库。如果您在之前的 Configuration.cs 中有任何种子操作,请将其复制过来。
步骤 4:欺骗 EF 此时,如果我们运行Update-Database,我们将得到原始错误。因此,我们需要欺骗 EF 使其认为它是最新的,而不运行这些命令。因此,进入您刚刚创建的初始迁移中的 Up 方法并将其全部注释掉。
步骤 5:更新数据库 由于在 Up 进程中没有要执行的代码,EF 将创建 dbo.__MigrationHistory 表,其中包含正确的条目,表明它正确运行了此脚本。如果你喜欢就去看看吧。现在,取消注释该代码并保存。如果您想检查 EF 是否认为其是最新的,您可以再次运行Update-Database 。它不会使用所有 CreateTable 命令运行 Up 步骤,因为它认为它已经完成了此操作。
第 6 步:确认 EF 实际上是最新的 如果您有尚未应用迁移的代码,这就是我所做的...
运行“Add-Migration MissingMigrations”这实际上将创建一个空脚本。因为代码已经存在,所以在初始迁移脚本中实际上有正确的命令来创建这些表,所以我只是将 CreateTable 和等效的 drop 命令剪切到 Up 和 Down 方法中。
现在,再次运行Update-Database并观察它执行新的迁移脚本,在数据库中创建适当的表。
第七步:再次确认并提交。 构建、测试、运行。确保一切都在运行,然后提交更改。
第 8 步:让团队的其他成员知道如何继续。 当下一个人更新时,EF 将不知道是什么击中了它,因为它之前运行的脚本不存在。但是,假设本地数据库可以被删除并重新创建,这一切都很好。他们需要删除本地数据库并再次从 EF 创建它。如果他们有本地更改和待处理的迁移,我建议他们在 master 上再次创建数据库,切换到其功能分支并从头开始重新创建这些迁移脚本。
归档时间: |
|
查看次数: |
20085 次 |
最近记录: |