Как запускать различные сценарии публикации до и после публикации SSDT в зависимости от профиля развертывания
Я использую SSDT в Visual Studio 2013.
Я создал несколько сценариев до и после публикации для сервера разработки. Сценарии перед развертыванием очищают данные из таблиц и заново устанавливают все поля автоматической идентификации. Сценарии после развертывания заполняют таблицы статическими данными и образцами данных.
Теперь мне нужно опубликовать базу данных на наших промежуточных и живых серверах баз данных. Я создал новые профили "publish.xml" для этих серверов. Но, очевидно, я не хочу запускать одинаковые сценарии pre и post.
Как я могу указать разные скрипты в зависимости от профиля публикации или сделать так, чтобы скрипты знали о цели и выполняли разные действия.
Моя самая большая проблема - публикация на реальном сервере и случайное уничтожение данных.
Заранее спасибо.
Doug
4 ответа
У вас есть несколько вариантов:
1 - Оберните изменения ваших данных в вызовах @servername или чего-то уникального для среды, чтобы у вас было что-то вроде:
if @@servername = 'dev_server'
begin
delete blah
insert blah
end
2 - Вы также можете добиться чего-то подобного, используя переменные sqlcmd, передав переменную с именем "/v:DestoryData=true" или что-то еще, и затем вы можете ссылаться на это в своем скрипте.
3 - Не используйте сценарии до / после развертывания, но используйте свой собственный механизм для их запуска, т. Е. Используйте командный файл для развертывания ваших dacpac и добавления вызова к sqlcmd до и после - недостатком этого является то, что при развертывании изменяется на таблица приводит к тому, что любые внешние ключи отключаются перед предварительным развертыванием и повторно включаются после последующего развертывания.
4 - Отредактируйте dacpac, сценарии предварительного / последующего развертывания - это просто текстовые файлы внутри dacpac, который по сути является zip-файлом, который соответствует формату упаковки Microsoft, и есть.net-пакет упаковки api, позволяющий вам его изменить.
Я думаю, что по этому поводу, пожалуйста, спросите, если что-то неясно:)
издание
Я бы предложил использовать переменные SQLCMD для выполнения вашего условного скрипта.
Если щелкнуть правой кнопкой мыши проект БД и выбрать "Свойства", появится вкладка "Переменные SQLCMD"
Введите "$(ServerName)" в качестве переменной и что-то в качестве значения по умолчанию.
Затем вам нужно открыть ваш КАЖДЫЙ.publish.xml в редакторе XML, чтобы вставить следующий код после части PropertyGroup:
<ItemGroup>
<SqlCmdVariable Include="ServerName">
<Value>[YourVersionOfServer]</Value>
</SqlCmdVariable>
</ItemGroup>
[YourVersionOfServer] должен быть равен результату @@servername на каждом из ваших серверов.
Конечный файл.publish.xml может выглядеть так:
Затем вы должны обернуть ваш условный код в файлы до и после развертывания:
if @@servername = '$(ServerName)'
begin
... code for specific server
end
Таким образом, вы можете гарантировать, что правильный код попадет на нужный сервер
Сначала настройте переменные SQLCMD, щелкнув правой кнопкой мыши по проекту и перейдя в свойства и на вкладку "Переменные SQLCMD":
Затем настройте структуру папок, чтобы вы могли организовать сценарии, которые вы хотите запустить для определенного сервера или любой другой вещи, которую вы хотите отключить, например, клиента. Каждый сервер получает папку. Мне нравится объединять все сценарии, которые я хочу запустить для этой папки, в индексный файл в этой папке. В индексе указана команда: r, за которой следуют все сценарии в папке, которая должна быть запущена, с упорядочением по имени файла с числовым префиксом, чтобы можно было контролировать порядок.
В файле индекса в папке, которая группирует все папки сервера, будет сделано нечто иное, чем вывод списка вызовов для файла индекса каждого сервера, вместо этого он переключает, какой файл индекса запускать, основываясь на переданной переменной SQLCMD на основе профиля публикации. Это делается с помощью следующего простого кода:
:r .\$(Customer)\Index.sql
Причина, по которой вы хотите сделать это, настраивая папки и индексные файлы, заключается в том, что он не только обеспечивает упорядоченность, но и позволяет использовать операторы Go во всех ваших файлах. Затем вы можете использовать один сценарий с: r операторами для всех других сценариев, которые вы хотите запустить, вложив в свое удовольствие. Вы можете настроить свой файл sqlcmd следующим образом, не требуя установки папок или определенных имен для файлов, но требуя удаления всех операторов GO. Делая это вышеописанным способом, вам не нужно удалять любые операторы go.
if @@servername = '$(ServerName)'
begin
... code for specific server
end
Затем, когда я щелкаю правой кнопкой мыши по проекту и нажимаю "Опубликовать", он строит проект и открывает следующее диалоговое окно. Я могу изменить, какие сценарии запускаются, изменив переменную SQLCMD.
Мне нравится сохранять наиболее часто используемые настройки в виде отдельного профиля публикации, а затем я могу вернуться к нему, просто щелкнув по его XML-файлу в обозревателе решений. Этот процесс делает все так просто, и нет необходимости изменять xml вручную, просто нажмите "Сохранить профиль как", "Загрузить профиль" или "Создать профиль" с помощью диалогового окна публикации базы данных, показанного выше.
Также вы можете сгенерировать ваши индексные файлы с помощью следующего скрипта powershell:
foreach($directory in (Get-ChildItem -Directory -Recurse) | Get-Item)
{
#skip writing to any index file with ---Ignore in it.
if(-Not ((Test-Path $directory\Index.sql) -and (Get-Content $directory\Index.sql | %{$match = $false}{ $match = $match -or $_ -match "---Ignore" }{$match})))
{
$output = "";
foreach($childitem in (Get-ChildItem $directory -Exclude Index.sql, *.ps1 | Sort-Object | Get-Item))
{
$output= $output + ":r .\" + $childitem.name
if($childitem -is [system.io.directoryinfo])
{
$output = $output + "\Index.sql";
}
$output = $output + "`r`n"
}
Out-File $directory\Index.sql -Encoding utf8 -InputObject $output
}
}
Для тех, кому интересно, вы также можете сделать что-то вроде этого:
Опубликовать профиль:
<ItemGroup>
<SqlCmdVariable Include="Environment">
<Value>Dev</Value>
</SqlCmdVariable>
</ItemGroup>
Сценарий после развертывания:
if '$(Environment)' = 'Dev'
begin
... code for specific server
end
Мне этот способ казался более естественным по сравнению с семантикой «ServerName». У меня также были проблемы с использованием
@@servername
, но не знаю почему.