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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 16.04.2014, 21:27   #1  
IKA is offline
IKA
Участник
 
359 / 65 (3) ++++
Регистрация: 15.03.2006
Запуталась в 3 соснах (( или как отловить исключение
Есть код , типа такого
X++:
try
{
    ttsbegin;
    ....
    stdClass.Method();

    myClass.Method();
    ....
    ttscommit;
}
catch
{}
в stdClass.Method();
код приблизительно такой:
X++:
try
{
    ttsbegin;
    ....
    if (!someValidation())
         throw error();....
    ttscommit;
}
catch
{}
в результате, естественно, как только вызываемый класс выбрасывает ошибку, то она перехватывается в catch уже моего класса, а мне надо , чтобы исполнение кода не прерывалось и перешло на строку
X++:
myClass.Method();
.

(То есть, суть в том, что вычисления в stdClass не критичны для моего класса и мне достаточно сообщения в инфологе, что они закончились с ошибкой и нужно продолжить выполние кода )
Retry не подходит, тк он на самое начало вернет моего try блока.
Замена исключения в stdClass на ttsAbort тоже не поможет, тк ttsAbort откатывает не только текущую транзакцию, но и внешние тоже(.

Как перехватить ошибку, выбрасываемую stdClass классом и продолжить выполнение кода?
Старый 16.04.2014, 21:34   #2  
Ruff is offline
Ruff
Дмитрий Ерин
Аватар для Ruff
1C
 
475 / 396 (14) ++++++
Регистрация: 18.09.2003
Адрес: Тула
Как-то так подойдет?
X++:
try
{
    ttsbegin;
    ....
    try
    {
       stdClass.Method();
    }
    catch
    { 
     // warning
    }
   
    myClass.Method();
    ....
    ttscommit;
}
catch
{}
Добавлено: Хотя правильнее наверно будет разбить этот блок на две транзакции - первая со стандартным, вторая - с вашим методом.
__________________

Последний раз редактировалось Ruff; 16.04.2014 в 21:38. Причина: немного подумал)
Старый 16.04.2014, 21:41   #3  
pedrozzz is offline
pedrozzz
Молодой, подающий надежды
Аватар для pedrozzz
MCBMSS
Лучший по профессии 2015
 
164 / 218 (8) ++++++
Регистрация: 18.02.2010
Адрес: Краснодар
Цитата:
Сообщение от Ruff Посмотреть сообщение
Как-то так подойдет?
Не подойдет, т.к. вложенный try{}catch{} не работает внутри внешней транзакции. Правильнее разбить на две независимых транзакции, но тут надо постановку смотреть, можно ли будет обеспечить целостность данных.
Добавлено: пока писал ответ, Вы и сами все поняли
__________________
Кононов Пётр

Последний раз редактировалось pedrozzz; 16.04.2014 в 21:44.
За это сообщение автора поблагодарили: Ruff (2).
Старый 17.04.2014, 00:36   #4  
IKA is offline
IKA
Участник
 
359 / 65 (3) ++++
Регистрация: 15.03.2006
По постановке они именно вложенные в этом-то и проблема.
по-видимому, придется переписывать логику в std, чтобы обойти исключение ... ох(
Старый 17.04.2014, 08:06   #5  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от IKA Посмотреть сообщение
То есть, суть в том, что вычисления в stdClass не критичны для моего класса и мне достаточно сообщения в инфологе, что они закончились с ошибкой и нужно продолжить выполние кода
А для чего вы тогда свою транзакцию открываете до stdClass?
Старый 17.04.2014, 16:50   #6  
IKA is offline
IKA
Участник
 
359 / 65 (3) ++++
Регистрация: 15.03.2006
Смысл мероприятия:

В цикле вставляются записи в таблицу - должны либо вставиться все, либо ни одной. Т.о транзакция. При вставке каждой записи для нее выполняются определенные пересчеты, которые, если произойдут - хорошо, если нет, то пользователь на основании инфолога потом разберется в каждой конкретной ситуации.
То есть по идее должно быть в инфологе нечто типа :
Строка 1:
Вставлена
Пересчет А выполнился
Пересчет Б закончился с такими-то ошибками (это надо отловить и продолжить выполнение кода)
Строка 2:
Вставлена
Пересчет А закончился с такими-то ошибками
Пересчет Б выполнился ....

и так для кучи строк.

Можно, конечно все переструктурировать в существующем коде. чтобы обойти проблему, но:
1) пользователям это не нравится, тк они для каждой строки хотят видеть все релевантные для нее ошибки /предупреждения. (И, вообще-то, я с ними согласна.)
2) по-моему, это принципиально неправильно, что , дожив до 2012, мы до сих пор не можем нормально отлавливать ошибки.

Последний раз редактировалось IKA; 17.04.2014 в 17:04.
Старый 17.04.2014, 17:57   #7  
RVS is offline
RVS
Сенбернар
Аватар для RVS
Злыдни
 
696 / 130 (6) +++++
Регистрация: 27.02.2003
Адрес: Королев МО
Как вариант :

- все вставлять во временную таблицу (общая транзакция не нужна)
- при отсутствии ошибок - переносить из временной в нормальную таблицу, в транзакции, ессно, но уже после всех "пересчетов"

Как вам оно?
__________________
Best Regards,
Roman

Последний раз редактировалось RVS; 17.04.2014 в 17:59.
Старый 17.04.2014, 23:24   #8  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от IKA Посмотреть сообщение
Можно, конечно все переструктурировать в существующем коде. чтобы обойти проблему, но:
1) пользователям это не нравится, тк они для каждой строки хотят видеть все релевантные для нее ошибки /предупреждения. (И, вообще-то, я с ними согласна.)
Научите пересчеты не выбрасывать исключения - вот и все. Чтобы не лезть глубоко в код, если проблематично протащить в пересчеты новый параметр, можно где-нить в GlobalCache вести флажок, управляющий этим поведением, а также повесить обработчик в ttsNotifyAbort(), чтобы этот флажок вычищал. При наличии флажка пересчеты будут просто выводить предупреждения и прекращать работу, при отсутствии - выбрасывать исключения, как раньше. В конце вставки всех строк анализируете наличие предупреждений в инфологе, как в проверках целостности сделано, и принимаете решение о том, накатывать транзакцию или нет. После успешного накатывания транзакции не забываете удалить флажок из GlobalCache, чтобы пересчеты заработали, как раньше.
Цитата:
Сообщение от IKA Посмотреть сообщение
2) по-моему, это принципиально неправильно, что , дожив до 2012, мы до сих пор не можем нормально отлавливать ошибки.
Это - by design, потому что предполагается, что если код выбрасывает исключение в транзакции, значит, в этой транзакции что-то пошло не так, и ее надо откатить. Это как остановка конвейера на японских заводах: каждый рабочий может это сделать при необходимости, но при этом каждый рабочий осознает всю полноту ответственности за такое решение. А когда можно "нормально отлавливать" любое и каждое исключение в транзакции, то получается, как с запуском Челленджера (см. про уплотнительные кольца и предупреждения Morton Thiokol).

