根据 this blog post,大多数使用 EF 迁移的公司应该不会使用 EF 迁移更新生产数据库的数据库架构。相反,博客文章的作者建议在部署过程中使用 Schema 更新脚本。
我已经使用 Schema 更新脚本几年了,虽然它们可以工作,但我计划在未来使用 EF 迁移,原因如下:
更快的部署,更少的停机时间
更简单的部署过程
现有数据的迁移比使用 T-SQL 更容易
等待应用更改的更易于理解的语法(具有干净 C# 语法的 DbMigration 类与传统环境中笨拙的 T-SQL 迁移脚本)。
如果新软件版本的部署失败,则有一个简单快捷的旧数据库模式降级路径
我能想到禁止使用 EF 迁移生产数据库的一个原因是,如果数据库架构仅由 DBA 而不是开发人员更改。但是,我既是 DBA 又是开发人员,所以这对我来说并不重要。
那么,使用 EF 更新生产数据库有哪些风险?
编辑:我想补充一点,正如solomon8718 已经建议的那样,我总是将生产数据库的新副本拉到我的登台服务器上,并在将它们应用到生产服务器之前测试要在登台服务器上应用的 EF 迁移。 IMO 这对于生产系统的任何模式更新都是必不可少的,无论我是否使用 EF 迁移。
好吧,无论如何我都会尝试回答。我会说不,没有理由不在生产中使用 Code First 迁移。毕竟,如果你不能一路走下去,这个易于使用的系统又有什么意义呢?
我看到的最大问题是您已经注意到的任何系统都可能遇到的所有问题。只要整个团队(包括 DBA,如果适用)都参与其中,我认为允许 EF 通过迁移来管理架构并不复杂,因此比传统的基于脚本的管理更不容易出错。在生产系统上执行迁移之前,我仍然会进行备份,但无论如何你都会这样做。
也没有说 DBA 不能从 Visual Studio 执行迁移。仍然可以使用数据库级别的权限锁定访问权限,并且他/她可以在执行实际操作之前查看迁移(如果需要,使用 -Script
以有用的 SQL 导出格式)。然后它们仍然处于控制之中,但您可以使用代码优先迁移。地狱,他们甚至可能最终喜欢它!
更新:由于提出了 SPROC 和 TVF,我们也在迁移中处理它们,尽管它们实际上是通过使用 Up()
中的 DbMigration.Sql()
调用的直接 SQL 语句完成的,而在 {3 } (您也可以将 CreateStoredProcedure
和 DropStoredProcedure
用于简单的 SPROC,但我认为您仍然必须在 SQL 中定义主体本身)。我想你可以说这是一个警告;目前还没有一种方法可以完全用 C# 编写完整、全面的数据库。但是,您可以使用包含 SQL 脚本的迁移来管理整个架构。我们从这个过程中发现的一个好处是,您可以将 C# 配置文件用于架构对象名称(例如,生产与开发的不同服务器名称)和一个简单的 String.Format
,并结合配置文件本身的 XML 转换。
是的,有充分的理由不使用 Code First Migrations 等自动化系统来更改生产数据库。但与往常一样,规则也有例外。
已经提到的一个原因是访问权限,这将与您组织的变更管理规则和安全策略直接相关。另一个原因是您对迁移工具本身的信任程度。我们确定该工具没有错误吗?如果工具在中途失败会发生什么?你确定你有最新的备份和一个在需要时回滚的过程吗?更改脚本可能会执行意外或低效的脚本。我遇到过这样的情况,其中生成的 sql 将数据复制到临时表中,删除原始表,然后重新创建原始表以添加新列,如果您不小心(或故意)更改列出现的顺序,或者当您重命名表时。如果涉及数百万条记录,这可能会导致严重的性能问题。
我的建议:
假设您有一个反映您的生产模式的暂存数据库,请使用迁移工具针对该系统生成其更改脚本。我们通常在运行之前从一个新的生产副本中恢复我们的阶段数据库。然后我们手动检查更改脚本以检查问题。之后,我们针对我们的阶段数据库运行脚本,以确保它正确执行并且所有预期的更改都发生了。现在我们确信这些脚本既可以安全地在生产环境中运行,又可以执行预期的更改。这个过程将解决我上面列出的所有三个问题。
我发现的另一个警告:如果您有多个网站使用相同的数据上下文,则需要确保所有网站都同时更新。否则,网站之间可能会出现持续的数据库更新/降级之争。除此之外,它对我来说很好。
编辑:在开始在生产中使用 EF 迁移一年后,我自己的观点:
EF Migrations 实际上非常酷,即使用于生产,只要您
在暂存系统上测试迁移。在运行集成测试之前,我通过在我的 CI 服务器上一直向下和向上迁移来测试所有迁移。不要自动触发迁移,而是使用管理员启动的批处理文件。这与在 SSMS 中手动运行 sql 进行迁移基本相同。
我在几个项目的生产中使用它。一旦你掌握了它的窍门,我认为它很好。
在开发过程中,您可以保持自动迁移,但最后您可以直接从包管理器控制台连接到实时数据库并生成迁移。它将为您提供所有更改的迁移。
但始终始终将 -script
选项与 update-database
一起使用并自己触发 SQL。
我还建议不要使用 web deploy 中的 update db 选项。这样就无法判断有多少迁移已经因错误而被触发。我遇到过几次麻烦。所以最好获取 SQL 并手动触发它。