我自己一直在做这件事,我可以告诉你这并不容易。
首先,要解决 JT 的回复 - 即使 SSDT 具有声明性更新机制,您也不能忽略“版本”。SSDT 在将任何源模式移动到任何目标模式方面做了一项“相当不错”的工作(前提是你知道所有的开关和陷阱),这确实不需要验证本身,但它不知道如何管理“数据运动”(至少我看不到!)。因此,就像 DBProj 一样,您可以在 Pre/Post 脚本中使用自己的设备。由于数据移动脚本依赖于已知的开始和结束模式状态,因此您无法避免对数据库进行版本控制。因此,“数据移动”脚本必须应用于模式的版本化快照,这意味着您不能随意将数据库从 v1 更新到 v8 并期望数据移动脚本 v2 到 v8 能够工作(大概,您不会
遗憾的是,我在 SSDT 发布中看不到任何允许我以集成方式处理这种情况的机制。这意味着您必须添加自己的脚手架。
第一个技巧是跟踪数据库(和 SSDT 项目)中的版本。我开始在 DBProj 中使用一个技巧,并将其带到 SSDT,经过一些研究,结果发现其他人也在使用它。您可以将数据库扩展属性应用于数据库本身(称其为“BuildVersion”或“AppVersion”或类似名称),并将版本值应用于它。然后,您可以在 SSDT 项目本身中捕获此扩展属性,SSDT 会将其添加为脚本(然后您可以检查包含扩展属性的发布选项)。然后,我使用 SQLCMD 变量来识别当前传递中应用的源版本和目标版本。一旦确定了源(项目快照)和目标(即将更新的目标数据库)之间的版本增量,您就可以找到所有需要应用的快照。在SSDT 部署中,您可能必须将其移动到构建或部署管道(我们使用 TFS 自动部署并有自定义操作来执行此操作)。
下一个障碍是保留模式的快照及其相关的数据移动脚本。在这种情况下,它有助于使脚本尽可能具有幂等性(这意味着,您可以重新运行脚本而不会产生任何不良副作用)。它有助于将可以安全地重新运行的脚本与必须只执行一次的脚本分开。我们对静态参考数据(字典或查找表)做同样的事情 - 换句话说,我们有一个 MERGE 脚本库(每个表一个),它使参考数据保持同步,这些脚本包含在帖子中-部署脚本(通过 SQLCMD :r 命令)。这里要注意的重要一点是,您必须以正确的顺序执行它们,以防这些引用表中的任何一个具有彼此的 FK 引用。我们按顺序将它们包含在主要的部署后脚本中,这有助于我们创建一个为我们生成这些脚本的工具——它还解决了依赖顺序。我们在“版本”结束时运行此生成工具,以捕获静态参考数据的当前状态。您的所有其他数据移动脚本基本上都是特殊情况,并且很可能只是一次性使用。在这种情况下,您可以做以下两件事之一:您可以针对 db build/app 版本使用 IF 语句,或者您可以在创建每个快照包后清除 1 次脚本。
它有助于记住 SSDT 将禁用 FK 检查约束,并且仅在部署后脚本运行后重新启用它们。例如,这使您有机会填充新的非空字段(顺便说一句,您必须启用为非空列生成临时“智能”默认值的选项才能使其工作)。但是,仅对 SSDT 由于架构更改而重新创建的表禁用 FK 检查约束。对于其他情况,您有责任确保数据移动脚本以正确的顺序运行以避免检查约束投诉(或者您在脚本中手动禁用/重新启用它们)。
DACPAC 可以帮助您,因为 DACPAC 本质上是一个快照。它将包含几个描述架构的 XML 文件(类似于项目的构建输出),但在您创建它时会及时冻结。然后,您可以使用 SQLPACKAGE.EXE 或部署提供程序发布该包快照。我还没有完全弄清楚如何使用 DACPAC 版本控制,因为它更依赖于“注册”数据应用程序,所以我们坚持使用自己的版本控制方案,但我们确实将自己的版本信息放入 DACPAC 文件名。
我希望我能提供一个更有说服力和详尽的例子,但我们仍在解决这里的问题。
SSDT 真正糟糕的一件事是,与 DBProj 不同,它目前不可扩展。尽管它在很多不同的事情上都比 DBProj 做得更好,但你不能覆盖它的默认行为,除非你能在前/后脚本中找到解决问题的方法。我们现在试图解决的问题之一是,当您拥有数千万条记录时,重新创建更新表 (CCDR) 的默认方法确实很糟糕。
-更新:我已经有一段时间没有看到这个帖子了,但显然它最近很活跃,所以我想我会添加一些重要的注意事项:如果你使用的是 VS2012,2013 年 6 月发布的 SSDT 现在有一个数据内置比较工具,还提供扩展点——也就是说,您现在可以为项目包含 Build Contributors 和 Deployment Plan Modifiers。