SQLCMD模式下的ServerConnection.ExecuteNonQuery

Dan*_*bes 11 c# sql-server sqlcmd data-tier-applications sql-server-data-tools

我正在使用Microsoft Data-Tier Application框架来创建基于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);
Run Code Online (Sandbox Code Playgroud)

然而,这错误...

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 ':'.
Run Code Online (Sandbox Code Playgroud)

我知道这个问题的答案是我需要处于SQLCMD模式,但我不知道如何告诉我的ServerConnection在所述模式下执行.

我想我的问题不像我在标题中说的那样具体.我真正需要做的是通过.Net框架执行从DacPackage生成的脚本.谁能帮我这个?

Sol*_*zky 13

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 Server数据工具(SSDT)/ Visual Studio生成的部署SQL脚本需要通过这三个程序之一运行.

由于您已经有一个.dacpac文件,Microsoft提供了一些方法来发布您应该检出的文件:

您还可以通过DacServices.GenerateDeployScript()创建发布SQL脚本,但这不会改变上述情况,因为发布/部署SQL脚本,无论是从Visual Studio"Publish {project_name}"生成还是GenerateDeployScript(),都是相同的脚本.这意味着,将具有SQLCMD模式冒号命令,如:setvar:on error exit以及在SQLCMD模式变量,这至少是将$(DatabaseName)其在下面的行中:

USE [$(DatabaseName)];
Run Code Online (Sandbox Code Playgroud)

虽然可以注释掉最初:setvar通过设置线DacDeployOptions财产CommentOutSetVarDeclarationstrue,这将仍然保留: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; 
*/
Run Code Online (Sandbox Code Playgroud)

所以他们确实打算只通过SQLCMD运行这个脚本,无论是通过DOS - > SQLCMD.EXE还是PowerShell - > Invoke-SqlCMD.

从技术上讲,可以生成一个部署脚本内容的字符串(而不是a stream)并通过a)删除任何冒号命令来操纵该字符串,以及b)将"$(DatabaseName)"替换为您要部署的任何数据库至.但是,我没有尝试过这个,我不推荐这个,我不确定它是否适用于SQL Server Data Tools可以生成哪些部署脚本的所有情况.但它似乎是一种选择.

此外,有点相关:您不需要SMO来运行SQL脚本.SMO是通过对象而不是直接通过T-SQL命令与SQL Server交互的手段.

编辑:
链接其他人尝试过这一点,发现它不起作用:

使生成的发布SQL脚本能够以程序化方式工作的可能性:

  • @DanForbes - 非常,是的.这三个程序之外的任何内容都没有任何关于结肠命令的线索.但是,这并不意味着您无法在C#中启动进程来调用"SQLCMD.EXE -S服务器"的命令行,并提供脚本名称和传入SQL脚本的相应标志. (3认同)