Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.04.18;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.026 c
3-1079764755
Kotyara
2004-03-20 09:39
2004.04.18
Динамическое создание TADOQuery


14-1080125132
Фикус
2004-03-24 13:45
2004.04.18
Какой выбрать движок для портала?


14-1080111601
Goida
2004-03-24 10:00
2004.04.18
Черный Тюльпан...


3-1079894810
Игорь
2004-03-21 21:46
2004.04.18
Запрос по таблице в памяти


3-1079728481
Igoryok
2004-03-19 23:34
2004.04.18
По сути про собственные репликации