Провайдер Firebird dot net не полностью выполняет запрос?

Я запускаю несколько команд SQL, используя провайдера dot net для Firebird в С#. В частности, я меняю схему базы данных, делаю обновления данных и тому подобное.

В рамках обработки я создаю новую таблицу, запускаю запрос на копирование данных из старой таблицы, а затем удаляю старую таблицу.

Когда я делаю это, firebird генерирует ошибку:

используется неудачный объект обновления метаданных

Я кое-что посмотрел, и кажется, что запрос на копирование данных еще не "очищен" или что-то в этом роде. Я имею в виду, что когда я проверяю таблицы мониторинга в Firebird с приостановленным выполнением С#, я вижу запрос в таблице MON$STATEMENTS как неактивный. Это после того, как я запустил оператор фиксации.

Мои вопросы:

Есть ли способ приостановить, подождать или заставить запрос полностью завершиться, прежде чем я попытаюсь запустить следующую команду?

Когда я запускаю ту же последовательность запросов в ISQL, она работает отлично. Есть ли что-то другое, что ISQL делает, что я могу заставить поставщика dot net Firebird сделать, чтобы он не держал этот запрос открытым или что-то в этом роде?

Итак, для справки код выглядит примерно так (очевидно, это очень упрощенно):

    // create the table
    string commandString  = "CREATE TABLE ...";

    // run the command in a transaction and commit it
    mtransaction = Connection.BeginTransaction( IsolationLevel.Serializable );
    FbCommand command = new FbCommand(commandString, Connection, mtransaction);
    command.ExecuteNonQuery();
    transaction.Commit();
    transaction.Dispose();
    transaction = null;

    // copy the data to the new table from the old
    commandString = "INSERT INTO ...";

    mtransaction = Connection.BeginTransaction(IsolationLevel.Serializable);
    FbCommand command = new FbCommand(commandString, Connection, mtransaction);
    command.ExecuteNonQuery();
    transaction.Commit();
    transaction.Dispose();
    transaction = null;

    // drop the old table
    commandString = "DROP TABLE ...";

    mtransaction = Connection.BeginTransaction(IsolationLevel.Serializable);
    FbCommand command = new FbCommand(commandString, Connection, mtransaction);
    command.ExecuteNonQuery();

    // this command fails with the exception
    // if I pause execution in c# before running this command, and 
    // use isql to look at the db I see the new table, and the data fully populated
    // and I also see the inactive insert command in MON$STATEMENTS
    transaction.Commit();
    transaction.Dispose();
    transaction = null;

person Beau    schedule 25.08.2011    source источник
comment
Для справки, я использую сборку Windows Firebird 2.1.0, и я использую, я думаю, DDEXProvider-2.0.1 для стороны С#.   -  person Beau    schedule 26.08.2011


Ответы (3)


Я столкнулся с той же проблемой и проверил (грубое) исправление Бо. Тем не менее, я нашел простое решение: удалить команду после фиксации транзакции! Тогда повторное подключение больше не требуется.

mtransaction = Connection.BeginTransaction(IsolationLevel.Serializable);
FbCommand command = new FbCommand(commandString, Connection, mtransaction);
command.ExecuteNonQuery();
transaction.Commit();
command.Dispose(); // Thus!
transaction.Dispose();

С уважением, Атон.

person John Silence    schedule 02.05.2013
comment
Хорошая находка! Такого не пробовал! - person Beau; 04.05.2013

Хорошо, Ужасное решение проблемы:

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

// create the table
string commandString  = "CREATE TABLE ...";

// run the command in a transaction and commit it
mtransaction = Connection.BeginTransaction( IsolationLevel.Serializable );
FbCommand command = new FbCommand(commandString, Connection, mtransaction);
command.ExecuteNonQuery();
transaction.Commit();
transaction.Dispose();
transaction = null;

// copy the data to the new table from the old
commandString = "INSERT INTO ...";

mtransaction = Connection.BeginTransaction(IsolationLevel.Serializable);
FbCommand command = new FbCommand(commandString, Connection, mtransaction);
command.ExecuteNonQuery();
transaction.Commit();
transaction.Dispose();
transaction = null;


// ------------------  
// Drop the connection entirely and start a new one
// so the table can be dropped 

Connection.Close();
Connection.Dispose();

// build connection string 
FbConnectionStringBuilder csb = new FbConnectionStringBuilder();
csb.DataSource ... etc...

// connect
Connection = new FbConnection(connectionString);
Connection.Open();

// Now have new connection that does not have weird
// lingering query, and table can now be dropped
// -----------------



// drop the old table
commandString = "DROP TABLE ...";

mtransaction = Connection.BeginTransaction(IsolationLevel.Serializable);
FbCommand command = new FbCommand(commandString, Connection, mtransaction);
command.ExecuteNonQuery();

// this no longer fails because the connection was complete closed
// and re-opened
transaction.Commit();
transaction.Dispose();
transaction = null;

ПРИМЕЧАНИЕ. Я очень не доволен этим решением. Это работает, но я не знаю, почему. Мне кажется чрезмерным и ненужным делать это, чтобы бросить стол. Я бы очень приветствовал любое понимание, которое кто-либо может предложить в этом вопросе!!!

person Beau    schedule 26.08.2011

Кажется, я сталкивался с подобным. Я предполагаю, что основной причиной является функция: MVCC. Когда я путаюсь со схемами или удаляю таблицы только затем, чтобы воссоздать их, Visual Studio обычно держит их открытыми. Я просто перезапускаю службу, и все в порядке.

person joe    schedule 04.02.2013