|  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. Цитата:  ) Последний раз редактировалось 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). | |