SqlCommand () ExecuteNonQuery () усекает текст команды

Я создаю пользовательскую утилиту развертывания дб, я должен считать текстовые файлы, содержащие sql сценарии, и выполнить их против базы данных.

Довольно легкий материал, пока неплохо.

Однако я встретился с препятствием, содержание файла читается успешно и полностью, но когда-то передается в SqlCommand и затем выполняется с SqlCommand. ExecuteNonQuery только часть сценария выполняется.

Я разжег Профилировщика и подтвердил, что мой код не передает весь сценарий.

    private void ExecuteScript(string cmd, SqlConnection sqlConn, SqlTransaction trans)
    {

        SqlCommand sqlCmd = new SqlCommand(cmd, sqlConn, trans);
        sqlCmd.CommandType = CommandType.Text;
        sqlCmd.CommandTimeout = 9000000; // for testing
        sqlCmd.ExecuteNonQuery();

    }

    // I call it like this, readDMLScript contains 543 lines of T-SQL
    string readDMLScript = ReadFile(dmlFile);
    ExecuteScript(readDMLScript, sqlConn, trans);
16
задан skaffman 16 March 2010 в 20:06
поделиться

2 ответа

Ага, каждый сталкивается с этой проблемой, когда в первый раз начинает посылать содержимое файлов сценария SQL в базу данных.

GO не является командой T-SQL. Это маркер конца пакета, распознаваемый всеми интерактивными инструментами SQL Microsoft (Management Studio, isql, osql). Чтобы справиться с этим, вам нужно будет написать свой собственный синтаксический анализатор, чтобы разбивать каждый блок текста в файле между операторами GO и передавать их в базу данных как отдельные команды.

Как вы реализуете свой синтаксический анализатор, зависит от вас. Это может быть простое (чтение каждой строки за раз, обнаружение строк, состоящих только из GO и пробелов) или сложное (разметка всех операторов и определение того, является ли GO подлинное утверждение или фрагмент текста внутри строки или многострочного комментария).

Лично я выбрал первый вариант. Он без проблем обрабатывает 99% всех файлов SQL, с которыми вы, вероятно, когда-либо столкнетесь.Если вы хотите полностью посвятить себя написанию токенизатора, я уверен, что многие люди уже сделали его, просто Google для этого.

Пример:

using(var reader = new SqlBatchReader(new StreamReader(dmlFile))) {
    string batch;
    while((batch = reader.ReadBatch()) != null) {
        var cmd = new SqlCommand(batch, conn, trans) { CommandType = CommandType.Text };
        cmd.ExecuteNonQuery();
    }
}

class SqlBatchReader : IDisposable {
    private TextReader _reader;
    public SqlBatchReader(TextReader reader) {
        _reader = reader;
    }
    /// <summary>
    /// Return the next command batch in the file, or null if end-of-file reached.
    /// </summary>
    public string ReadBatch() {
        // TODO: Implement your parsing logic here.
    }
}
35
ответ дан 30 November 2019 в 16:09
поделиться

Ответ основан на комментариях под исходным сообщением:

GO - это маркер для Management Studio / osql / isql. Он сообщает, что нужно отправить пакет команд на SQL Server. В вашей утилите вы должны разделить входные данные, используя GO в качестве разделителя, и отправить каждый элемент отдельно (без команды GO)

1
ответ дан 30 November 2019 в 16:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: