21.11.2011, 11:20 | #1 |
Участник
|
Доброго времени суток!
Я вот столкнулся с задачей, решение которой мне не приходит на ум. Может его и вовсе нет, но я надеюсь что это не так. Суть: идёт импорт данных, во время импорта естественно идут всяческие проверки и если что не так, то вываливаемся в ERROR. По ходу импорта ведётся его лог, куда, чего, откуда и на какой стадии. В этот же лог хотелось бы записать и ошибку, если таковая произойдёт. Вот тут и вопрос: как это сделать? Ведь ERROR отменяет все действия, поэтому то что я запишу в таблицу лога тоже будет отменено. |
|
21.11.2011, 11:27 | #2 |
Участник
|
Пиши в текстовой файл или COMMIT таблицы лога.
__________________
Want to believe... |
|
21.11.2011, 11:39 | #3 |
Участник
|
Писать в текстовый файл, об этом я думал, но когда я скину данные из файла в лог? А мне эти данные по зарез нужны в логе. Причём лог мне нужен актуальный. В общем через текстовый файл, это конечно решение, но очень уж корявое. А вот про COMMIT таблицы лога, можно по подробней, разве COMMIT не всю БД коммитит?
|
|
21.11.2011, 13:22 | #4 |
Участник
|
Все Errors (в смысле все ситуации кот. вызывают Error)вынести в отдельный CU50xxx. Использовать if CU50xxx.run Then...
Else WriteLogFile(,,,GETLASTERRORTEXT,..) |
|
21.11.2011, 13:38 | #5 |
Участник
|
Занимаюсь сейчас похожей задачей. Все изменения в базу заношу только после всех проверок, это позволяет не порождать Error, для отмены транзакции. Все Error'ы заменил на message.
Правда, если что-то не штатное, то систему не поборешь. |
|
21.11.2011, 13:50 | #6 |
Участник
|
|
|
21.11.2011, 14:22 | #7 |
Участник
|
Да транзакция откатится, но в LogFile все можно отобразить.
Test1. => WriteLogfile(1), Test2, => WriteLogfile(2),... Commit; If CU50xxx then.. else WriteLogFile(3); |
|
21.11.2011, 14:53 | #8 |
Участник
|
Если начать транзакцию до запуска кодеюнита в примере от zma, то в случае вызова ERROR выскочит ошибка выполнения (во время транзакции нельзя использовать CU.RUN с возвращаемым значением отличным от Ok). Т.е. надо попробовать переписать код так, что бы транзакция стартовала в случае удачного выполнения кодеюнита (IF CU50xx.RUN THEN). Это было бы не проблемой, если бы проверка была всего одна. Но если у меня десятки проверок, причём вложенных... И всё это уже написано и работает, тут я уже боюсь браться за подобную реализацию, лучше уж через файлы...
Пока писал, придумал что можно сделать. Фактически это вариация на тему того, что предложил InTacto. Пока разбираем входящие данные, пишем всё во временные таблицы (кроме Лога). При этом после каждой записи в Лог (или перед потенциальными вызовами ERROR) делаем COMMIT. Ну и в самом конце, сливаем данные из временных таблиц в обычные. В итоге у нас и ERROR нормально отработает и Лог запишется и данные никуда не попадут, если встретится хотя бы один ERROR. Или ещё красивее. Делаем функцию LogError, которую вызываем вместо ERROR, в ней пишем в Лог всё что нужно, потом COMMIT, а потом ERROR. Теперь у нас COMMIT вызовется только перед ERROR, а не перед каждым потенциальным ERROR или после каждой записи в Лог. |
|
21.11.2011, 16:02 | #9 |
Участник
|
Цитата:
Сообщение от Predatore
В том то и засада, что транзакция не отменится, если быть ещё точнее, то если начать транзакцию до запуска кодеюнита, то в случае вызова ERROR выскочит ошибка выполнения (во время транзакции нельзя использовать CU.RUN с возвращаемым значением отличным от Ok). Т.е. надо попробовать переписать код так, что бы транзакция стартовала в случае удачного выполнения кодеюнита (IF CU50xx.RUN THEN). Это было бы не проблемой, если бы проверка была всего одна. Но если у меня десятки проверок, причём вложенных... тут я уже даже боюсь браться за подобную реализацию, лучше уж через файлы...
Пока писал, придумал что можно сделать. Фактически это вариация на тему того, что предложил InTacto. Пока разбираем входящие данные, пишем всё во временные таблицы (кроме Лога). При этом после каждой записи в Лог (или перед потенциальными вызовами ERROR) делаем COMMIT. Ну и в самом конце, сливаем данные из временных таблиц в обычные. В итоге у нас и ERROR нормально отработает и Лог запишется и данные никуда не попадут, если встретится хотя бы один ERROR. Код: CLEARLASTERROR; textLoc := ''; COMMIT; IF Codeunit5xxx.RUN() THEN; textLoc := COPYSTR(GETLASTERRORTEXT,1,MAXSTRLEN(textLoc)); if textLoc <> '' THEN BEGIN WriteLog(textLoc); END; |
|
21.11.2011, 16:34 | #10 |
Участник
|
Цитата:
Сообщение от AlexB
Цитата:
Сообщение от Predatore
В том то и засада, что транзакция не отменится, если быть ещё точнее, то если начать транзакцию до запуска кодеюнита, то в случае вызова ERROR выскочит ошибка выполнения (во время транзакции нельзя использовать CU.RUN с возвращаемым значением отличным от Ok). Т.е. надо попробовать переписать код так, что бы транзакция стартовала в случае удачного выполнения кодеюнита (IF CU50xx.RUN THEN). Это было бы не проблемой, если бы проверка была всего одна. Но если у меня десятки проверок, причём вложенных... тут я уже даже боюсь браться за подобную реализацию, лучше уж через файлы...
Пока писал, придумал что можно сделать. Фактически это вариация на тему того, что предложил InTacto. Пока разбираем входящие данные, пишем всё во временные таблицы (кроме Лога). При этом после каждой записи в Лог (или перед потенциальными вызовами ERROR) делаем COMMIT. Ну и в самом конце, сливаем данные из временных таблиц в обычные. В итоге у нас и ERROR нормально отработает и Лог запишется и данные никуда не попадут, если встретится хотя бы один ERROR. Код: CLEARLASTERROR; textLoc := ''; COMMIT; IF Codeunit5xxx.RUN() THEN; textLoc := COPYSTR(GETLASTERRORTEXT,1,MAXSTRLEN(textLoc)); if textLoc <> '' THEN BEGIN WriteLog(textLoc); END; |
|
22.11.2011, 07:58 | #11 |
Участник
|
Данные во временных таблицах не удаляются при откате транзакций. Создайте Single Instance кодеюнит и пишите лог во временную таблицу.
В базу буфер временной таблицы можно сбрасывать либо по событию (инициализация нового лог-батча к примеру) или по выходу юзера из Нава. |
|