PS.
Цитата:
Сообщение от IKA Посмотреть сообщение
В цикле вставляются записи в таблицу - должны либо вставиться все, либо ни одной. Т.о транзакция.
Вставляйте свои записи в RecordSortedList - тогда на момент вызова пересчетов можно будет обойтись без общей транзакции и отловить каждую ошибку в вашем try/catch, а в конце обработки, если ошибок не было, можно будет вставить все строки разом в одной транзакции (вариации на тему временной таблицы )

Последний раз редактировалось gl00mie; 18.04.2014 в 01:06. Причина: PS
За это сообщение автора поблагодарили: S.Kuskov (2).
Старый 18.04.2014, 08:57   #9  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от IKA Посмотреть сообщение
В цикле вставляются записи в таблицу - должны либо вставиться все, либо ни одной. Т.о транзакция. При вставке каждой записи для нее выполняются определенные пересчеты, которые, если произойдут - хорошо, если нет, то пользователь на основании инфолога потом разберется в каждой конкретной ситуации.
Можно сначала вставить записи, закрыть транзакцию, а потом без общей транзакции (если необходимо, то сделать транзакцию для каждой отдельной строки) выполнить пересчет?
Старый 18.04.2014, 10:06   #10  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Результат пересчетов, насколько я понял, должен влиять на то, накатывать транзакцию или нет.
Старый 18.04.2014, 11:24   #11  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
На сколько я понял посыл такой. "вставлять нужно всегда все, даже при ошибках валидации, либо не вставлять ни одной, если например свет отключился".

Но дело в том что для системы исключение "искуственное", сгенерированное при валидации уровня бизнес-логики, ничем не отличается от исключения, возникшего на более низком слое. Но вы же в случае аппаратного сбоя не хотите SQL серверу сказать все равно запиши эту строку, а пользователь потом по логам подправит, что не довставилось. .

