Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.09.25;
Скачать: [xml.tar.bz2];

Вниз

Есть ли в 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.011 c
14-82392
waw
2003-09-05 11:47
2003.09.25
Компоненты для программирования под Palm OS?


14-82468
cyborg
2003-09-06 20:38
2003.09.25
Assembler - NOT с регистром


6-82375
Юля
2003-07-25 13:00
2003.09.25
Сетевой диск


3-82073
Centurion
2003-09-05 14:29
2003.09.25
Ошибка БД


6-82350
Маратей_И
2003-07-25 13:44
2003.09.25
Раскажите про WININET.PAS





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский