【问题标题】:How to disable predeployment and postdeployment scripts in DacServices.Deploy()如何在 DacServices.Deploy() 中禁用部署前和部署后脚本
【发布时间】:2017-08-18 17:39:24
【问题描述】:

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

现在在 CreateNewDatabase 案例中,我们希望能够在禁用部署前和部署后脚本的情况下运行 DacServices.Deploy()。 IE。在这种情况下不应执行它们。

我试图在 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

【问题讨论】:

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


    【解决方案1】:

    您可以采取多种方法来解决这个问题,这有点脑残(嘿,昨晚时钟倒退了,我什至不确定当前时间是否):

    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) 让您的脚本检查它们是否应该设置数据,例如仅在表行数为零时才插入

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

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

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

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

    希望对你有帮助:)

    埃德

    【讨论】:

      【解决方案2】:

      尝试两件事:

      1. 首先,如果您使用MSBuild,则执行此类操作非常容易,因为您可以定制特定配置以包含项目的一个或多个部分。在您的 .sqlproj 文件中有一个 <ItemGroup> 部分,应该类似于以下内容:

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

        您可以简单地添加一个“条件”来确定是否使用该 ItemGroup。您可以在整个 .sqlproj 文件中看到这些“条件”属性(通常)。所以结果应该类似于:

        <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
          <PreDeploy Include="Script.PreDeployment1.sql" />
          <PostDeploy Include="Script.PostDeployment1.sql" />
        </ItemGroup>
        

        然后,您只需在“活动配置”下拉菜单中的“发布”或“调试”之间切换,部署前和部署后脚本将相应地包含或排除。

      2. 另一个想法是以某种方式重置部署前和部署后脚本。由于您将 DacPac 加载到 dacPackage,您将可以访问 PreDeploymentScriptPostDeploymentScript 属性。我无法测试,但可以“擦除”那里的内容(假设流已经指向存储的脚本)。

      【讨论】:

      • 看着清除流,但他们只是得到
      • @Lyon 是的,该属性是仅获取的,但这只是获取对流本身的引用。该文档指出该流可用于读取和写入。所以你应该可以使用 StreamWriter 。类似:stream _PreScript = _MyDacPackage.PreDeploymentScript;,然后使用_PreScript 将基本流设置为长度为 0,或清除它,或类似的东西。这有意义吗?
      • dacPackage.PreDeploymentScript.SetLength(0); 执行没有错误,但之后的流长度仍然是相同的正数,实际脚本内容仍然是GenerateDeployScript 输出的一部分。
      • @CeeMcSharpface 所以 PreDeployment 脚本仍然包括在内?我想知道首先调用Flush() 是否会有所帮助。如果没有,我想知道您是否可以简单地 Close() 它并且在尝试从关闭的流中读取时不会出错?
      • 是的,它仍然包含在内。我仔细测试过;还有一系列关于如何清除MemoryStream(setlength,flush before,...)的stackoverflow帖子,但无济于事。 GetBuffer 扩展技巧也不起作用。最终我按照自己的回答解决了。
      【解决方案3】:

      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 之后被简单地覆盖,因此请考虑先将其复制掉,以防您希望原件不变。

      (这部分被第 5 项中链接的 Internet 资源所涵盖)在accepted answer 中;但是上面显示的代码就是你所需要的)

      【讨论】:

      • 不错。遗憾的是必须修改 DACPAC 以暂时排除部署前和/或部署后脚本。其他很多东西都是可配置的,以至于禁用这些几乎是奇怪的。感谢分享!
      猜你喜欢
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 2017-07-16
      • 1970-01-01
      • 1970-01-01
      • 2020-12-21
      • 1970-01-01
      相关资源
      最近更新 更多