ADO.NET и ExecuteNonQuery: как использовать DDL - PullRequest
0 голосов
/ 23 июня 2010

Я выполняю сценарии 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);
    }
}

Ответы [ 2 ]

2 голосов
/ 15 августа 2010

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

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

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

1 голос
/ 23 июня 2010

Вы должны запускать каждую партию отдельно. В частности, для запуска сценария, который может содержать несколько пакетов (ключевые слова «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
}
...