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