如何正确使用SSDT和Visual Studio 2012数据库项目pipe理数据库部署?

我正在研究阶段试图在现有的小型项目上采用2012年数据库项目。 我是C#开发人员,而不是DBA,所以我不是特别stream利的最佳实践。 我一直在寻找谷歌和stackoverflow几个小时,但我仍然不知道如何正确处理一些关键的部署scheme。

1)在几个开发周期中,如何pipe理我的数据库的多个版本? 如果我在我的数据库的v3上有一个客户端,并且我想将其升级到v8,我该如何pipe理它? 我们目前为我们产品的每个版本pipe理手工架构和数据迁移脚本。 我们是否还需要单独做这件事,或者是否有新的模式支持或取代这个模式?

2)如果模式的变化需要数据移动,那么处理这个问题的最好方法是什么? 我假定Pre-Deployment脚本中有一些工作用于保存数据,然后Post-Deploy脚本将它放回正确的位置。 这是它的方式还是有更好的?

3)对于如何更好地使用这些新技术的任何其他build议或指导也非常感谢!

更新:自从我最初提出这个问题以来,我对这个问题的理解有所增加,而当我提出一个可行的解决scheme时,这并不是我所希望的解决scheme。 这里是我的问题的重新说明:

我遇到的问题纯粹是与数据有关。 如果我在我的应用程序的第一版上有一个客户端,并且我想将它们升级到我的应用程序的第五版,那么如果他们的数据库没有数据,我就不会遇到问题。 我只是简单地让SSDT智能地比较模式并一次性迁移数据库。 不幸的是客户有数据,所以并不那么简单。 架构从我的应用程序的版本1更改为版本2到版本3(等)所有影响数据。 我目前的数据pipe理策略要求我维护每个版本升级的脚本(1到2,2到3等)。 这可以防止我直接从我的应用程序版本1到版本5,因为我没有数据迁移脚本直接去那里。 为每个客户创build自定义升级脚本或者pipe理从每个版本到每个更高版本的升级脚本的前景是指数级无法pipe理的。 我所希望的是,SSDT能够实现某种策略,使事物的数据pipe理更容易,甚至可以像事物的模式一样简单。 我最近使用SSDT的经验并没有给我这样一个存在的策略的希望,但我希望有不同的发现。

我一直在做这个,我可以告诉你,这并不容易。

首先,为了解决JT的答复 – 即使使用SSDT的声明性更新机制,也不能排除“版本”。 SSDT做一个“非常体面”的工作(假如你知道所有的开关和陷阱)将任何源模式移动到任何目标模式,这确实不需要verioning本身,但它不知道如何pipe理“数据动议“(至less不是我能看到!)。 所以,就像DBProj一样,你在Pre / Post脚本中留下了自己的设备。 由于数据运动脚本依赖于已知的开始和结束模式状态,因此无法避免对数据库进行版本控制。 因此,“数据移动”脚本必须应用于模式的版本化快照,这意味着您不能随意更新从v1到v8的数据库,并期望数据移动脚本v2到v8能够正常工作(假定您不会需要一个v1数据运动脚本)。

不幸的是,在SSDT发布中,我看不到任何机制,使我能够综合处理这种情况。 这意味着你将不得不添加自己的scafolding。

第一个技巧是跟踪数据库中的版本(和SSDT项目)。 我开始在DBProj中使用一个技巧,并把它带到SSDT,经过一番研究,结果发现其他人也在使用这个技巧。 您可以将数据库扩展属性应用到数据库本身(称为“BuildVersion”或“AppVersion”或类似的东西),并将版本值应用于它。 然后,您可以在SSDT项目本身中捕获此扩展属性,SSDT将其作为脚本添加(然后可以检查包含扩展属性的发布选项)。 然后,我使用SQLCMDvariables来确定当前传递中应用的源版本和目标版本。 一旦确定源(项目快照)和目标(即将更新的目标数据库)之间的版本差异,您可以find所有需要应用的快照。 不幸的是,在SSDT部署中这样做很棘手,您可能需要将其移至构build或部署pipe道(我们使用TFS自动部署并具有自定义操作来执行此操作)。

下一个障碍是保持模式的快照以及与其关联的数据运动脚本。 在这种情况下,有助于使脚本尽可能地具有幂等性(也就是说,您可以重新运行脚本而不会产生任何不良副作用)。 它有助于将可以安全地重新运行脚本的脚本拆分为只能执行一次的脚本。 我们对静态引用数据(字典或查找表)做了同样的事情 – 换句话说,我们有一个MERGE脚本库(每个表一个),使参考数据保持同步,这些脚本包含在post中 – 部署脚本(通过SQLCMD:r命令)。 这里要注意的重要一点是,如果这些引用表中的任何一个引用了FK, 就必须按照正确的顺序执行它们。 我们将这些脚本依次包含在主要的部署后脚本中,这有助于我们创build一个为我们生成这些脚本的工具 – 它也解决了依赖性顺序。 我们在“版本”结尾处运行这个生成工具来捕获静态引用数据的当前状态。 所有其他数据移动脚本基本上都是特例,并且很可能只是一次性使用。 在这种情况下,您可以执行以下两项操作之一:可以针对数据库版本/应用程序版本使用IF语句,也可以在创build每个快照包后清除1次脚本。

