Проблемы при выполнении SQL-скрипта с использованием Firebird.NET 2.5 (код ошибки = -104) - PullRequest
2 голосов
/ 20 июля 2010

Извините за мой английский в первую очередь. У меня проблема и мне нужна помощь. У меня есть простой инструмент, созданный мной на c #. Этот инструмент позволяет подключиться к локальному или удаленному серверу Firebird (v.2.5). И мой инструмент может создать указанный файл .fdb (базу данных) где-то на сервере.

Также у меня есть файл с инструкциями SQL (создание таблицы, триггеры и т. Д.). Я хочу выполнить этот файл после создания базы данных. Выполнение этого файла заполнит структуру пользовательской базы данных - не данные, а только структуру.

Но затем я пытаюсь выполнить свой SQL-скрипт - сервер Firebird возвращает

Код ошибки SQL = -104 Токен неизвестная строка xxx столбец xxx.

Это строка в этом CREATE TABLE операторе SQL, например:

CREATE TABLE tb1
(
    col1 INTEGER NOT NULL,
    col2 VARCHAR(36)
); 

/* This next create statement causes an error */

CREATE TABLE tb2
(
    col1 INTEGER NOT NULL,
    col2 VARCHAR(36)
); 

Если я оставлю только один оператор создания в моем файле - все будет хорошо ... Я не знаю, как я объяснил (понятно или нет)) - другими словами - почему я не могу выполнить полный запрос с ли создавать заявления в одной транзакции? Вот мой основной метод, который выполняет запрос:

public static string Do(string conString, string query)
{
            using (FbConnection conn = new FbConnection())
            {
                try
                {
                    conn.ConnectionString = conString;
                    conn.Open();
                    FbTransaction trans = conn.BeginTransaction();
                    FbCommand cmd = new FbCommand(query, conn, trans);
                    cmd.ExecuteNonQuery();
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    System.Windows.MessageBox.Show(ex.ToString());
                    return "Transaction Fail";
                }
            }
            return "Transaction Commited";
}

Есть запрос к моему файлу SQL.

Ответы [ 2 ]

4 голосов
/ 10 декабря 2012

Как Виктор уже заявил в своем последнем комментарии, вы можете использовать класс FBScript для пакетного выполнения.

Я только что столкнулся с той же задачей.Этот вопрос направил меня в правильном направлении, но мне пришлось заняться дальнейшими поисками.

В этом примере источником утверждений является внешний файл сценария:

private void ExecuteScript(FbConnection myConnection, string scriptPath) {
    if (!File.Exists(scriptPath))
        throw new FileNotFoundException("Script not found", scriptPath);

    FileInfo file = new FileInfo(scriptPath);
    string script = file.OpenText().ReadToEnd();

    // use FbScript to parse all statements
    FbScript fbs = new FbScript(script);
    fbs.Parse();

    // execute all statements
    FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
    fbe.Execute(true);
}

Это будет работатьхорошо, но вы можете удивиться, почему все это не окружено транзакцией.На самом деле нет поддержки для «привязки» FbBatchExecution к транзакции напрямую.

Первое, что я попробовал, было следующее ( не будет работать )

private void ExecuteScript(FbConnection myConnection, string scriptPath) {
    using (FbTransaction myTransaction = myConnection.BeginTransaction()) {
        if (!File.Exists(scriptPath))
            throw new FileNotFoundException("Script not found", scriptPath);

        FileInfo file = new FileInfo(scriptPath);
        string script = file.OpenText().ReadToEnd();

        // use FbScript to parse all statements
        FbScript fbs = new FbScript(script);
        fbs.Parse();

        // execute all statements
        FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
        fbe.Execute(true);

        myTransaction.Commit();
    }
}

В результате возникнет исключение: «Для выполнения требуется, чтобы объект Command имелОбъект транзакции, когда объект соединения, назначенный команде, находится в ожидающей локальной транзакции. Свойство транзакции команды не было инициализировано. "

Это означает лишь то, что команды, выполняемые FbBatchExecution, не являютсяприсваивается нашей локальной транзакции, которая окружает блок кода.Здесь помогает то, что FbBatchExecution предоставляет событие CommandExecuting, где мы можем перехватить каждую команду и назначить нашу локальную транзакцию следующим образом:

private void ExecuteScript(FbConnection myConnection, string scriptPath) {
    using (FbTransaction myTransaction = myConnection.BeginTransaction()) {
        if (!File.Exists(scriptPath))
            throw new FileNotFoundException("Script not found", scriptPath);

        FileInfo file = new FileInfo(scriptPath);
        string script = file.OpenText().ReadToEnd();

        // use FbScript to parse all statements
        FbScript fbs = new FbScript(script);
        fbs.Parse();

        // execute all statements
        FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);

        fbe.CommandExecuting += delegate(object sender, CommandExecutingEventArgs args) {
            args.SqlCommand.Transaction = myTransaction;
        };

        fbe.Execute(true);
        // myTransaction.Commit();
    }
}

Обратите внимание, что я раскомментировал строку myTransaction.Commit ().Я был немного удивлен таким поведением, но если вы сохраните эту строку, транзакция выдаст исключение, сообщающее, что она уже была зафиксирована.Параметр bool fbe.Execute (true) называется «autoCommit», но изменение этого значения на false, похоже, не имеет никакого эффекта.

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

1 голос
/ 20 июля 2010

Вероятно, ошибка при запуске двух операторов create в одном пакете. Будет ли это работать, если разбить его на отдельные запросы? Это работает в вашем инструменте SQL?

...