SQL Azure 中不存在数据库时,是否需要先迁移 EF 代码?

Do I need a migration for EF code first when the database does not exist in SQL Azure?

我已经尝试了很多 EF 迁移 v6.0.1 的变体(从没有数据库,到空数据库,再到现有数据库),但我对 Azure 数据库实例有一个特殊的问题能够在第一次部署时使用 Octopus 部署正确创建。

有很多地方可能会出错,所以我想如果可以的话,我会和你们这些优秀的人一起检查 EF Code First 迁移的一些基础知识:

如果我创建代码优先模型,并且知道数据库在 Azure 上的预期目标数据库服务器中不存在。默认情况下 'CreateDatabaseIfNotExists' 方法 禁用 AutomaticMigrations;

如果我随后使用包含我的 DbContext 和迁移配置的程序集调用 'migrate.exe',我会得到一个使用模型当前状态创建的新数据库吗?或者我会得到一个什么都没有的新数据库吗?即我是否需要明确 'add-migration' 模型的初始状态?

我在文档中读到数据库实例应该由迁移过程自动创建,但是没有人明确说明(至少对我而言)这个新创建的数据库将使用当前模型生成而无需正式的'initial state' 迁移已创建。

所以问题是:我是否需要为 migrate.exe 生成的显式迁移模型才能工作?

通过我尝试的任何方式,我得到了一个数据库,但应用程序启动时显示了不友好的消息"Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations."请记住,这是刚开始创建数据库的同一个应用程序库(从头开始)我无法理解这是怎么发生的!

我确实通过 SQL Server management studio 手动删除了几次目标数据库,这很糟糕吗?我是否删除了一些需要恢复的重要用户帐户?

迁移和数据库初始化器CreateDatabaseIfNotExists不一样

Migrations 使用数据库初始化器 MigrateDatabaseToLatestVersion,它依赖于数据库 _MigrationsHistory.

中的特殊 table

相比之下,CreateDatabaseIfNotExists 是依赖于特殊数据库 table EdmMetadata 的数据库初始化器之一。它完全按照它所暗示的那样做:创建一个数据库,其中 tables 匹配模型的当前状态,即每个 DbSet<T> 的 table仅当数据库不存在时.

您在此处引用的特定错误 Model compatibility cannot be checked because the database does not contain model metadata. 是由于存在 DbSet<T> 个对象而发生的,这些对象被添加到代码库 之后 初始数据库创建,不存在于 EdmMetadata.

有 4 个基本的数据库初始化程序可用,其中 3 个在不使用迁移时使用:

  • CreateDatabaseIfNotExists
  • DropCreateDatabaseWhenModelChanges
  • DropCreateDatabaseAlways

另请注意,第 4 个初始化程序 MigrateDatabaseToLatestVersion 将允许您使用迁移 ,即使 AutomaticMigrations 已禁用; AutomaticMigrations 有不同的用途,不直接与数据库初始化程序交互。

如果您打算使用迁移,您应该将数据库初始值设定项更改为 MigrateDatabaseToLatestVersion 而忽略其他 3 个。相反,如果您打算 使用Migrations,那么Initializer的选择视情况而定。

  • CreateDatabaseIfNotExists 当您确定您的数据模型没有进行主动更改并且您只打算关心新部署上的数据库创建时,将更合适。此初始化程序将帮助确保您不会因意外删除数据库或实时数据而遇到任何问题。
  • DropCreateDatabaseWhenModelChanges 在开发中最合适,当您经常更改模型并希望能够验证对模型的这些更改时。它不适用于生产服务器,因为对模型的更改可能会无意中导致重新创建数据库。
  • DropCreateDatabaseAlways 仅适用于测试,每次您 运行 测试时,您的数据库都是从头开始创建的。

Migrations 与这 3 个数据库初始化程序不同,因为它从不 删除 数据库 ,它改为使用 Data Motion 执行一系列 Create TableDrop Table SQL 调用。

您还可以随时在程序包管理器控制台中使用 Update-Database -Script -SourceMigration:0,无论您使用的是哪个数据库初始化程序,都可以生成完整的 SQL 脚本,可以是 运行针对服务器重新创建数据库。

首先,非常感谢 Claies 帮助我弄清了这个问题的真相。我接受他的回答是正确的,因为最终是他的回答和一些额外阅读的结合让我找到了我的解决方案。

在回答 post 的实际问题 'Do I need a migration for EF code first when the database does not exist in SQL Azure?' 时,答案是肯定的,如果您禁用了自动迁移。但还有一点需要注意:

这个特定问题的 Azure 方面实际上与我的情况无关。我的问题有两方面:

  1. 生成的迁移与目标模型不同步。我是什么意思?我的意思是,我从我的本地数据库生成迁移脚本,该数据库本身与创建错误迁移的本地代码库不同步。这可以通过比较 __MigrationHistory 中模型文本的前几行看出。这种意识是通过参考这个有用的 post 来帮助的,它解释了它是如何工作的。

  2. 更令人尴尬的是(我相信我们都做到了)我的网站本身的章鱼部署(使用 Octopack)不知何故忽略了包含 Web.Config 文件.据我所知,这可能是在我安装了 Visual Studio 的转换扩展后发生的。在我的 nuget 包中,我可以看到有一个 web.config.transform 文件,但没有 web.config。基本上这意味着当应用程序启动时,它没有配置文件可以求助,根本没有连接字符串。但这导致了稍微误导性的错误

Model compatibility cannot be checked because the database does not contain model metadata.

虽然它应该说的是,没有连接字符串,你这个白痴。 希望这可以帮助人们在阅读 Claies 的回答和那个博客后更好地理解这个过程-post。首先,检查你有一个 web.config 文件并且里面有一个连接字符串...