如何捕获DacSevices.Deploy输出?

时间:2015-07-10 19:33:48

标签: sql-server dacpac

所以我设法部署了DACPAC schema via Octopus。我正在使用与.Net对象交互的Deploy.ps1脚本,就像文章描述的那样。

我希望通过在我们的Octopus日志中包含从sqlcmd获得的“标准输出”来使部署过程更加透明。我正在寻找生成的架构修改消息以及我们的开发人员在前/后脚本中添加的任何自定义迁移迁移消息。

我能想到的唯一解决方法是首先使用DACPAC服务生成脚本,然后使用sqlcmd.exe运行它。有什么想法吗?

3 个答案:

答案 0 :(得分:22)

找到解决方案,以防其他人遇到此问题。您只需订阅您的DacService Message event即可。

C#示例:

var services = new Microsoft.SqlServer.Dac.DacServices("data source=machinename;Database=ComicBookGuy;Trusted_connection=true");

var package = Microsoft.SqlServer.Dac.DacPackage.Load(@"C:\Database.dacpac");

var options = new Microsoft.SqlServer.Dac.DacDeployOptions();
options.DropObjectsNotInSource = true;
options.SqlCommandVariableValues.Add("LoginName", "SomeFakeLogin");
options.SqlCommandVariableValues.Add("LoginPassword", "foobar!");

services.Message += (object sender, Microsoft.SqlServer.Dac.DacMessageEventArgs eventArgs) => Console.WriteLine(eventArgs.Message.Message);

services.Deploy(package, "ComicBookGuy", true, options);

Powershell样本(由八达通触手执行):

# This script is run by Octopus on the tentacle
$localDirectory = (Get-Location).Path
$tagetServer = $OctopusParameters["SQL.TargetServer"]
$databaseName = "ComicBookGuy"

Add-Type -path "$localDirectory\lib\Microsoft.SqlServer.Dac.dll"

$dacServices = New-Object Microsoft.SqlServer.Dac.DacServices ("data source=" + $tagetServer + ";Database=" + $databaseName + "; Trusted_connection=true")
$dacpacFile = "$localDirectory\Content\Unity.Quotes.Database.dacpac"

$dacPackage = [Microsoft.SqlServer.Dac.DacPackage]::Load($dacpacFile)

$options = New-Object Microsoft.SqlServer.Dac.DacDeployOptions
$options.SqlCommandVariableValues.Add("LoginName", $OctopusParameters["SQL.LoginName"])
$options.SqlCommandVariableValues.Add("LoginPassword", $OctopusParameters["SQL.LoginPassword"])
$options.DropObjectsNotInSource = $true

Register-ObjectEvent -InputObject $dacServices -EventName "Message" -Action { Write-Host $EventArgs.Message.Message } | out-null

$dacServices.Deploy($dacPackage, $databaseName, $true, $options)

在powershell版本中,我无法获得方便的“Add_EventName”样式的事件通知,因此我不得不使用笨重的cmdlet。 MEH。

答案 1 :(得分:2)

使用sqlpackage而不是sqlcmd来部署dacpac。

在此处获取最新版本:https://msdn.microsoft.com/en-us/mt186501

$sqlpackage = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\sqlpackage.exe"

它会自动在控制台上输出错误。我们使用TFS构建定义并调用powershell,它能够显示部署期间发生的错误。

用法:

& $sqlpackage /Action:Publish /tsn:$dbServer /tdn:$database /sf:$mydacpac/pr:$dbProfile /variables:myVariable=1

答案 2 :(得分:0)

此变体不仅捕获输出,而且还允许您通过捕获异常来捕获并响应部署失败

function Load-DacPacAssembly()
{
    $assemblyName = "Microsoft.SqlServer.Dac.dll"
    $packageFolder = <some custom code to find our package folder>
    $dacPacAssembly = "$packageFolder\lib\net46\$assemblyName"

    Write-Host "Loading assembly $assemblyName"
    Add-Type -Path "$dacPacAssembly" 
}

function Publish-Dacpac($dacpac, $publishProfile){

    Load-DacPacAssembly

    Write-Host "Loading profile $publishProfile..."
    $dacProfile = [Microsoft.SqlServer.Dac.DacProfile]::Load($publishProfile)
    $dacService = New-Object Microsoft.SqlServer.dac.dacservices ($dacProfile.TargetConnectionString)

    Write-Host "Loading dacpac $dacpac"
    $dacPackage = [Microsoft.SqlServer.Dac.DacPackage]::Load($dacpac)

    $event = Register-ObjectEvent -InputObject $dacService -EventName "Message" -Action { 
        $message = $EventArgs.Message
        $colour = "DarkGray"
        if ($message -contains "Error SQL")
        {
            $colour = "Red"
        }

        Write-Host $message -ForegroundColor $colour
    }

    Write-Host "Publishing...."

    try {
        $dacService.deploy($dacPackage, $dacProfile.TargetDatabaseName, $true, $dacProfile.DeployOptions)
    }
    catch [Microsoft.SqlServer.Dac.DacServicesException]
    {        
        $message = $_.Exception.Message
        Write-Host "SQL Publish failed - $message" -ForegroundColor Red # Customise here for your build system to detect the error
        exit;
    }
    finally
    {
        Unregister-Event -SourceIdentifier $event.Name
    }
}