Publish 如何根据部署配置文件运行不同的SSDT发布前和发布后脚本

Publish 如何根据部署配置文件运行不同的SSDT发布前和发布后脚本,publish,sql-server-data-tools,Publish,Sql Server Data Tools,我正在Visual Studio 2013中使用SSDT 我已经为开发服务器创建了一些发布前和发布后脚本。预部署脚本清空表中的数据并重新设置所有自动标识字段。部署后脚本使用静态数据和示例数据填充表 现在我需要将数据库发布到我们的暂存和实时数据库服务器。我已经为这些服务器创建了新的“publish.xml”配置文件。但很明显,我不希望运行相同的pre和post脚本 如何根据发布配置文件指定不同的脚本,或使脚本了解目标并执行不同的操作 我最担心的是发布到live server并意外破坏数据 提前谢谢

我正在Visual Studio 2013中使用SSDT

我已经为开发服务器创建了一些发布前和发布后脚本。预部署脚本清空表中的数据并重新设置所有自动标识字段。部署后脚本使用静态数据和示例数据填充表

现在我需要将数据库发布到我们的暂存和实时数据库服务器。我已经为这些服务器创建了新的“publish.xml”配置文件。但很明显,我不希望运行相同的pre和post脚本

如何根据发布配置文件指定不同的脚本,或使脚本了解目标并执行不同的操作

我最担心的是发布到live server并意外破坏数据

提前谢谢


道格

你有几个选择:

1-将数据更改包装在对@servername的调用中或环境特有的调用中,这样您就可以:

if @@servername = 'dev_server'
begin
     delete blah
     insert blah

end
2-您还可以使用sqlcmd变量实现类似的功能,传入名为“/v:DestoryData=true”的变量或其他内容,然后您可以在脚本中引用该变量

3-不要使用部署前/部署后脚本,但要有自己的运行机制,即使用批处理文件部署DACPAC,并在部署前后添加对sqlcmd的调用-缺点是,在部署时,对表的更改会导致在部署前禁用所有外键,在部署后重新启用外键

4-编辑dacpac,部署前/部署后脚本只是dacpac中的文本文件,本质上是一个遵循microsoft打包格式的zip文件,并且有一个.net打包api可供修改

我想就是这样,如果有什么不清楚的地方,请询问:)


ed

我建议在条件脚本执行中使用SQLCMD变量

如果右键单击DB项目并选择属性,则会出现一个选项卡“SQLCMD变量”

输入“$(服务器名)”作为变量,输入一些内容作为默认值

然后,您需要在xml编辑器中打开EVERY.publish.xml,以便在PropertyGroup部分之后插入以下代码:

<ItemGroup>
    <SqlCmdVariable Include="ServerName">
        <Value>[YourVersionOfServer]</Value>
    </SqlCmdVariable>
</ItemGroup>

因此,您可以保证正确的代码命中正确的服务器

首先通过右键单击项目并转到“属性”和“SQLCMD变量”选项卡来设置SQLCMD变量:

然后设置一个文件夹结构,用于组织要为特定服务器运行的脚本或任何其他要关闭的对象(如客户)运行的脚本。每个服务器都有一个文件夹。我喜欢将要为该文件夹运行的所有脚本装入该文件夹中的索引文件中。索引列出了一个:r命令,后跟文件夹中应该运行的每个纸条,按文件名和数字前缀组织,以便可以控制顺序

在对所有服务器文件夹进行分组的文件夹中的索引文件中,它将执行不同于列出对每个服务器索引文件的调用的操作,而是根据发布配置文件传入的SQLCMD变量切换要运行的索引文件。它通过以下简单代码来实现:

:r .\$(Customer)\Index.sql
您希望通过设置文件夹和索引文件这样做的原因是,它不仅可以使事情保持有序,还允许您在所有文件中使用Go语句。然后,您可以将一个脚本与:r语句一起用于所有其他要运行的脚本,嵌套到您的核心内容中。 您可以按照以下方式设置sqlcmd文件,不需要设置文件夹或文件的特定名称,但需要删除所有GO语句。通过以上方法,您不必删除任何go语句

if @@servername = '$(ServerName)'
begin
    ... code for specific server
end
然后,当我右键单击项目并点击“发布”时,它将构建项目并弹出以下对话框。我可以通过更改SQLCMD变量来更改运行哪些脚本。

我喜欢将最常用的设置保存为一个单独的发布配置文件,然后在解决方案资源管理器中单击它的.xml文件,就可以返回到它。这个过程使一切变得非常简单,不需要手动修改xml,只需单击Saveprofile as、Loadprofile或使用上面显示的PublishDatabase对话框创建profile

此外,您还可以使用以下powershell脚本生成索引文件:

foreach($directory in (Get-ChildItem -Directory -Recurse) | Get-Item)
{
    #skip writing to any index file with ---Ignore in it.
    if(-Not ((Test-Path $directory\Index.sql) -and (Get-Content $directory\Index.sql | %{$match = $false}{ $match = $match -or $_ -match "---Ignore" }{$match})))
    {
        $output = "";
        foreach($childitem in (Get-ChildItem $directory -Exclude Index.sql, *.ps1 | Sort-Object | Get-Item))
        {
            $output= $output + ":r .\" + $childitem.name 
            if($childitem -is [system.io.directoryinfo])
            {
                $output = $output + "\Index.sql";
            }
            $output = $output + "`r`n"
        }
        Out-File $directory\Index.sql -Encoding utf8 -InputObject $output       
    }
}

对于任何想知道你也可以这样做的人:

发布配置文件:

<ItemGroup>
    <SqlCmdVariable Include="Environment">
        <Value>Dev</Value>
    </SqlCmdVariable>
</ItemGroup>

与“服务器名”语义相比,这种方式对我来说似乎更自然一些。我在尝试使用
@@servername
时也遇到问题,但不确定原因。

我会对第3条语句提出异议。这是真的,但部分是真的。PostDeployment是填充任何静态字典、插入初始数据、检查现有数据及其完整性(如-如果外键和检查约束受信任)、序列重置(在MSSQL>2012中)的最佳位置,测试数据生成。嘿,关于使用cmdvars的一步一步回答得很好:)-我确实指出了第2项的缺点,但它们很有用,因此您可以偶尔使用它们:)我喜欢这种方法,特别是对于:r.\$(Customer)\Index.sql部分。然而,我不能让它完全工作。我有一个名为$(ServerName)的变量,它有一个默认值,但在发布和添加其他值时,它仍然只引用默认路径的index.sql。我提出了一个问题:
<ItemGroup>
    <SqlCmdVariable Include="Environment">
        <Value>Dev</Value>
    </SqlCmdVariable>
</ItemGroup>
if '$(Environment)' = 'Dev'
begin
    ... code for specific server
end