ServerConnection.ExecuteNonQuery в режиме SQLCMD

Я использую приложение уровня данных Microsoft для создайте сценарий развертывания на основе DacPackage объект. Я пытаюсь использовать Microsoft.SqlServer .Management.Smo.Server для выполнения этого скрипта...

SqlConnection deployConnection = new SqlConnection(connBuilder.ToString());
deployConnection.Open();
Server server = new Server(new ServerConnection(deployConnection));
server.ConnectionContext.ExecuteNonQuery(deployScript);

Тем не менее, эта ошибка с...

Unhandled Exception: Microsoft.SqlServer.Management.Common.ExecutionFailureException:
  An exception occurred while executing a Transact-SQL statement or batch. --->
  System.Data.SqlClient.SqlException: Incorrect syntax near ':'.

Я знаю, что решение этой проблемы заключается в том, что мне нужно находиться в режиме SQLCMD, но я не знаю, как сообщить моему ServerConnection для выполнения в указанном режиме.

Я предполагаю, что моя проблема не так специфична, как то, что я указываю в заголовке. Что мне действительно нужно сделать, так это выполнить скрипт, сгенерированный из DacPackage через .Net framework. Кто-нибудь может мне с этим помочь?


person Dan Forbes    schedule 28.10.2014    source источник


Ответы (1)


Команды режима SQLCMD не являются командами T-SQL; они работают только в SQL Server Management Studio (SSMS)/Visual Studio (VS) и SQLCMD.EXE. Режим SQLCMD по своей сути является тем, как работает SQLCMD.EXE, и его можно включить вручную в SSMS/VS; это часть этих приложений, а не то, что можно сделать через провайдера.

Эти приложения интерпретируют команды режима SQLCMD и не передают их SQL Server. Команды режима SQLCMD сначала анализируются/выполняются (именно так они могут повлиять на SQL, который должен быть отправлен), а затем окончательная версия SQL отправляется на SQL Server.

Следовательно, сценарии развертывания SQL, созданные SQL Server Data Tools (SSDT)/Visual Studio, необходимо запускать с помощью одной из этих трех программ.

Поскольку у вас уже есть файл .dacpac, Microsoft предлагает несколько способов опубликовать те, которые вам следует проверить:

Вы также можете создать сценарий публикации SQL через DacServices. GenerateDeployScript(), но это не изменит ситуацию, как указано выше, поскольку SQL-скрипт публикации/развертывания, независимо от того, сгенерирован ли он из Visual Studio "Publish {project_name}" или GenerateDeployScript(), является одним и тем же скриптом. Это означает, что он будет иметь команды двоеточия режима SQLCMD, такие как :setvar и :on error exit, а также переменные режима SQLCMD, которые, по крайней мере, будут $(DatabaseName), которые используются в следующей строке:

USE [$(DatabaseName)];

Хотя можно закомментировать начальные :setvar строк, установив DacDeployOptions свойство CommentOutSetVarDeclarations на true, что по-прежнему оставит строку :on error exit, а также строку для :setvar __IsSqlCmdEnabled "True", которая используется для определения того, включен ли режим SQLCMD. Чуть выше этой конкретной строки :setvar находится комментарий, в котором говорится:

/*
Detect SQLCMD mode and disable script execution if SQLCMD mode is not supported.
To re-enable the script after enabling SQLCMD mode, execute the following:
SET NOEXEC OFF; 
*/

Таким образом, они действительно предполагают, что этот сценарий запускается только через SQLCMD, будь то через DOS -> SQLCMD.EXE или PowerShell -> Invoke-SqlCMD.

Технически можно сгенерировать строку содержимого сценария развертывания (а не stream) и манипулировать этой строкой, а) удалив любые команды с двоеточием и б) заменив «$ (DatabaseName)» на любую базу данных, которую вы собираетесь использовать. развертывание в. Однако я не пробовал это, я не рекомендую это, и я не уверен, что это будет работать во всех ситуациях, когда сценарии развертывания могут быть сгенерированы SQL Server Data Tools. Но это похоже на возможный вариант.

