我的公司使用Visual Studio数据库项目将更新部署到我们的数据库。据我所知,它提供了用于比较项目模式和目标DB的状态,并生成代码以将后者的模式更新为前者的功能。它还提供了一个部署前脚本和一个部署后脚本,但仅此而已。

缺少的是版本控制和/或订购的任何概念。例如,如果我想向表中添加不可为空的FK列,则需要分两个步骤进行操作-首先,使用部署后脚本将其添加为可为空的列,以更新行以使其具有有意义的值。第二,使列不可为空。这些必须按顺序进行。

据我所知,在通过Visual Studio数据库项目进行部署时,无法确保部署前和部署后脚本的这种顺序排序。我在这里吗?这有两个含义:首先,创建表后,您真的不能真正在表中添加不可为空的FK列;其次,部署前和部署后脚本将不断增长并包含因为它们都在数据库部署时每一次都运行,所以它们是从几年前开始就陷入困境的。

是否可以使用Visual Studio数据库项目进行版本更新,如果没有,是否存在可以进行这种版本控制的项目类型?

最佳答案

首先,您已在Visual Studio 2012上对此进行了标记-如果您使用的是Visual Studio 2012,请务必升级到vs 2013或2015,并获得最新版本的SSDT,因为该版本每3个月发布一次,具有新功能和修复功能,所以效果很好值得获得更新的版本-我在下面谈论的是当前行为,不知道在Visual Studio 2012的原始ssdt中是否可以使用所有这些功能。

有几句话要说,首先,您可以通过结合使用/p:BlockWhenDriftDetected和将数据库注册为数据层应用程序(/p:RegisterDataTierApplication)来执行有序部署。这将允许您执行以下操作:

  • 构建dacpac 1
  • 部署dacpac 1
  • 构建dacpac 2
  • 部署dacpac 2
  • 构建dacpac 3

  • 这将使您无法在部署dacpac 1之前部署dacpac 2,但这并不理想,因为如果在部署dacpac 2之前先构建dacpac 3,那么如果不重建dacpac 3就无法部署。 。

    当您处理数据库更改时(有时不仅是sql server,还有任何rdbms),有时需要分阶段发布更改,对我而言,这比技术问题更像是一个过程问题。我要做的是:
  • 创建更改的第一部分
  • 在积压订单中创建票证以完成更改
  • 部署更改
  • 在部署之后的 future 迭代中,拿起票证以完成更改
  • 部署完成

  • 需要注意的一些事情:
  • 需要纪律以确保您整理并完成工作,以敏捷的方式工作并不意味着马虎:)
  • 您编写的任何脚本都应是幂等的,因此,如果您要设置一些静态数据等,请使用诸如if是否存在检查或合并语句之类的内容,如果您修改任何模式对象,则将其包装在存在的情况下,等等。如果这样做,您会发现部署更简单的体验

  • 如果您遵循此过程,而不是依靠策略的版本控制类型,则不必担心部署dacpac的顺序,如果脚本很重要,则将其保留在部署后脚本中,并检查该脚本是否应该执行任何工作在这样做之前。如果脚本太大,则可以使用:r sqlcmd导入将其分成不同的文件。我也听说有人使用部署存储过程,并从部署后脚本中调用这些存储过程。

    我更喜欢只部署dacpac的最新(或特定版本)的过程,因为这意味着无论您要使用更高版本还是将其还原到早期版本,您都可以始终部署到该版本。

    最后,通过添加非空fk列的示例,可以一次部署dacpac来完成此操作。为此,您将:
  • 创建新的表定义(包括非null和外键约束)
  • 在您的部署后脚本中,对表进行更新,以便正确设置数据(显然使其具有幂等性,以便在需要时可以永久存在)
  • 部署启用时/p:GenerateSmartDefaults

  • 生成部署脚本时,将得到如下所示的脚本:
  • 部署前脚本(如果有)
  • 创建具有临时默认约束的列不为空
  • 删除临时约束
  • 使用nocheck创建外键,因此它实际上并未被执行
  • 运行部署后脚本
  • 使用“with check check”启用外键约束

  • 我提到的/p:参数是传递给sqlpackage.exe的参数。如果您不使用它,而是使用其他方式进行部署,则通常可以将其作为参数传递,如果让我知道遇到困难时如何部署,我可以为您提供帮助。有关args的说明,请参见https://msdn.microsoft.com/en-us/library/hh550080.aspx(sqlpackage.exe命令行语法)。

    让我知道,如果您有任何疑问,还需要考虑其他一些事情,但是检查模式定义并自动生成部署脚本会减少大量部署更改的工作,这意味着您可以专注于更有用的事情-编写单元测试对于一个:)。

    埃德

    10-08 19:10