AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX Blogs
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 11.09.2007, 05:42   #1  
Blog bot is offline
Blog bot
Участник
 
25,626 / 848 (80) +++++++
Регистрация: 28.10.2006
Issues concerning X++: Exception handling and transactions
Источник: http://blogs.msdn.com/x/archive/2007...nsactions.aspx
==============

The runtime semantics of exceptions is peculiar in X++. The difference from the semantics from other languages is that exception handling considers any catch blocks that are in a scope that contains a running transaction as ineligible to handle the exception. Consequently the behavior of exceptions is quite different in the situation where a transaction is running and in the situation where no transactions are running. This makes the exception semantics different from exception semantics of other languages, even though the syntax is very much the same. This is a perfect setup for confusion even for seasoned X++ programmers.
Please consider the example below for the following discussion:
X++:
1: try
2: {
3:     MyTableType t;
4:     ttsBegin;    // Start a transaction 
5:     try
6:     {
7:         throw error(Something bad );
8:     }
9:     catch
10:     {
11:         // Innermost catch block 
12:     }
13:     update_recordset t  // Must run within a transaction 
14:     ttsCommit;    // Commit the transaction 
15: }
16: catch
17: {
18:     Info (In outermost exception );
19: }
20:
20:
When the exception is thrown in the code above, the control is not transferred to the innermost catch block, as would have been the case if there had been no transaction active; Instead the execution resumes at the outermost exception handler, i.e. the first exception handler outside the try block where where the transaction started (This is the catch all exception handler in line 19).
This behavior is by design. Whenever an exception is thrown all transactions are rolled back (except for two special exceptions namely Exception::UpdateConflict and Exception::UpdateConflictNotRecovered, that do not roll back the active transactions). This is an inseparable part of the semantics of throwing exceptions in X++. If the exception is not one of the two exceptions mentioned above, the flow of control will be transferred to the handler of the outermost block that contains a TTSBegin. The reasoning behind this is that the state of the database queries would not be consistent when the transactions are rolled back, so all code potentially containing this code is skipped.
Another issue is balancing of the transaction-level.
Please consider an amended example:
X++:
1: try
2: {
3:     MyTableType t;
4:     ttsBegin;      // Start a transaction – Increment TTS-level to 1 
5:     try
6:     {
7:         ttsBegin;  // Start a nested transaction – Increment TTS-level to 2 
8:         throw new SysException(Something bad );
9:         ttsCommit;     // Decrease TTS-level to 1 
10:     }
11:     catch
12:     {
13:         // Innermost catch block 
14:         // What is the tts level here? 
15:         info (appl.ttslevel());
16:         // Something bad happened -> abort the transaction 
17:         ttsAbort;
18:     }
19:     update_recordset t  // Must run within a transaction 
20:     ttsCommit;       // Decrease TTS-level to 0, and commit 
21: }
22: catch
23: {
24:     Info (In outermost exception );
25: }
Let’s examine the case where we allowed the inner catch block to run as the result of throwing the exception. The question is: What should the TTS-Level be in the innermost catch block?
TTSlevel is 1: This won’t work, as the innermost catch block must be able to compensate (and commit) or abort the level-2 transaction. TTS Level 1 would mandate that the system has taken the decision to either abort or commit the level-2 transaction.
TTSlevel is 2: This won’t work either, as the innermost catch block should be able to abort the level-2 transaction. A ttsabort inside the innermost catch block will also abort the level-1 transaction, and render the code following the catch block void. This in turn requires that the innermost catch block throws a new exception, and then we end up in the outermost catch block anyway.
I hope this provides a little clarity in these murky waters.



Источник: http://blogs.msdn.com/x/archive/2007...nsactions.aspx
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
За это сообщение автора поблагодарили: alex55 (1).
Старый 14.02.2009, 00:46   #2  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
Цитата:
This behavior is by design. Whenever an exception is thrown all transactions are rolled back (except for two special exceptions namely Exception::UpdateConflict and Exception::UpdateConflictNotRecovered, that do not roll back the active transactions).
Однако: Exception::UpdateConflictNotRecovered у меня откатывает транзакцию как и другие ошибки, в отличие от Exception::UpdateConflict:

Info Сообщение (00:41:37) rec count: 3
Info Сообщение (00:41:37) level 1 catched
Info Сообщение (00:41:37) level 1 completed
Info Сообщение (00:41:37) rec count: 0

X++:
static void Test_TTS_1(Args _args)
{
    Test_TTS_1 Test_TTS_1;
    ;
 
    delete_from Test_TTS_1;

    try
    {
        ttsbegin; //tts level 1

        try
        {
            ttsbegin; //tts level 2

            try
            {
                Test_TTS_1.insert();
                Test_TTS_1.insert();
                Test_TTS_1.insert();
                select count(recid) from Test_TTS_1;
                info("rec count: " + int2str(Test_TTS_1.RecId));

                //throw error("my exception");
                throw Exception::UpdateConflictNotRecovered;
                //throw Exception::UpdateConflict;
            }
            catch //implicit ttsabort
            {
                info("level 3 catched");
            }

            ttscommit;

            info("level 3 completed");
        }
        catch //implicit ttsabort
        {
            info("level 2 catched");
        }

        ttscommit;

        info("level 2 completed");
    }
    catch //implicit ttsabort
    {
        info("level 1 catched");
    }

    info("level 1 completed");

    select count(recid) from Test_TTS_1;

    info("rec count: " + int2str(Test_TTS_1.RecId));

}
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
staticsax: New approach to Exceptions and Transactions handling Blog bot DAX Blogs 0 13.11.2007 20:30
Pokluda: SysTest part IV.: Test/Suite initialization and cleaning; Execution isolation Blog bot DAX Blogs 0 28.10.2006 17:43
SysDictCoder: Axapta error handling and database transactions Blog bot DAX Blogs 0 28.10.2006 16:47
Говорят вышел SP2 для Axapta 3. Кто нибуть что знает на эту тему? soin DAX: Прочие вопросы 10 13.10.2003 10:43

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 10:17.