这有助于记住SSDT将禁用FK检查约束,只有在部署后脚本运行后才能重新启用它们。 这给你一个机会填充新的非空字段,例如(顺便说一句,你必须启用该选项来生成非空列的临时“智能”默认值,使其工作)。 但是,FK检查约束仅在由于模式更改而正在重新创buildSSDT的表中禁用。 对于其他情况,您有责任确保数据运动脚本以正确的顺序运行,以避免检查限制投诉(或者手动禁用/重新启用脚本中的脚本)。

DACPAC可以帮助您,因为DACPAC本质上是一个快照。 它将包含描述模式的几个XML文件(类似于项目的构build输出),但是在您创build它时及时冻结。 然后,您可以使用SQLPACKAGE.EXE或部署提供程序发布该包快照。 我还没有弄清楚如何使用DACPAC版本,因为它与“已注册”的数据应用程序相关联,所以我们坚持使用我们自己的版本控制scheme,但是我们将自己的版本信息放入DACPAC文件名。

我希望我有一个更确凿和详尽的例子来提供,但我们也在这里解决这个问题。

有一件事情真的吸引SSDT是不同于DBProj,它目前不能扩展。 尽pipe它在很多不同的事情上比DBProj做得好得多,但是除非你能够在前/后脚本中find解决问题的方法,否则你不能覆盖它的默认行为。 我们现在试图解决的一个问题是,当你有数千万条logging时,重新创build更新表(CCDR)的默认方法真的很糟糕。

-UPDATE:我有一段时间没有看到这篇文章,但是显然它最近一直很活跃,所以我想添加一些重要的注意事项:如果你使用的是VS2012,SSDT的2013年6月发行版现在有一个Data比较工具内置,并提供可扩展性点 – 也就是说,您现在可以包含项目的构build贡献者和部署计划修饰符。

我还没有真正发现有关这个主题的更多有用的信息,但是我花了一些时间去了解工具,修补和玩耍,我想我已经拿出了一些可以接受的答案来解决我的问题。 这些不一定是最好的答案。 我仍然不知道是否有其他机制或最佳实践来更好地支持这些情况,但是这里是我想到的:

给定版本的数据库的Pre-Deploy脚本和Post-Deploy脚本仅用于迁移以前版本的数据。 在每个开发周期开始时,脚本都会被清理出来,随着开发的进行,他们将得到充实的数据,从而安全地将数据从以前的版本迁移到新版本。 这里的一个例外是数据库中的静态数据。 此数据在devise时已知,并以T-SQL MERGE语句的forms保留在Post-Deploy脚本中。 这有助于使用最新的发布脚本将任何版本的数据库部署到新的环境中。 在每个开发周期结束时,将从前一个版本生成一个发布脚本。 该脚本将包括生成的sql来迁移模式和手工部署脚本。 是的,我知道发布工具可以直接用于数据库,但这不是我们的客户的一个好select。 我也知道dacpac文件,但我不知道如何使用它们。 生成的发布脚本似乎是我知道的用于生产升级的最佳select。

所以要回答我的情况:

1)要将数据库从v3升级到v8,我必须执行v4生成的发布脚本,然后是v5,然后是v6等。这与我们现在的做法非常相似。 很好理解,数据库项目似乎使创build/维护这些脚本变得更容易。

2)当架构从数据下方更改时,使用Pre-and-Deploy部署脚本将数据迁移到新版本所需的位置。 受影响的数据本质上是在Pre-Deploy脚本中备份的,并在Post-Deploy脚本中放回原位。

3)我仍然在寻找如何在这些场景和其他方面使用这些工具的build议。 如果我在这里遇到任何问题,或者我还有其他问题,请告诉我! 谢谢!

在我使用SSDT的经验中,数据库的版本号(例如v1,v2 … vX等等)的概念有点过时了。 这是因为SSDT提供了一种称为声明式数据库开发的开发模式,它松散地表示您告诉SSDT您希望您的模式处于什么状态,然后让SSDT负责通过与您已有的状态进行比较来负责进入该状态。 在这个范例中,部署v4和v5等概念将消失。

正如您正确指出的那样,您的前置和后置部署脚本存在用于pipe理数据的目的。

希望有所帮助。

JT

我只是想说,这个线程迄今为止非常好。

我一直在斟酌同样的担忧,并试图在我们的组织中解决这个相当大的遗留应用程序中的这个问题。 我们已经开始了向SSDT(在TFS分支上)的过程,但是我们真的需要了解部署过程,并且一直在pipe理自定义的迁移以及引用/查找数据。

更复杂的是,我们的应用程序是一个代码库,但可以根据“客户”进行定制,所以我们有大约190个数据库,对于这个项目,不仅仅是3个左右,或许正常。 我们一直在进行部署,甚至经常设置新的客户。 现在,我们严重依赖PowerShell和旧版增量发布脚本(以及相关脚本在该版本中创build新客户)。 我计划一旦我们把这一切全部拿出来,但请分享你学到的东西。 我相信我们最终会维护每个版本的自定义发行脚本,但是我们会看到。 关于在项目中维护每个脚本的想法,包括From和To SqlCmdvariables是非常有趣的。 如果我们这样做了,那么我们可能会一路修剪,一旦所有人都超过这个版本,就会删除真正的旧升级脚本。

顺便说一句 – 关于最小化浪费的问题,我们还花了一些时间来弄清楚如何自动执行列的正确命名/数据types约定,以及基于所有主键和外键的自动生成关于命名规则,以及索引和检查约束等。最难的部分是处理不遵守规则的“exception”。 如果有人有兴趣的话,也许我也会分享一下,但是现在我需要大量的部署,迁移和参考数据。 再次感谢。 就好像你们今天早上正在说什么在我脑海里一样。