#delphi #firebird #delphi-xe #dbexpress
#delphi #firebird #delphi-xe #dbexpress
Вопрос:
У меня есть соединение dbExpress, подключенное к базе данных Firebird, под управлением Firebird Embedded. Пока все работает нормально, но происходит что-то очень странное.
У меня есть модуль данных, который содержит соединение и несколько TSimpleDataset
объектов, представляющих разные таблицы. Но когда я пытаюсь добавить новую таблицу, кажется, что она работает, но затем завершается неудачей:
procedure Update(module: TdmDatabase);
const
SQL = 'CREATE TABLE NEW_TABLE (blah blah blah)';
SQL2 = 'ALTER TABLE NEW_TABLE ADD CONSTRAINT PK_NEW_TABLE PRIMARY KEY (blah)';
SQL3 = 'DROP TABLE NEW_TABLE';
begin
module.connection.ExecuteDirect(SQL); //succeeds
module.connection.ExecuteDirect(SQL2); //succeeds
try
module.New_TableDataset.Active := true; //fails
except
module.connection.ExecuteDirect(SQL3); //succeeds
raise;
end;
end;
Когда я пытаюсь создать таблицу, кажется, что она работает, и я могу, ALTER
и DROP
это просто отлично, но когда я пытаюсь открыть dataset, который выполняет SELECT
против него, я получаю ошибку «недопустимое имя таблицы». Если я запускаю его в отладчике и завершаю программу сразу после выполнения CREATE TABLE
инструкции, затем проверяю базу данных, новой таблицы там нет.
Кто-нибудь знает, что могло вызвать это, и как я могу это исправить?
Комментарии:
1. Я не знаком с DBX, я использую IBX для Firebird, поэтому вот комментарий: убедитесь, что вы зафиксировали транзакцию, которую использовали для создания таблицы. Убедитесь, что ваш «New_TableDataset» активирован с помощью новой транзакции, он не активируется с помощью длительной транзакции, которая имеет другое представление системных таблиц.
2. Другие советы: я бы запускал большинство операций DDL в своей собственной транзакции, фиксируя после каждой из них. На самом деле в некоторых инструментах есть опция «автоматической фиксации операций DDL». И я бы определенно не смешивал DDL с обычными операциями.
3. Возможно, используйте компонент TSQLQuery вместо TSimpleDataset, который устарел.
4. @No’am: Устарело? В какой версии? Потому что этого, безусловно, нет в Delphi XE, и TSQLQuery не является подходящей заменой для него.
Ответ №1:
- Это похоже на проблему с чистой транзакцией, где
SQL
,SQL2
иSQL3
выполняются в одной (или во многих) транзакциях. И транзакция остается активной по крайней мере после этогоSQL
. ИNew_TableDataset
работает в другой транзакции, которая, конечно, не видит незафиксированных изменений первой транзакции. - Проблема не в DataSnap / dbExpress, а скорее в конкретной реализации драйвера. Итак, полезно знать, что это за драйвер. И необязательно обращаться в службу технической поддержки поставщика драйверов.
- Что делать (чистое предположение):
- Попробуйте включить выполнение команд в явный контроль транзакций. Это будет (может) гарантировать, что транзакция завершена после требуемого шага.
- Попробуйте выполнить
COMMIT
послеSQL
и / илиSQL2
. - Попробуйте использовать
TSQLQuery
вместоExecuteDirect
. Надеюсь, все команды будут выполняться в одной транзакции.
PS: Наконец, рассмотрите возможность использования другого драйвера dbExpress или даже библиотеки доступа к данным.
Комментарии:
1. Спасибо. Включение
CREATE TABLE
в свою собственную явную транзакцию сработало.
Ответ №2:
У меня была аналогичная проблема с ADO, решение было :
1/ Как уже говорилось: выполните ФИКСАЦИЮ после всего вашего DDL SQL.
2/ Когда первое создание пройдет нормально, выполните запрос SELECT ( COMMIT) для созданной таблицы
Комментарии:
1. Если это не проблема с драйвером, совет «2» просто бесполезен. И если драйвер настолько плох, его следует заменить. Что касается «1», то его следует дополнить, указав, что ФИКСАЦИЯ должна следовать за инструкциями DDL (язык определения данных) — в нынешнем виде похоже, что ФИКСАЦИЯ должна следовать за всеми инструкциями SQL, и это явно неверно, потому что это подрывает всю концепцию использования транзакций, чтобы несколько операций выполнялись успешно или не выполнялись как группа.
2. @CosminPrund Я знаю, что 2 / кажется бесполезным, но в моем случае это было эффективно, и иногда драйвер не может быть заменен так просто, и более того: его легко протестировать. Я согласен с вашим 1 / замечанием: я отредактирую свой пост.