如何在DacServices.Deploy()中禁用预部署和部署后脚本

时间:2017-03-25 21:40:22

标签: c# sql-server deployment sql-server-data-tools dacpac

我们有一些自动化的dacpac部署代码,可以使用Microsoft.SqlServer.Dac正确处理C#中的CreateNewDatabase和简单的更新数据库方案

现在,在CreateNewDatabase案例中,我们希望能够在禁用Pre和Post Deployment脚本的情况下运行DacServices.Deploy()。即它们不应该在这种情况下执行。

我试图在DacDeployOptionsDacServices对象中找到合适的位置,但找不到任何可以执行此操作的内容。理想

问题1 我想要DacDeployOptions.IgnorePreDeploymentScript = true之类的东西我有什么方法可以在运行时实现这个目标吗?

作为替代方案,前段时间我记得看过示例代码,其中展示了如何遍历dacpac并在运行时创建新的dacpac。我认为这种方法可以让我简单地创建一个新的dacpac,我可以将其传递给Deploy,它将排除Pre和Post Deployment脚本。我不喜欢这个解决方案,但它可以让我实现我所需要的。

问题2 有人可以为我指出一些例子吗?

我的代码:

var dacService = new DacServices(ConstDefaultConnectionString);
using (var dacPackage = DacPackage.Load(dacPacFilePath))
{
    var deployOptions = new DacDeployOptions 
    { 
       CreateNewDatabase = true, 
       IncludeTransactionalScripts = false
    };
    dacService.Deploy(dacPackage, TestDatabaseName, true, deployOptions);
}

问题与:Create LocalDB for testing from Visual Studio SQL project

有关

3 个答案:

答案 0 :(得分:2)

你可以采取多种方法来解决这个问题,这是一个大脑转储(嘿,昨晚时钟倒流了,我甚至不确定当前时间):

1)创建一个空项目,使用相同的数据库引用引用您的主项目 - 当您在没有脚本的情况下部署使用IncludeCompositeObjects部署空项目时 - 前/后部署脚本仅从您部署的dacpac运行而不是从任何引用dacpacs但很明显代码和方案已经部署完毕。这描述了它:

https://the.agilesql.club/blog/Ed-Elliott/2016-03-03/Post-Deploy-Scripts-In-Composite-Dacpac-not-deploying

2)使用SQLCMD变量包装数据设置并将值传递给部署。

3)让你的脚本检查他们是否应该设置数据,如果表rowcount为零只插入

4)参考数据使用合并脚本 - 我不清楚这是针对参考数据还是设置测试数据

5)使用.net packaging api从dacpac中删除前/后部署脚本,这将向您展示如何编写脚本,以便您能够执行GetPart而不是WritePart:

https://github.com/GoEddie/Dir2Dac/blob/master/src/Dir2Dac/DacCreator.cs

总的来说,我猜可能有一个更简单的解决方案 - 如果这是用于测试,那么可能使数据设置成为测试设置的一部分?如果你是单元测试tSQLt可以帮助你通过使用FakeTable来避免这一切。

希望有所帮助:)

答案 1 :(得分:1)

要尝试两件事:

  1. 首先,如果您使用MSBuild,那么执行此类操作非常简单,因为您可以定制特定的配置以包含一个或多个项目。在您的 .sqlproj 文件中,void setM(int m){ if ((m+min)>59){ hour+=((min+m)/60); min=0; min=(min+m)%60; } else min+=m; } 部分应与以下内容类似:

    <ItemGroup>

    您只需添加“条件”即可确定是否使用该ItemGroup。您可以在 .sqlproj 文件中查看这些“条件”属性(通常)。所以结果看起来应该类似于:

    <ItemGroup>
      <PreDeploy Include="Script.PreDeployment1.sql" />
      <PostDeploy Include="Script.PostDeployment1.sql" />
    </ItemGroup>
    

    然后,您只需在“Active Configuration”下拉菜单中的“Release”或“Debug”之间切换,相应地包含或排除部署前后脚本。

  2. 另一个想法是以某种方式重置部署前后脚本。由于您将DacPac加载到<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PreDeploy Include="Script.PreDeployment1.sql" /> <PostDeploy Include="Script.PostDeployment1.sql" /> </ItemGroup> ,因此您可以访问PreDeploymentScriptPostDeploymentScript属性。我无法测试,但有可能“擦除”那里有什么(假设流已经指向存储的脚本)。

答案 2 :(得分:1)

DACPAC是ZIP文件。使用System.IO.Packaging命名空间的功能从现有程序包中删除部署前和部署后脚本。

using System.IO.Packaging;

// [...]

using (var dacPac = Package.Open(dacPacFile))
{
    var preDeploy = new Uri("/predeploy.sql", UriKind.Relative);
    if (dacPac.PartExists(preDeploy))
    {
        dacPac.DeletePart(preDeploy);
    }

    var postDeploy = new Uri("/postdeploy.sql", UriKind.Relative);
    if (dacPac.PartExists(postDeploy))
    {
        dacPac.DeletePart(postDeploy);
    }

    dacPac.Close();
}

Close之后该文件只是被覆盖,因此,如果您希望原始文件不变,请考虑先将其复制掉。

accepted answer中的

(第5项中链接的互联网资源部分覆盖了该内容);但是上面显示的代码就是您所需要的)