Как выполнить SQL с комментариями и инструкциями GO, используя SqlConnection? - PullRequest
11 голосов
/ 09 октября 2009

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

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

Вот ошибка:

Синтаксис запроса недействителен., Рядом термин «/», строка 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-скрипт прекрасно работает с SQL Management Studio Express (фактически, приложение сгенерировало этот скрипт!). Это просто собственное представление запросов в обозревателе серверов Visual Studio и из моего собственного кода, который, похоже, не работает.

Ответы [ 4 ]

11 голосов
/ 09 октября 2009

Вам необходимо использовать классы управления 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);
8 голосов
/ 09 октября 2009

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

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 на отдельные команды и выполняет каждую из них. Я регулярно использую это для настройки тестовых баз данных с созданными сценариями SQL.

1 голос
/ 09 октября 2009

Мне странно, что вы получаете EntitySqlException ...

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

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 ();
0 голосов
/ 15 октября 2015

в 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...