Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
3-1079670894
Сказочник
2004-03-19 07:34
2004.04.18
Два SELECTа подряд......


3-1079891555
neVIP
2004-03-21 20:52
2004.04.18
Эксклюзивный доступ к базе


1-1081074775
Serious Sam
2004-04-04 14:32
2004.04.18
Как сделать, чтобы приложение запускалось в определенное время?


1-1080732046
TATIANA
2004-03-31 15:20
2004.04.18
Модальная форма - кнопка "ОК" - Edit


14-1080131354
dr Tr0jan
2004-03-24 15:29
2004.04.18
Опять про хостинг, но уже с MySQL





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский