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

Вниз

Есть ли в DELPHI аналог функции AbnormalTermination()?   Найти похожие ветки 

 
mishgan   (2003-09-08 10:29) [0]

Нужно в блоке try .. finally .. end определить, каким образом произошло выполнение finally-секции: естественным путем, или неявно, например в результате возникновения Exception, либо был вызов exit, break, continue и т.п.
В Visual C++ есть функция AbnormalTermination(). Если вызвать в секции funally, то можно определить как мы в нее попали (явно или неявно).
В DELPHI такой функции не обнаружено (анализ system и sysutils ничего полезного не дал). Поэтому приходится заводить переменные-флажки, а этого не хочется постоянно делать.


 
mishgan   (2003-09-08 15:26) [1]

:(((


 
sts ©   (2003-09-08 19:15) [2]

if ExceptObject<>nil then ...


 
mishgan   (2003-09-09 12:28) [3]

У меня чей-то ExceptObject всегда nil

procedure TForm1.Button1Click(Sender: TObject);
var
i: real;
begin
i:=0;
try
//raise Exception.Create("raise");
i:=1/i;
finally
if ExceptObject<>nil then
ShowMessage("1:"+FloatToStr(i))
else
ShowMessage("2");
end;
end;

В этом примере всегда выводится "2"


 
mishgan   (2003-09-10 09:50) [4]

уп


 
KSergey ©   (2003-09-10 10:01) [5]

Погодите..
Для отлова исключений - есть конструкция try..except (буквального аналога в Си нет, к стати)
В excep секцию попадаем только при возниковени исключения.

Однако же отловить exit, break, continue - здесь не выйдет, это не исключения (к стати, а что за выход по continue??). Но можно вместо этих выходов возбудить исключение и погасить его (в том же try..except). Наверное, это будет то, что надо


 
mishgan   (2003-09-10 10:39) [6]

>>Для отлова исключений - есть конструкция try..except
Мне и не нужно их отлавливать. Мне нужно определить как мы попали в finally, нормальным путем или нет (в finally у меня делается Commit/Rollback Transaction). В VC++ это делается в секции finally вызовом функции AbnormalTermination.
>>к стати, а что за выход по continue
Если try .. finally находится в теле цикла, то такое возможно.
>>Но можно вместо этих выходов возбудить исключение
Не, так не интересно. Лучше буду пользоваться флажками, как и сейчас.


 
KSergey ©   (2003-09-10 10:52) [7]

[6] mishgan (10.09.03 10:39)
Не, так не интересно. Лучше буду пользоваться флажками, как и сейчас.


Ну и напрасно, по-моему. Впрочем, вам виднее.
По поводу когда делать RollBack.
Я делаю всегда такую конструкцию:

BeginTrans;
try
.. возможно, создание объекта или здесь ничего и нет
try
... какой-то код модификаци БД
CommitTrans; // раз сюда добрались - все прошло успешно
finally
..тут уничтожаем созданный объект(ы)
end;
except
RollBack; // раз сюда попали - случилась невезуха
raise; // в общем случае гасить исключение - не хорошо, пусть об нем все знают
end;


 
mishgan   (2003-09-10 15:02) [8]

Если во вложенной секции try .. finally есть exit то транзакция останется незавершенной.
Да и по другим причинам такой вариант не очень катит - транзакция может откатываться не только в случае исключений, а в случае каких-то логических ошибок (которые анализируются отдельно). Получается, что ROLLBACK нужно писать в двух местах - нерасиво:
/////////////
BeginTrans;
try
try
... какой-то код модификаци БД
Errors:=....
finally
if not Errors then
CommitTrans
else
Rollback;
end;
except
RollBack;
raise;
end;
/////////////
Такой код уже не очень красив.
А вот если бы (мечтательно) был AbnormalTermination, то можно было бы обойтись одной секцией try ... finally


 
clickmaker ©   (2003-09-10 15:11) [9]

А такой вариант

try
Errors := false;
BeginTrans;
try
... какой-то код модификаци БД
Errors:=....
if Errors then
Raise Exception.Create("Errors")
finally
if not Errors then Commit;
end;
except
RollBack;
raise;
end;


 
mishgan   (2003-09-10 16:29) [10]

clickmaker [9]
Опять же exit (и т.п.) пропустим и останется тогда висеть транзакция надолго (в секцию Except не попадем) :(


 
clickmaker ©   (2003-09-10 16:33) [11]

Ну, в конце концов, можно и так

try
Errors := false;
BeginTrans;
try
... какой-то код модификаци БД
Errors:=....
finally
if not Errors then
Commit
else
Raise Exception.Create("Errors")
end;
except
RollBack;
raise;
end;


 
vuk ©   (2003-09-10 16:38) [12]

Почти то же самое, что у clickmaker только иначе.
Errors := false;
BeginTrans;
try
...
finally
if Errors then
Rollback
else
Commit;
end;


 
vuk ©   (2003-09-10 16:42) [13]

Вместо точек можно написать:

try
DoSomething;
if SomeCondition then
Errors := true;
except
Errors := true;
raise;
end;


 
mishgan   (2003-09-10 17:55) [14]

2(12)
Щас почти так и есть:
TrRes := false;
BeginTrans;
try
ErrorCode:=... //insert/update/delete/execute_sp
if ErrorCode<>0 then exit;
...
ErrorCode:=... //insert/update/delete/execute_sp
if ErrorCode<>0 then exit;
...
ErrorCode:=... //insert/update/delete/execute_sp
if ErrorCode<>0 then exit;
...
ErrorCode:=... //insert/update/delete/execute_sp
if ErrorCode<>0 then exit;
...
TrRes:=True; // В finally попадем естественным путем
finally
if (TrRes) and (ErrorCode=0) then
Rollback
else
Commit;
end;


 
Sandman25 ©   (2003-09-10 18:04) [15]

Если есть функция, возвращающая статус незавершенности транзакции, то можно так:

BeginTrans;
try
...
CommitTrans;
finally
if TransActive then
Rollback;
end;


 
Vuk ©   (2003-09-10 18:29) [16]

to mishgan:
У нас в таких случаях, по возможности, пишется одна SP, в которой и делаются все действия и проверки.


 
KSergey ©   (2003-09-11 07:41) [17]

[8] mishgan (10.09.03 15:02)
Если во вложенной секции try .. finally есть exit то транзакция останется незавершенной.


Вранье наглое. ;)
Если Exit стоит между try .. finally, но секция finally выполнится по любому!

Да и по другим причинам такой вариант не очень катит - транзакция может откатываться не только в случае исключений, а в случае каких-то логических ошибок (которые анализируются отдельно). Получается, что ROLLBACK нужно писать в двух местах - нерасиво:

Не надо его писать в 2 местах вовсе.
Надо просто в случае проблем генерировать обственное исключение и писать примерно такой код:

type
ERollbackTran = class Exception;
...

BeginTrans;
try
...
if проблема then raise ERollbackTran.Create("..");
...
CommitTran;
except
RollbackTran;
raise;
end;


Можно при необходимости свое исключение обработать по особому. Вот и все. Если по особому обрабатывать не нужно - можно и свой тип не заводить, просто Exception создавать. Да и флаги ни какие не нужны, при любой ошибке - код геренации исключения, можно его в отдельную ф-цию вынести при желании.
И все очень красиво (на мой взгляд).

[11] clickmaker © (10.09.03 16:33)

try
Errors := false;
BeginTrans;

try
... какой-то код модификаци БД
Errors:=....
finally
if not Errors then
Commit
else
Raise Exception.Create("Errors")
end;
except
RollBack;
raise;
end;


А вот так не надо делать (внимание на выделенный фрагмент).
Получится, что если при старте транзакции произойдет исключение - мы тут же вывалимся на RollBack, а ролбэкать-то нечего - транзакция еще не началась. В принципе ничего фатального, драйвер БД не идиот, он проверит при роллбэке была ли начата транзакция и к проблемам код не приведет, однако это не верно.
Так что надо BeginTrans выносить до try..except:

BeginTrans;
try
...
except
RollBack;
raise;
end;


 
mishgan   (2003-09-11 15:13) [18]

KSergey [17]
>>Вранье наглое. ;)
>>Если Exit стоит между try .. finally, но секция finally >>выполнится по любому
Это я знаю. Но обрати внимание, что 7-мом посте в finally нет оператора ROLLBACK, он есть в except. В секцию except в случае выполнения Exit мы не попадаем и транзакция остается открытой.


 
KSergey ©   (2003-09-12 07:03) [19]

> [18] mishgan (11.09.03 15:13)

Хм, дейстаивтельно, признаю, в пылу перепалки не все нюансы углядел. ;)
Впрочем, потому и счиатю лучшим рзруливанием - выход с возбуждением исключения.



Страницы: 1 вся ветка

Текущий архив: 2003.09.25;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.02 c
14-82420
NailMan
2003-09-08 19:13
2003.09.25
Kreed и как оно себе на уме


1-82265
3APA3A
2003-09-15 11:03
2003.09.25
AV при работе с ActionManager и ActionToolBar


6-82368
Leran2003
2003-07-24 15:44
2003.09.25
IdHTTP


6-82376
Checist [root]
2003-07-25 02:42
2003.09.25
Интеграция с HTML


3-82148
Karnegi
2003-09-03 13:39
2003.09.25
Помогите с копированием строк