Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Нужна ли проверка InTransaction в однопоточном приложении? [D7, XP]


И. Павел ©   (2009-10-13 11:57:00) 

Здравствуйте!
В коде дописываемой мною программы обращение к базе везде выполняется так:

if not DataMod.ADOConnection1.InTransaction then
begin
 DataMod.ADOConnection1.BeginTrans;
 try
   ADOQuery1.SQL.Clear;
   ADOQuery1.SQL.Add('…
  …
   DataMod.ADOConnection1.CommitTrans;
 except
   DataMod.ADOConnection1.RollbackTrans;
 end;

Создания дополнительных потоков не нашел.
Подскажите, пожалуйста, имеет ли смысл вставлять тут “if not DataMod.ADOConnection1.InTransaction then” или предыдущий программист просто выдрал это из какого-то примера и везде копировал? Думаю, что ADOConnection1.InTransaction показывает только транзакции, совершаемые текущей программой (или все же всеми), и тогда InTransaction всегда будет false если приложение однопоточное?


И. Павел   (2009-10-13 15:06:00) [1]

Кажется теперь понял:
if not DataMod.ADOConnection1.InTransaction
как раз проверяет ситуацию, если Rollback отказал и транзакция не завершилась. SQL 2005 ругается на вложенную транзакцию: 'В данном сеансе невозможен запуск дополнительных транзакций', так что, наверное, лучше не писать
if not DataMod.ADOConnection1.InTransaction
чтобы вылетала ошибка, и пользователь понимал, что запрашиваемая операция не выполнилась. Иначе
if not DataMod.ADOConnection1.InTransaction
просто будет молчать и ничего не делать.


Медвежонок Пятачок   (2009-10-13 14:42:00) [2]

Единственное, что приходит в голову:

except
try  
  Rollback
except
  Application.MessageBox('Нет связи');
  Application.Terminate;
end;
end;


Ты так ничего и не понял.
Откуда уверенность, что роллбак вызвал исключение потому что нет связи?
Она например есть, но на сервере роллбак сегмент закончился и он ее откатить не может (это одна из тысячи возможных причин)


И. Павел   (2009-10-13 14:38:00) [3]


> Медвежонок Пятачок ©

Интересный вариант :)
И что в этом случае будет? Вылетит ошибка при выполнении Rollback?
А транзакция в итоге закроется? Или при возобновлении связи останется активна?
И самое главное: такой вариант можно как нибудь учесть в программе?

Единственное, что приходит в голову:

except
 try  
   Rollback
 except
   Application.MessageBox('Нет связи');
   Application.Terminate;
 end;
end;


Медвежонок Пятачок   (2009-10-13 14:24:00) [4]

> except
>   RollbackTrans;
> end;

Если транзакция в обработчике уже не активна, то будет еще один эксепшен для которого у тебя трая не предусмотрено.

Пример:
Начинаем транзакцию.
Вносим изменения.
На коммите пропала связь.
Эксепшен.
в обработчике роллбачить уже нечего. точнее некого.


И. Павел   (2009-10-13 14:22:00) [5]

Хотя, ИМХО, лучше уж ERROR, чем тихое игнорирование встреченных SQL запросов :)


И. Павел   (2009-10-13 14:15:00) [6]


> Медвежонок Пятачок ©


Спасибо. Но в программе старт транзакции нигде не отделен от ее завершения, тоесть логика не сложная и вложенная, а простая:


> BeginTrans;
> try
>   …
>   CommitTrans;
> except
>   RollbackTrans;
> end;


тоесть транзакция всегда закроется, даже после ошибки, а внутри try транзакция 100% открыта, иначе бы программа вылетела до try.

Но за пример, когда, в принципе, может возникнуть ошибка, спасибо, поищу, может быть в коде действительно есть незакрывающиеся сразу транзакции...


Медвежонок Пятачок   (2009-10-13 14:04:00) [7]

Так с чем же это связано?

Ни с чем кроме логики приложения.
Например открываем форму справочника и начинаем транзакцию.
В форме справочника открываем запись на редактирование и снова стартуем транзакцию.
Например потому что справочник программировал один программист, а редактор записи другой.

Если сервер не поддерживает вложенные транзакции, будет еррор.
Хотя поток один единственный.

Кроме того, вызывая безусловные роллбаки и коммиты ты как бы уверен на все сто что коннекшен сейчас в транзакции.
А это вовсе не обязательно.


И. Павел   (2009-10-13 13:46:00) [8]


> Inovet ©

???
Вроде бы нигде true не писал.


> tru ADOQuery4.SQL.ExecSQL/Open


это просто описка, там, разумеентся, try


Inovet   (2009-10-13 13:43:00) [9]

> [0] И. Павел   (13.10.09 11:57)

А не путаешь ли ты try с true?


И. Павел   (2009-10-13 13:20:00) [10]

Из справки:

> Use the InTransaction property to prevent calling BeginTrans
> when a transaction has already been initiated for the connection
> component.

А если поток один и везде ошибка ловится и в except вызывается Rollback, то вроде бы InTransaction не нужен, так как вложенных BeginTrans нет...


И. Павел   (2009-10-13 13:12:00) [11]


> с многопоточностью это никак не связано

Так с чем же это связано? Единственное, о чем я подумал, когда увидел этот код, что где-то может быть второй процесс, в этот же момент работающий с этой же базой, и может откатиться/подтвердиться другая транзакция...


> Ответ на вопрос нужно или нет скрывается в строках между
> try и Commit


Там повторяются конструкции вида:

 ADOQuery4.SQL.Clear;
 ADOQuery4.SQL.Add('select/update/insert...
 tru ADOQuery4.SQL.ExecSQL/Open
 except  on e : exception do ...


Иногда идут циклы


> while
...
  ADOQuery4.Next
...
 


Иногда даже встречаются транзакции, всключающие только несколько select-ов, кстати, подскажите, пожалуйста, нужны ли BeginTrans и Commit/Rollback только для цепочки Select-ов, что то я совсем запутался. Вроде бы незачем...


Dennis I. Komarov   (2009-10-13 12:38:00) [12]

Ответ на вопрос нужно или нет скрывается в строках между try и Commit


Медвежонок Пятачок   (2009-10-13 12:16:00) [13]

с многопоточностью это никак не связано


Наверх

Титульная страница Поиск, карта сайта Написать письмо