Форум: "Базы";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];
ВнизTransaction Найти похожие ветки
← →
stelius © (2004-03-17 17:34) [0]Народ, помогите разобраться. В цикле открываю и закрываю транзакцию. При первой итерации все проходит нормально, а при второй вылетает ошибка:
General SQL error.
You tried to commit or roll back a transaction without first using Begin Trans.
← →
serge35 (2004-03-17 17:35) [1]Попробуй сделать Commit после каждой транзакции
← →
Reindeer Moss Eater © (2004-03-17 17:36) [2]serge35
Все верно, только все наоборот.
После каждго коммита или ролбэка надо снова начинать транзакцию
← →
stelius © (2004-03-17 17:39) [3]Я только одну открываю.
for i := 0 to Cnt - 1 do begin
Database1.StartTransaction;
...
Database1.Commit;
end; //for
← →
Reindeer Moss Eater © (2004-03-17 17:44) [4]А зачем такие транзакции?
Убери их вызовы и они будут сами инициироваться и завершаться строго по твоей задуманной, но нереализованной логике
← →
stelius © (2004-03-17 17:59) [5]2 Reindeer Moss Eater
В теле цикла в разные ТБД заносятся данные одной записи в БД. Если в какую-то таблицу данные не могут быть внесены, то надо отменить запись в предыдущие таблицы.for i := 0 to Cnt - 1 do begin
Database1.StartTransaction;
Query1.Open;
Query1.Edit;
for j := 0 to CntFld - 1 do begin
Query1.FieldValues[<имя_поля>] := <значение>;
try
Query1.Post;
Query1.ApplyUpdates;
except
Database1.Rollback;
Continue;
end; //try
...
Database1.Commit;
end; //for
← →
Val © (2004-03-17 19:03) [6]так судя по всему возникает экзепшн и выполняется ролбэк, и остается совсем одинокий коммит.
← →
Reindeer Moss Eater © (2004-03-17 20:24) [7]Query1.ApplyUpdates;
...
Database1.Rollback;
Не надо смешивать вместе ручное управление транзакциями и задействовать режим CachedUpdates
← →
Michail Dalakov © (2004-03-17 21:13) [8]To Reindeer Moss Eater © (17.03.04 20:24) [7]
Это почему же
procedure CachedCommit(const A:array of TDBDataSet);
var h,i:integer;
begin
h:=High(A);
DM.Database1.StartTransaction;
try
for i:=0 to h do A[i].ApplyUpdates;
DM.Database1.Commit;
except
on E: Exception do begin
for i:=0 to h do A[i].CancelUpdates;
DM.Database1.Rollback;
Raise;
end;
end;
for i:=0 to h do A[i].CommitUpdates;
end;
← →
Reindeer Moss Eater © (2004-03-17 22:45) [9]Ничего не имею против, тем более, что я сказал "не надо", а "не нельзя".
Объясняю почему.
При использовании CachedUpdates Борланд рекомендует вызывать ApplyUpdates не у индивидуального датасета, а у TDatabase.
Note: The preferred method for updating datasets is to call a database component’s ApplyUpdates method rather than to call each individual dataset’s ApplyUpdates method...
Теперь смотрим в метод TDatabase.ApplyUpdates и видим, что он сам начинает транзакцию, не проверяя InTransaction.
Таким образом, если мы используем CachedUpdates, сами управляем транзакциями и следем рекомендациям Борланда, то
на Database1.ApplyUpdates([Query1]) получаем исключение A user transaction is already in progress
Вот отсюда и появилось мое заключение о том, что ручное управление транзакциями при CachedUpdates - масло маслянное.
BDE само начнет транзакцию и завершит её
← →
stelius © (2004-03-18 08:51) [10]2 Reindeer Moss Eater
Хорошо, но тогда как реализовать следующее:
Необходимо заполнить 2 ТБД. Поля 2-й ТБД заполняются на основе значений полей 1-й ТБД. Сначала заполняем 1-ю ТДБ, делаем ApplyUpdates. Начинаем заполнять 2-ю ТБД и при попытке ApplyUpdates вылетает exception, делаем CancelUpdates для 2-й ТБД. Но ведь данные в первую таблицу занесены, как сделать rollback к состоянию до заполнения 1-й ТБД без использования явного запуска транзакции?
P.S. И еще не совсем понимаю почему первая итерация вышеописанного цикла проходит нормально (ТБД заполняются корректно), а последующие нет.
← →
Reindeer Moss Eater © (2004-03-18 10:09) [11]Я же сказал, что:
ApplyUpdates Борланд рекомендует вызывать не у датасета, а у TDatabase передавая ему массив датасетов.
При этом самому стартовать транзакции не нужно. Потому что:
1. TDatabase.ApplyUpdates сам стартует транзакцию и завершает ее
2. Ты начинаешь транзакцию раньше, чем это требуется. Ничего криминального конечно в этом нет, но у сервера раньше чем это реально становится нужно отбираются драгоценные ресурсы.
Твой цикл не содержит операции связанные с непосредственной модификацией данных на сервере. А транзакция уже стартована.
Хорошо еще что взаимодействия с юзером внутри его нет.
Хотя вполне логично её использовать например в OnUpdateError если дорожишь нервами пользователя.
Вот и выводы:
Не стартуй транзакции сам.
Используй CachedUpdates
Вызывай ApplyUpdates у Database1
И будет счастье.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.03 c