Кроме того, незначительное отношение: вам не нужен SMO для запуска сценариев SQL. SMO — это средство взаимодействия с SQL Server через объекты, а не напрямую через команды T-SQL.

EDIT:
Ссылки, где другие пробовали это и нашли, что это не работает:

Возможности программной работы сгенерированного SQL-скрипта публикации:

person Solomon Rutzky    schedule 28.10.2014
comment
Таким образом, нет способа программно выполнить сгенерированные сценарии SQLCMD из среды .Net - это то, о чем вы говорите? - person Dan Forbes; 28.10.2014
comment
@DanForbes - в значительной степени да. Ничто за пределами этих трех программ не имеет ни малейшего представления о том, что это за команды с двоеточием. НО это не означает, что вы не можете запустить процесс на C#, чтобы вызвать командную строку для сервера SQLCMD.EXE -S и указать имя сценария и соответствующий флаг для передачи сценария SQL. - person Solomon Rutzky; 28.10.2014
comment
Большое спасибо, @srutzky! - person Dan Forbes; 28.10.2014
comment
@DanForbes: я знаю, что вы уже приняли это (спасибо), но я нашел дополнительную информацию, которую сейчас добавляю в свой ответ. - person Solomon Rutzky; 29.10.2014
comment
Превосходно! Я изучу эти предложения. Еще раз большое спасибо, @srutzky! - person Dan Forbes; 29.10.2014
comment
Итак, я просматривал документы MSDN для класса DacServices и заметил, что метод GenerateDeployScript указывает следующее возвращаемое значение: Строка сценария Transact-SQL, используемого для создания или обновления базы данных. схема на основе предоставленного DacPackage. Но это, кажется, прямо противоречит поведению, которое я вижу, и тому, что вы говорите выше. Это просто опечатка от имени Microsoft? - person Dan Forbes; 29.10.2014
comment
@DanForbes Спасибо, что указали на класс DacServices, я его раньше не видел, но очень круто. Проблема здесь в том, что вы путаете две вещи как взаимозаменяемые: сценарии публикации SQL и файлы DacPac. Вы опубликуете одно или другое. Метод GenerateDeployScript берет файл .dacpac и создает из него сценарий публикации SQL. Но это не публикация, и у вас уже есть сценарий SQL. Итак, выберите тип файла, который вы хотите развернуть (.sql или .dacpac). Если .sql, используйте SQLCMD.EXE или PowerShell, как указано. В противном случае используйте DacServices.Deploy. Я добавлю это к ответу. - person Solomon Rutzky; 29.10.2014
comment
Да, я понимаю это, но выше вы сказали, что команды режима SQLCMD не являются командами T-SQL, но тогда документация, похоже, указывает, что возвращаемая строка является сценарием T-SQL. Это мое недоразумение. Между прочим, то, что я пытаюсь сделать прямо сейчас, — это профилировать производительность развертывания DACPAC непосредственно через класс DacServices по сравнению с выполнением сценария развертывания, который может сгенерировать класс DacServices. - person Dan Forbes; 29.10.2014
comment
@DanForbes, вы говорите, что а) сгенерировали сценарий развертывания SQL через GenerateDeployScript() и б) что сценарии SQL действительно содержат команды :setvar и т. д. SQLCMD-режима? - person Solomon Rutzky; 29.10.2014
comment
Да, это именно то, что я говорю. - person Dan Forbes; 29.10.2014
comment
Я также вижу :on error exit. Я думаю, что это может быть (в дополнение к :setvars), но это довольно сложно сказать. - person Dan Forbes; 29.10.2014
comment
Давайте продолжим обсуждение в чате. - person Solomon Rutzky; 29.10.2014
comment
@DanForbes: я только что нашел кое-что интересное, библиотеку с открытым исходным кодом (довольно небольшую), которая обрабатывает SQL-скрипты, специфичные для SQLCMD. Я добавил новый пункт в последний раздел (средний/второй) с деталями. - person Solomon Rutzky; 02.11.2014