Как выполнить SQL с комментариями и операциями GO с помощью SqlConnection?

Я не могу выполнить SQL, создающий базу данных с использованием объекта DbCommand. Что я делаю не так? Здесь мой код:

DbConnection connection; // initialized and opened elsewhere
DbCommand cmd = connection.CreateCommand();
cmd.CommandText = sql;
cmd.ExecuteNonQuery();

Здесь ошибка:

Синтаксис запроса недействителен., рядом term '/', строка 1, столбец 2. Описание: Необработанное исключение произошли во время выполнения текущий веб-запрос. Пожалуйста, просмотрите трассировки стека для получения дополнительной информации о ошибка и где она возникла в код.

Сведения об исключении: System.Data.EntitySqlException: синтаксис запроса недействителен., ближайший '/', строка 1, столбец 2.

Здесь первая часть файла. Исключение выбрано только для комментариев в первой строке:

/****** Object:  Table [dbo].[User]    Script Date: 10/08/2009 12:14:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[User](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [FirstName] [nvarchar](50) NULL,
    [LastName] [nvarchar](50) NULL,
    [EmailAddress] [nvarchar](100) NULL,
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Тот же SQL script отлично справляется с SQL Management Studio Express (на самом деле это приложение создало этот script!). Это просто Visual Studio собственного просмотра запросов проводника сервера и из моего собственного кода, который, кажется, не работает.

Ответ 1

Вам нужно использовать классы управления SQL вместо обычного SqlCommand. На этой странице показано, как это сделать. Если вы попытаетесь разобрать SQL самостоятельно, тогда всегда будут случаи краев, которые вы пропустите. Например, что, если строка в коде содержит слово "GO" с возвратом ведущей и конечной каретки?

Добавьте эти ссылки:

  • Microsoft.SqlServer.Smo
  • Microsoft.SqlServer.ConnectionInfo
  • Microsoft.SqlServer.Management.Sdk.Sfc(Изменить: эта ссылка не требуется)

Затем вы можете использовать этот код:

string connectionString, scriptText;
SqlConnection sqlConnection = new SqlConnection(connectionString);
ServerConnection svrConnection = new ServerConnection(sqlConnection);
Server server = new Server(svrConnection);
server.ConnectionContext.ExecuteNonQuery(scriptText);

Ответ 2

Вот фрагмент кода, который я размещенный на моем блоге некоторое время назад, который может решить эту проблему:

private static void RunScript(SqlConnection connection, string script)
{
    Regex regex = new Regex(@"\r{0,1}\nGO\r{0,1}\n");
    string[] commands = regex.Split(script);

    for (int i = 0; i < commands.Length; i++)
    {
        if (commands[i] != string.Empty)
        {
            using(SqlCommand command = new SqlCommand(commands[i], connection))
            {
                command.ExecuteNonQuery();
                command.Dispose();
            }
        }
    }
}

Он разбивает SQL script на отдельные команды и выполняет каждый из них. Я регулярно использую это для настройки тестовых баз данных с помощью сгенерированных SQL-скриптов.

Ответ 3

Мне кажется странным, что вы получаете исключение EntitySqlException...

Другим решением, которое вы можете выбрать, является выполнение этого script с помощью инструмента командной строки osql. Вы можете создать экземпляр System.Diagnostics.Process и использовать этот процесс для вызова osql, который, в свою очередь, выполняет script.

System.Diagnostics.Process p = new System.Diagnostics.Process ();

p.StartInfo.FileName = Environment.GetEnvironmentVariable ("COMSPEC");
p.StartInfo.UseShellExecute = false;
p.StartInfo.ErrorDialog = false;

p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;

p.Start ();

p.StandardInput.WriteLine ("echo off");
string command = @"osql -U -b -e -S " + servername + " -d " + databasename + " -i \'" + filename + "\'";
p.StandardInput.WriteLine (command);
p.StandardInput.WriteLine ("exit");

p.WaitForExit ();

Ответ 4

в SQL Server вы можете объединить столько запросов, сколько хотите, с помощью простого разделителя пробелов, но для этого вам нужно удалить "GO". Пример:

BEGIN TRANSACTION   SET QUOTED_IDENTIFIER ON  SET ARITHABORT ON  SET NUMERIC_ROUNDABORT OFF   SET CONCAT_NULL_YIELDS_NULL ON   SET ANSI_NULLS ON   SET ANSI_PADDING ON   SET ANSI_WARNINGS ON   COMMIT   BEGIN TRANSACTION   $remove this GO here$   CREATE TABLE dbo.Tmp_Tralala(   ERRID numeric (18,0) NOT NULL) ) ON [PRIMARY]   $remove this GO here$   IF EXISTS(SELECT * FROM dbo.Tralala)   EXEC('INSERT INTO ..etc