|
16.04.2014, 21:27 | #1 |
Участник
|
Запуталась в 3 соснах (( или как отловить исключение
Есть код , типа такого
X++: try { ttsbegin; .... stdClass.Method(); myClass.Method(); .... ttscommit; } catch {} код приблизительно такой: X++: try { ttsbegin; .... if (!someValidation()) throw error();.... ttscommit; } catch {} X++: myClass.Method(); (То есть, суть в том, что вычисления в stdClass не критичны для моего класса и мне достаточно сообщения в инфологе, что они закончились с ошибкой и нужно продолжить выполние кода ) Retry не подходит, тк он на самое начало вернет моего try блока. Замена исключения в stdClass на ttsAbort тоже не поможет, тк ttsAbort откатывает не только текущую транзакцию, но и внешние тоже(. Как перехватить ошибку, выбрасываемую stdClass классом и продолжить выполнение кода? |
|
16.04.2014, 21:34 | #2 |
Дмитрий Ерин
|
Как-то так подойдет?
X++: try { ttsbegin; .... try { stdClass.Method(); } catch { // warning } myClass.Method(); .... ttscommit; } catch {}
__________________
Последний раз редактировалось Ruff; 16.04.2014 в 21:38. Причина: немного подумал) |
|
16.04.2014, 21:41 | #3 |
Молодой, подающий надежды
|
Не подойдет, т.к. вложенный try{}catch{} не работает внутри внешней транзакции. Правильнее разбить на две независимых транзакции, но тут надо постановку смотреть, можно ли будет обеспечить целостность данных.
Добавлено: пока писал ответ, Вы и сами все поняли
__________________
Кононов Пётр Последний раз редактировалось pedrozzz; 16.04.2014 в 21:44. |
|
|
За это сообщение автора поблагодарили: Ruff (2). |
17.04.2014, 00:36 | #4 |
Участник
|
По постановке они именно вложенные в этом-то и проблема.
по-видимому, придется переписывать логику в std, чтобы обойти исключение ... ох( |
|
17.04.2014, 08:06 | #5 |
Участник
|
|
|
17.04.2014, 16:50 | #6 |
Участник
|
Смысл мероприятия:
В цикле вставляются записи в таблицу - должны либо вставиться все, либо ни одной. Т.о транзакция. При вставке каждой записи для нее выполняются определенные пересчеты, которые, если произойдут - хорошо, если нет, то пользователь на основании инфолога потом разберется в каждой конкретной ситуации. То есть по идее должно быть в инфологе нечто типа : Строка 1: Вставлена Пересчет А выполнился Пересчет Б закончился с такими-то ошибками (это надо отловить и продолжить выполнение кода) Строка 2: Вставлена Пересчет А закончился с такими-то ошибками Пересчет Б выполнился .... и так для кучи строк. Можно, конечно все переструктурировать в существующем коде. чтобы обойти проблему, но: 1) пользователям это не нравится, тк они для каждой строки хотят видеть все релевантные для нее ошибки /предупреждения. (И, вообще-то, я с ними согласна.) 2) по-моему, это принципиально неправильно, что , дожив до 2012, мы до сих пор не можем нормально отлавливать ошибки. Последний раз редактировалось IKA; 17.04.2014 в 17:04. |
|
17.04.2014, 17:57 | #7 |
Сенбернар
|
Как вариант :
- все вставлять во временную таблицу (общая транзакция не нужна) - при отсутствии ошибок - переносить из временной в нормальную таблицу, в транзакции, ессно, но уже после всех "пересчетов" Как вам оно?
__________________
Best Regards, Roman Последний раз редактировалось RVS; 17.04.2014 в 17:59. |
|
17.04.2014, 23:24 | #8 |
Участник
|
Цитата:
Цитата:
PS. Вставляйте свои записи в RecordSortedList - тогда на момент вызова пересчетов можно будет обойтись без общей транзакции и отловить каждую ошибку в вашем try/catch, а в конце обработки, если ошибок не было, можно будет вставить все строки разом в одной транзакции (вариации на тему временной таблицы ) Последний раз редактировалось gl00mie; 18.04.2014 в 01:06. Причина: PS |
|
|
За это сообщение автора поблагодарили: S.Kuskov (2). |
18.04.2014, 08:57 | #9 |
Участник
|
Цитата:
Сообщение от IKA
В цикле вставляются записи в таблицу - должны либо вставиться все, либо ни одной. Т.о транзакция. При вставке каждой записи для нее выполняются определенные пересчеты, которые, если произойдут - хорошо, если нет, то пользователь на основании инфолога потом разберется в каждой конкретной ситуации.
|
|
18.04.2014, 10:06 | #10 |
Участник
|
Результат пересчетов, насколько я понял, должен влиять на то, накатывать транзакцию или нет.
|
|
18.04.2014, 11:24 | #11 |
Участник
|
На сколько я понял посыл такой. "вставлять нужно всегда все, даже при ошибках валидации, либо не вставлять ни одной, если например свет отключился".
Но дело в том что для системы исключение "искуственное", сгенерированное при валидации уровня бизнес-логики, ничем не отличается от исключения, возникшего на более низком слое. Но вы же в случае аппаратного сбоя не хотите SQL серверу сказать все равно запиши эту строку, а пользователь потом по логам подправит, что не довставилось. . Ещё момент, на который стоит обратить внимание. При вставке строки, необходимо обрабатывать ошибки только своего метода, или же и стандартного тоже? Если вопрос в обработке (читай предотвращении отката транзакции) в стандартном методе, то здесь необходимо задуматься. Используя стандартный метод, вы либо соглашаетесь с его действиями, либо нет. Если метод написан так, что при неудачной валидации вставка строки откатывается, то никакими внешними (по отношению к методу) перехватчиками вы не сможете (да и не должны) изменить это. Для изменения поведения придется изменить метод. И мне кажется это правильным. |
|
18.04.2014, 13:44 | #12 |
Сенбернар
|
Цитата:
Все-таки, КМК, хотят следующего : - сперва проверить весь массив исходных данных (а-ля Проверка журнала) - затем, если все ОК - записать данные из этого массива данных в какую-то таблицу (а-ля Разноска журнала) То, что я там предлагал - минимально трудоемкое решение второго случая.
__________________
Best Regards, Roman |
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
18.04.2014, 17:37 | #13 |
Участник
|
RVS, спасибо. Да в такой постановке вопроса есть смысл.
В случае возникновения ошибки при вставке одной из строк, продолжить пытаться вставлять остальные строки, и только потом сделать откат. |
|
18.04.2014, 18:23 | #14 |
Участник
|
Задача.
Имеем стандартный метод, из которого возможен выброс исключения. Необходимо обработать (успешно, не успешно - не важно) этим методом все строки. Если получилось обработать все строки успешно (без исключений), то подтвердить транзакцию, иначе откатить все, даже успешно обработанные строки. Решение. Идея такая: Этап первый "оптимистический". Открываем транзакцию и строка за строкой выполняем обработку в надежде на то что исключений не будет. Если все получилось закрываем транзакцию. Этап второй "ловим исключение". Помещаем транзакцию, описанную в первом этапе в блок 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 |
Дмитрий Ерин
|
Испытываю дискомфорт при большом скоплении флагов) Поэтому позволил себе альтернативную модификацию решения от 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). |