Ещё момент, на который стоит обратить внимание. При вставке строки, необходимо обрабатывать ошибки только своего метода, или же и стандартного тоже? Если вопрос в обработке (читай предотвращении отката транзакции) в стандартном методе, то здесь необходимо задуматься. Используя стандартный метод, вы либо соглашаетесь с его действиями, либо нет. Если метод написан так, что при неудачной валидации вставка строки откатывается, то никакими внешними (по отношению к методу) перехватчиками вы не сможете (да и не должны) изменить это. Для изменения поведения придется изменить метод. И мне кажется это правильным.
Старый 18.04.2014, 13:44   #12  
RVS is offline
RVS
Сенбернар
Аватар для RVS
Злыдни
 
696 / 130 (6) +++++
Регистрация: 27.02.2003
Адрес: Королев МО
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Насколько я понял посыл такой. "вставлять нужно всегда все, даже при ошибках валидации, либо не вставлять ни одной, если например свет отключился"
Перечитал еще раз - а ведь правда, и так тоже понять можно )))

Все-таки, КМК, хотят следующего :

- сперва проверить весь массив исходных данных (а-ля Проверка журнала)
- затем, если все ОК - записать данные из этого массива данных в какую-то таблицу (а-ля Разноска журнала)

То, что я там предлагал - минимально трудоемкое решение второго случая.
__________________
Best Regards,
Roman
За это сообщение автора поблагодарили: S.Kuskov (1).
Старый 18.04.2014, 17:37   #13  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
RVS, спасибо. Да в такой постановке вопроса есть смысл.

В случае возникновения ошибки при вставке одной из строк, продолжить пытаться вставлять остальные строки, и только потом сделать откат.
Старый 18.04.2014, 18:23   #14  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,437 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Задача.
Имеем стандартный метод, из которого возможен выброс исключения.
Необходимо обработать (успешно, не успешно - не важно) этим методом все строки.
Если получилось обработать все строки успешно (без исключений), то подтвердить транзакцию, иначе откатить все, даже успешно обработанные строки.

Решение.
Идея такая: Этап первый "оптимистический". Открываем транзакцию и строка за строкой выполняем обработку в надежде на то что исключений не будет. Если все получилось закрываем транзакцию.
Этап второй "ловим исключение". Помещаем транзакцию, описанную в первом этапе в блок try-catch. При возникновении исключения транзакция откатится и мы узнаем об этом.
Этап третий "зацикливаем". В случае поимки нами исключения повторяем для оставшихся строк первый и второй этап, но уже без подтверждения транзакции даже в случае успеха.
X++:
enumerator = Lines.getEnumerator()
first = true;
do
{
    toBeContinued = false;

    try
    {
        ttsbegin;
            while (enumerator.moveNext())
            {
                stdClass.exceptionWarinigMethod(enumerator.current())
            }
        if (first) ttscommit;
        else ttsabort;
    } 
    catch
    {
        toBeContinued = true;
    }

    first = false;
}
while (toBeContinued)
За это сообщение автора поблагодарили: Ruff (3).
Старый 18.04.2014, 23:57   #15  
Ruff is offline
Ruff
Дмитрий Ерин
Аватар для Ruff
1C
 
475 / 396 (14) ++++++
Регистрация: 18.09.2003
Адрес: Тула
Испытываю дискомфорт при большом скоплении флагов) Поэтому позволил себе альтернативную модификацию решения от S.Kuskov:
X++:
    enumerator = Lines.getEnumerator();
    for (errCount = 0; true; errCount++)
    {
        try
        {
            ttsbegin;
                while (enumerator.moveNext())
                {
                    stdClass.exceptionWarinigMethod(enumerator.current())
                }
            if (errCount == 0) ttscommit;
            else ttsabort;
        }
        catch
        {
            continue;
        }
        break;
    }
За это сообщение автора поблагодарили: S.Kuskov (1).
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
DAX2009, try / catch не перехватывает исключение (не в транзакции) AR® DAX: Программирование 4 23.05.2013 15:29
BusinessConnector .Net - исключение при вызове AxaptaRecord.Write Evgenius DAX: Программирование 22 04.05.2011 19:47
Исключение при переустановке Evgenius DAX: Администрирование 7 21.12.2010 15:49
Как понять что вызывает исключение Invalid Method Call Jab Straight DAX: Программирование 0 17.12.2007 23:23
Почему может не ловиться исключение korvin DAX: Программирование 5 19.09.2006 16:49

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

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

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