Как захватить вывод DacSevices.Deploy?
Поэтому мне удалось развернуть нашу схему DACPAC через Octopus. Я использую скрипт Deploy.ps1, взаимодействующий с объектами.Net, как описано в статье.
Я хотел бы сделать процесс развертывания более прозрачным, включив "стандартный вывод", который вы получаете из sqlcmd, в наши журналы Octopus. Я ищу сгенерированные сообщения об изменении схемы, а также любые пользовательские сообщения о миграции, которые наши разработчики поместили в сценарии pre/post.
Единственный обходной путь, о котором я могу подумать, - это сначала сгенерировать сценарий с помощью служб DACPAC, а затем запустить его с помощью sqlcmd.exe. Есть идеи?
3 ответа
Нашел решение, разместив сообщение на случай, если кто-то еще столкнется с этим. Вам просто нужно подписаться на событие Message вашего DacService.
Образец 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, поэтому мне пришлось использовать неуклюжий командлет. Мех.
Используйте 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
Этот вариант фиксирует выходные данные, но также позволяет вам захватывать и реагировать на сбои развертывания, перехватывая исключение
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
}
}