使用TeamCity自动部署SQL更改(替代Redgate?)

时间:2013-09-03 10:27:05

标签: .net sql-server svn teamcity

我正在使用TeamCity为我们的测试环境创建用于.NET应用程序的CI和自动部署(使用SVN控制的源代码),并且一切顺利。我正处于我想要自动执行db脚本的阶段。我已经做了一些搜索并阅读了几篇文章,例如http://www.troyhunt.com/2011/02/automated-database-releases-with.html(特洛伊特的博客非常宝贵!),许多人似乎都指出使用RedGate软件来管理和部署变更。我有点担心让一个新工具处理脚本生成,所以我想知道是否有其他可接受的方法值得调查。

我们当前的解决方案设计标准包括一个包含数据库相关文件的项目,例如我们的orm db。它还包含一系列文件夹,其中包含我们的更改脚本,如下所示。

MySolution
 > MySolution.Data
    > 3.0 Scripts
       * 01 - UpdateUserTable.sql
       * 02 - UpdateRoleTable.sql
    > 3.1 Scripts
       * 01 - CreateJobTable.sql
       * 02 - InsertJobTypes.sql
       * 03 - AndSoOn.sql

我认为这种结构非常重要,因为虽然我们希望在签入时自动部署到我们的测试环境,但我们部署实际版本的频率要低得多,而且我不确定RedGate的比较工具是否可以处理有时会发生的变化。这就是为什么我更喜欢使用脚本的版本文件夹,然后在发布时增加次要内容以保持脚本版本的整齐包含。

有了这个预先存在的结构,我倾向于保留它并添加一个TeamCity构建定义,该定义可以在成功部署时应用db脚本。我想我可以让TeamCity在预期路径中向SVN识别新添加的.sql文件,然后在服务器上执行这些文件,但也许我开始期待开箱即用。我过去使用TFS和MSBUILD以及自定义构建步骤实现了这种解决方案,但对于TeamCity方式我是全新的。

是否已经有了实现这样的目标的过程?在我看来,这是一个非常正常的实现,我还没有找到如何。或者RedGate解决方案是我们应该采用的标准吗?

3 个答案:

答案 0 :(得分:4)

我在2年前读过同样的特洛伊亨特文章。这是一个启示,我很快就开始使用SQL Source Control + SQL Compare + TC。这是一个很好的解决方案,但是有一些东西不能像我想的那样工作。其中最主要的是SQL Source Control不支持(或不支持)分支/合并策略。此外,SQL Source Control是一个带外过程,需要开发人员培训,采用和了解其怪癖。它从未扎根。我们的团队最终离开了RedGate,转而支持TeamCity驱动的Entity Framework迁移,我们没有回头。

直接提出问题:我认为你在这里尝试做的事情是可能的,尽管我认为寻找新添加的SQL脚本不一定是TeamCity的工作。红门和实体框架都识别数据库本身中最近部署的脚本/迁移,并在确定应该开始应用更改的位置时引用它。您可以在数据库中存储类似的值('3.0'),或者作为TC构建参数,然后使用powershell迭代较新的文件夹并使用 sqlcmd 应用最新的脚本。

您可能会考虑查看基于EF的迁移,特别是如果您采用了代码优先模型。如果您有兴趣,我可以更新此答案,以更多地谈论我们如何做到这一点。

<强>更新

EF代码优先迁移通过捕获迁移类中的一组离散数据库模式更改来工作。此类具有UpDown方法,可以应用/反转特定批量的架构更改。这或多或少等同于Ruby和其他人的做法。

当您对实体模型进行更改(添加表,删除列,更改约束等)时,可以通过在程序包管理器控制台中调用Add-Migration <DescriptionOfSchemaChange>来创建新的迁移类。这将生成名为<timestamp>_<DescriptionOfSchemaChange>.cs的新类。然后,您可以通过调用Update-Database在本地应用该迁移。实体框架为您管理细节,但您可以根据需要将任意SQL注入迁移步骤。 PluralSight提供了涵盖这些概念的great course

