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

How to disable predeployment and postdeployment scripts in DacServices.Deploy()

我们有一些自动化的 dacpac 部署代码,可以使用 Microsoft.SqlServer.Dac

在 C# 中正确处理 CreateNewDatabase 和直接的更新数据库场景

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

我试图在 DacDeployOptionsDacServices 对象中找到合适的位置,但找不到任何合适的地方 this.Ideally

问题 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

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

1) 创建一个空项目,该项目使用相同的数据库引用来引用您的主项目 - 当您在没有脚本的情况下进行部署时,使用 IncludeCompositeObjects 部署空项目 - pre/post 部署脚本仅来自 运行您部署的 dacpac 不是来自任何引用的 dacpac,但显然已部署代码和方案。是这样描述的:

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

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

3) 让您的脚本检查它们是否应该设置数据,例如仅在 table 行计数为零时才插入

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

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

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

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

希望对您有所帮助:)

埃德

尝试两件事:

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

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

    您只需添加一个 "Condition" 即可确定是否使用该 ItemGroup。您可以在整个 .sqlproj 文件中看到这些 "Condition" 属性(通常)。所以结果应该类似于:

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

    然后您只需在 "Active Configuration" 下拉列表中的 "Release" 或 "Debug" 之间切换,然后将相应地包含或排除预部署和 post 部署脚本。

  2. 另一个想法是以某种方式重置预部署和 post 部署脚本。由于您将 DacPac 加载到 dacPackage,您将可以访问 PreDeploymentScript and PostDeploymentScript 属性。我无法测试,但可能 "erase" 那里有什么(假设流已经指向存储的脚本)。

DACPAC 是 ZIP 文件。使用 System.IO.Packaging 命名空间的功能从现有包中删除 pre- 和 post-deployment 脚本。

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 项中链接的互联网资源中)在 中;但是上面显示的代码就是您所需要的)