Вопрос

Я выполняю SQL-скрипты для изменения схемы базы данных.Выглядит это примерно так:

using (var command = connection.CreateCommand())
{
    command.CommandText = script;
    command.ExecuteNonQuery();
}

Кроме того, команды выполняются в рамках транзакции.

Сумма выглядит примерно так:

Alter Table [TableName]
ADD [NewColumn] bigint NULL

Update [TableName]
SET [NewColumn] = (SELECT somevalue FROM anothertable)

Я получаю сообщение об ошибке, потому что NewColumn не существует.Кажется, он анализирует и проверяет его перед выполнением.

Когда я выполняю весь процесс в Management Studio, я могу поместить GO между утверждениями, тогда это работает.Когда я кладу GO в скрипт, ADO.NET жалуется (неправильный синтаксис рядом с 'GO').

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


Моя реализация, если кого-то заинтересует, согласно ответу Джона Сондерса:

List<string> lines = new List<string>();
while (!textStreamReader.EndOfStream)
{
    string line = textStreamReader.ReadLine();
    if (line.Trim().ToLower() == "go" || textStreamReader.EndOfStream)
    {
        ExecuteCommand(
            string.Join(Environment.NewLine, lines.ToArray()));

        lines.Clear();
    }
    else
    {
        lines.Add(line);
    }
}
Это было полезно?

Решение

Вы должны запустить каждую партию отдельно. В частности, для запуска скрипта, который может содержать несколько партий («Go» ключевых слов), вы должны разделить скрипт на ключевые слова «GO».

Не испытано:

string script = File.ReadAllText("script.sql");
string[] batches = script.Split(new [] {"GO"+Environment.NewLine}, StringSplitOptions.None);
foreach (string batch in batches)
{
    // run ExecuteNonQuery on the batch
}

Другие советы

Не используете для этого одну из многочисленных библиотек ORM?Хорошо :-)

Чтобы быть в полной безопасности при запуске скриптов, которые вносят структурные изменения, используйте SMO, а не SqlClient, и убедитесь, что MARS не включен через строку подключения (SMO обычно жалуется, если это так или иначе).Ищите Подключение к серверу class и ExecuteNonQuery - разные библиотеки DLL, конечно :-)

Разница в том, что SMO dll передает скрипт как есть в SQL, так что это подлинный эквивалент запуска его в SSMS или через строку isql cmd.Нарезка на GO-s заканчивается гораздо большим сканированием каждый раз, когда вы сталкиваетесь с очередным сбоем (например, GO может быть в середине многострочного комментария, может быть несколько инструкций USE, скрипт может удалять саму базу данных, к которой подключен SqlClient - упс :-).Я только что уничтожил одну такую вещь в унаследованной мной кодовой базе (после того, как более сложные скрипты вступили в конфликт с MARS, а MARS хорош для производственного кода, но не для администрирования).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top