迁移由可执行文件migrate.exe管理,该可执行文件作为Entity Framework NuGet包的一部分进行部署。在TeamCity中,您可以使用migrate.exe针对指定的数据库运行迁移。首先,您必须将migrate.exe本地复制到包含迁移类的程序集。然后,您只需使用数据库连接字符串作为参数对该程序集运行migrate.exe。工作目录是迁移程序集的目录。

copy ..\..\packages\EntityFramework.5.0.0\tools\migrate.exe .

migrate.exe ASSEMBLY.dll /connectionString="CONNECTION_STRING" /connectionProviderName="System.Data.SqlClient"

答案 1 :(得分:2)

经过大量搜索和了解我如何实现目标后,我决定继续编写我自己的控制台应用程序,为我做这个。我将在这里列出基本步骤,以后可以更详细地将它们充实。

DatabaseRevisionUpdater(控制台应用)

  1. 使用SVNSharp,DatabaseRevisionUpdater挂钩到我们的SVN服务器 并从指定的SVN版本范围读取SQL脚本文件到内存中。
  2. 在.NET创建的Transaction中,应用程序然后逐个读取脚本文件。如果在运行这些脚本时遇到任何错误,则回滚事务并退出应用程序,错误代码为-1。
  3. 目标数据库应包含一些新的日志记录表,这些日志表在更新时写入。版本表跟踪哪些修订,成功和失败。单独的表包含有关为此修订请求运行的每个脚本的信息(状态为Successful,Failed和Skipped)。
  4. 当进行未来更新时,将根据步骤3中的表确定数据库的版本。如果请求与之前的任何成功更新相交,则更新将不会继续,因为它假定已经应用了更新。 SVN更新修订版也可以从这些表中确定。
  5. TeamCity Integration

    • 添加了Runner type:Command Line
    • 的构建步骤
    • 工作目录是包含我的控制台应用程序的构建服务器上的目录
    • 运行:自定义脚本(不要使用带参数的可执行文件,因为它似乎不能处理包含双引号的参数,比如我的dbConnectionString)
    • 自定义脚本:可执行文件后跟以我的数据库为目标的参数。参数包括svnUsername,svnPassword,svnPath,databaseConnectionString,最重要的是RevisionTo。我使用%build.vcs.number.APP_ID%来获取当前版本的修订号。

    奖金使用情况 - 更新已断开连接的数据库

    这一切都适用于我们的测试环境,但我们的实时环境位于一个无法访问svn或互联网的隔离网络上(出于安全考虑)。使用我的控制台应用程序,我使用了一些不同的模式。上面描述的模式是直接更新,这是一个一体化的解决方案。它通过查看其日志表来确定DB当前版本,它会轮询SVN以查找所有更新,直到您指定的修订版本为止,它会针对目标数据库运行它们并相应地更新其日志记录表。对于我们的现场环境,我添加了几个额外的模式。出口和进口。

    • 导出用于在修订范围内从SVN获取脚本。然后将它们保存到XML文件中。它根本不关心目标数据库。
    • 导入用于导入XML数据文件并将其中的更新应用于目标数据库。它关心版本兼容性,但与SVN无关。

    这基本上是我的解决方案。没有任何开箱即用,但它就像一个魅力。我可以很好地使TeamCity与它进行交互,并使用Console输出来详细描述使其尽可能透明的过程。 TeamCity在其构建日志中报告所有这些输出,也会失败或成功,具体取决于我的返回码是0或其他。

    作为一个星期的旅程,我决定做一个小博客文章,详细说明我是如何到达这里以防其他人感兴趣的:https://andrekriegler.wordpress.com/2013/09/12/auto-deploy-database/

答案 2 :(得分:0)

在Red Gate,我们正在研究我们称之为“迁移v2”的内容。这是一种数据库部署技术,它既使用模式比较方法,也允许用户指定自己的脚本,例如在数据运动情况下。

有一个series of web pages可以更好地描述这一点,以及a GoogleGroup forum

如果您对此功能有何疑问,请与我们联系。