繁体   English   中英

实体框架代码优先:如何手动更新数据库?

[英]Entity Framework Code-First: How to manually update the database?

我构建了一个小 WPF 演示应用程序,它使用 EF Code-First 将其数据保存在 SQL CE 4.0 DB 中。 除非我从 model object 中删除一个属性,否则它工作正常。 例如,如果我从这个 class 中删除“HosteBy”......

public class Dinner
{
    public int DinnerID { get; set; }
    public string Title { get; set; }   
    public DateTime EventDate { get; set; }
    public string Address { get; set; }
    public string HostedBy { get; set; }

    public virtual ICollection<RSVP> RSVPs { get; set; }
}

...它抛出这个异常:

自数据库创建以来,支持“NerdDinners”上下文的 model 已更改。 手动删除/更新数据库,或使用 IDatabaseInitializer 实例调用 Database.SetInitializer。 例如,DropCreateDatabaseIfModelChanges 策略将自动删除并重新创建数据库,并可选择使用新数据为其播种。

即使从数据库中手动删除了“HosteBy”字段,该错误仍然存在。 我在这里想念什么? 我必须删除/截断数据库还是有其他解决方案?

在您更改 Code First Model 的第一个场景中,在您手动修改数据库之前,答案是打开 (Nuget) Package 管理器控制台并键入:

update-database -verbose

除了 - 因为在这种情况下您正在删除一个列,这将报告它即将删除某些内容,并且如果您没有明确表示可以,它不会删除任何内容。 所以你输入:

update-database -f -verbose

现在这将删除您在 Model 中的列。 -verbose告诉你它运行的 SQL。 如果您害怕让它删除东西,而是在 SQL 运行之前检查它,请使用:

更新数据库 -f -脚本

这会将 SQL 转储到您可以查看的脚本中,然后自己手动运行。

在您继续手动删除数据库中的列的情况下,您现在手头有一个更复杂的场景; 此处另一个答案中描述的 EdmMetadata 表包含整个数据库的 hash 现在与数据库本身不匹配。 您可以运行手动 SQL 以通过检查您之前拥有的内容和您的数据库当前的外观,将数据库返回到实体框架所期望的方式(手动修改之前的方式,使其与哈希一致)。

如果这不可行,那么您现在处于 Entity Framework Code First 中最丑陋的部分。 您需要消除 hash 表并将数据库反向工程为代码文件。

hash 表名取决于 EF 的版本。 在您所询问的旧版 EF4 中,它称为 EdmMetadata。 在较新的 EF5 中,它称为 __MigrationHistory(如果您正在查看 SQL Server Management Studio,则在数据库中的系统表下)。 你需要把它擦掉。

第二步(将数据库逆向工程为代码)的好消息是,Microsoft 已经发布了一个测试版工具,可以为您执行此操作。

对数据库进行逆向工程和 EF Power Tools 演练

您可以跳过那里的许多第一步,因为他们只是设置数据库并添加一些废话,以便他们可以演示您需要做什么:对数据库进行逆向工程。

更新:

使用手动迁移来解决这种情况也是可行的。 备份数据库,然后运行:

add-migration WhateverYouWantToCallThis

需要运行的对 db EF Migrations 的修改将出现在生成的 C# 命令中。 现在由您来修改它们,以解决它试图做的问题(例如尝试删除已删除的列),并落实未来需要的事情(例如添加回您在 model 中仍有一个表,但您在数据库中手动删除了)。

添加并运行update-database -f后,EF Code First 将相信您已按照需要的方式更新了数据库,并根据最终结果更新其 hash。 如果您进行了正确的更改,您现在可以正常进行迁移。 如果这仍然导致错误,您通常可以将手动迁移的命令复制到某处并将其删除,从备份中恢复数据库,再次添加手动迁移并重试。 最坏的情况是您求助于上面的逆向工程步骤。

如果您的数据库包含一些名为EdmMetadata的奇怪表,则您的上下文使用一些非常基本的数据库版本控制。 When it created the database it stored a hash of your model into this table and each time it builds a model for your application (first time you use the context after restarting your application) it again computes the hash and compares it with the hash stored in那张桌子。 这意味着您的 model 中的任何更改都将导致不同的 hash 和 EF 将对您看到的异常做出反应。 手动更改数据库对您没有帮助,因为该表包含仍然是旧的。

解决方案是:

  • 删除此版本控制。 它需要按照此处所述删除IncludeMetadataConvention
  • 更新 hash。 It would require to reverse engineer the algorithm for hash computation (for example by Red Gate .NET Reflector, JetBrains dotPeek, SharpDevelop ILSpy or Telerik JustDecompile) and computing new hash from compiled model (or using reflection to read internal property from DbCompiledModel.ModelHash with already计算哈希),您将存储在EdmMetadata表中。
  • 手动删除数据库并让 EF 创建一个新数据库 - 您将丢失所有数据
  • 将初始化程序设置为DropCreateDatabaseIfModelChanges - 如果您更改 model,它将自动删除数据库并创建一个新数据库 - 您将丢失所有数据

查看本文关于使用现有数据库进行代码优先迁移的部分
http://msdn.microsoft.com/en-us/data/dn579398

有时您的项目和数据库可能会不同步。 因此,您可能必须根据现有数据库重新同步您的架构。



1) 基于现有架构创建迁移:
添加迁移初始创建

2) 之后运行 Update-Database 以将条目添加到 _MigrationsHistory 表中,以指示迁移已完成到现有架构。

使用 Code First 时需要记住的三个简单事项

  1. 启用迁移
  2. 添加迁移
  3. 更新数据库

一切都是不言自明的。

您需要在 Package Manager Console 上手动运行这些命令。 我迟到了,但希望它会有所帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM