Имя: Пароль:
1C
1С v8
Как откатить всю транзакцию? "В данной транзакции уже происходили ошибки"
0 ИС-2
 
naïve
16.07.13
11:50
Есть код, который исправляет множество контрагентов.
Надо сделать так, что если есть хотя бы одна ошибка, то транзакция вся откатывалась.
Но код вылетает с ошибкой "В данной транизакции уже происходили ошибки".
Что делаю не так? Где ошибка

Вот упрощенный пример кода:

   НачатьТранзакцию();
   // тут нормальный запрос
   Выборка = Справочники.Контрагенты.Выбрать();
   
   Пока Выборка.Следующий() Цикл
       Объект = Выборка.ПолучитьОбъект();
       
       // тут идет изменение реквизитов
       
       ЕстьОшибка = Ложь
       Попытка
           // тут какая-либо проверка не проходит
           // и Отказ перед записью стает Истина
           Объект.Записать();
       Исключение
           ЕстьОшибка = Истина;
       КонецПопытки;
   КонецЦикла;
   
   Если ЕстьОшибка Тогда
       ОтменитьТранзакцию();
   иначе
       ЗафиксироватьТранзакцию();
   КонецЕсли;
1 Man4kin
 
16.07.13
11:52
ЕстьОшибка = Ложь
Вынести за цикл
2 Maxus43
 
16.07.13
11:53
Исключение
           ЕстьОшибка = Истина;
КонецПопытки;
Если ЕстьОшибка Тогда Прервать; КонецЕсли;
3 ИС-2
 
naïve
16.07.13
11:55
(1) это да. Просто пример кода не рабочий. И все же как решить мой вопрос.
4 Maxus43
 
16.07.13
11:57
(3) выходи из цикла при первой же ошибке, что тут непонятного?
5 Man4kin
 
16.07.13
11:58
(3) дк это и есть решение вопроса, вынеси перед циклом эту строку.
6 ssh2006
 
16.07.13
12:00
(0) после того как не удалось записать один элемент, что либо записать в этой транзакции уже нельзя, поэтому (4)
7 zzerro
 
16.07.13
12:04
ЕстьОшибка = Ложь;
НачатьТранзакцию();
Пока ... Цикл
8 Maxus43
 
16.07.13
12:04
(5) нет, цикл продолжится, ровно как и ошибки
9 Maxus43
 
16.07.13
12:05
всем внимательно читать код, а потом советовать выносить до цикла. Сути это не меняет, криво - да, толку ноль от выноса
10 zzerro
 
16.07.13
12:06
пля...

ЕстьОшибка = Ложь;
НачатьТранзакцию();
Пока ... Цикл
  Попытка
     ТвойОбъект.Записать();
  Исключение
     ЕстьОшибка = Истина;
     Прервать;
  КонецПопытки
КонецЦикла;

Если ЕстьОшибка Тогда
   ОтменитьТранзакцию();
Иначе
   ЗафиксироватьТранзакцию();
КонецЕсли;
11 ИС-2
 
naïve
16.07.13
12:07
вот поправленный код. Но по сути вопроса, что-то можно сделать?
   
ЕстьОшибка = Ложь;
   НачатьТранзакцию();
   // тут нормальный запрос
   Выборка = Справочники.Контрагенты.Выбрать();
   
   Пока Выборка.Следующий() Цикл
       Объект = Выборка.ПолучитьОбъект();
       
       // тут идет изменение реквизитов
       
       
       Попытка
           // тут какая-либо проверка не проходит
           // и Отказ перед записью стает Истина
           Объект.Записать();
       Исключение
           ЕстьОшибка = Истина;
       КонецПопытки;
   КонецЦикла;
   
   Если ЕстьОшибка Тогда
       ОтменитьТранзакцию();
   иначе
       ЗафиксироватьТранзакцию();
   КонецЕсли;
12 Man4kin
 
16.07.13
12:07
(8) тогда он узнает все ошибки и будет править, а при прерывании он будет запускать обработку несколько раз и по одной ошибке исправлять.
13 Maxus43
 
16.07.13
12:09
(12) вторая ошибка в транзакции вызовет сообщение (0). Оно надо? он откатить хочет, а не показ ошибки
14 zzerro
 
16.07.13
12:09
еще рас пля... не посмотрел код....
Вот проверяй "какую-либо проверку" сам....
15 Maxus43
 
16.07.13
12:09
(11) ты издеваешся?) тебе много раз писали про волшебное слово ПРЕРВАТЬ
16 Man4kin
 
16.07.13
12:10
(13) ошибка возникает только при фиксации транзакции.
17 ssh2006
 
16.07.13
12:11
(16) если в транзакции произошла хоя бы одна ошибка связанная с записью данных, то продолжение транзакции невозможно
18 Man4kin
 
16.07.13
12:13
(17) у него же в попытке запись идет .
19 Maxus43
 
16.07.13
12:15
(16) нет
(18) вот именно

До фиксации или отката не доходит, ошибка происходит
20 ssh2006
 
16.07.13
12:16
(18) "Если восстановимая ошибка базы данных произошла в процессе выполнения транзакции, то, вне зависимости от того, было исключение, вызванное этой ошибкой, перехвачено и обработано или нет, транзакция уже не может быть продолжена или зафиксирована. Единственная операция с базой данных, которую можно произвести в такой ситуации - это отмена транзакции."
http://its.1c.ru/db/metod81#content:2313:1
21 Man4kin
 
16.07.13
12:17
(20) уяснил,спасибо :-)
22 ИС-2
 
naïve
16.07.13
12:21
(15) не точно поставил ТЗ :) Надо вывести еще все сообщения об ошибках. Т.е прервать не подходит
23 ИС-2
 
naïve
16.07.13
12:22
(20) получается ни как?
24 Maxus43
 
16.07.13
12:23
(23) в одной транзакции - никак
25 ИС-2
 
naïve
16.07.13
12:27
(24) а множество транзакций уже не откатить?
26 Maxus43
 
16.07.13
12:28
(25) нет, в 1с не раелизовано
27 Maxus43
 
16.07.13
12:29
смысл транзакции - или всё, или ничего. При наступлении ошибки срабатывает вариант Ничего, и далее продолжать попытки не имеет смысла
28 ssh2006
 
16.07.13
12:29
(22) Чтобы вывести ошибки и при этом ничего не записывать можно например так сделать

  Пока Выборка.Следующий() Цикл
НачатьТранзакцию();        
Объект = Выборка.ПолучитьОбъект();
       
       // тут идет изменение реквизитов

       
       
       Попытка

   
           Объект.Записать();

       Исключение
         
Сообщить(ОписаниеОшибки());
       КонецПопытки;
ОтменитьТранзакцию();
   КонецЦикла;
29 Maxus43
 
16.07.13
12:31
(28) + и потом, если ошибок нет, то можно записать все.
Будет как бы двойная попытка записи в ИБ, первая для отлова ошибок, вторая - собственно запись
30 ИС-2
 
naïve
18.07.13
07:17
(28) тоже ругается. Вылатает несколько "В этой транзакции уже происходили ошибки" и аварийная ошибка
31 Славен
 
18.07.13
07:27
Никак, с такой постановкой
32 1Сергей
 
18.07.13
07:32
Пиши свою процедуру проверки объекта на наличие ошибок
33 Славен
 
18.07.13
07:32
если только не хранить список изменний для каждого объекта отдельно и откатывать назад не отменой транзакции,  а обратной записью измененных реквизитов
34 Славен
 
18.07.13
07:33
(32)+1, можно и так
Выдавать глобальные идеи — это удовольствие; искать сволочные маленькие ошибки — вот настоящая работа. Фредерик Брукс-младший