Разработчики 1С часто сталкиваются с ситуацией, когда необходимо програмно изменить ресурсы или реквизиты независимого непериодического регистра сведений. Однако неверное размещение кода или некорректная отладка регламентных заданий могут привести к аварийному завершению работы платформы и сетевым ошибкам соединения.
В этой статье мы разберем причины возникновения критических ошибок при записи регистра, рассмотрим правильную методику обновления данных и научимся отлаживать регламентные задания.
Рассмотрим распространенную ошибку, возникающую при попытке обновить данные прямо из модуля набора записей регистра сведений. Предположим, в событии ПередЗаписью модуля набора записей размещен следующий код:
Процедура ПередЗаписью(Отказ, Замещение)
НаборЗаписей = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ПодразделениеОрганизации.Установить(Справочники.Организации.НайтиПоКоду("1111"));
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.ПодразделениеОрганизации = Справочники.Организации.НайтиПоКоду("1111");
НоваяЗапись.ДатаРедактирования = ТекущаяДата();
НаборЗаписей.Записать();
КонецПроцедуры
Проанализируем, что происходит при вызове этого кода:
ПередЗаписью.Записать().Записать() снова генерирует событие ПередЗаписью для нового набора.В результате образуется бесконечная рекурсия. Память стека вызовов мгновенно заполняется, и рабочая служба сервера 1С (процесс rphost) принудительно разрывает соединение с клиентом. На стороне пользователя это выглядит как сетевая ошибка сокетов 10054 (0x00002746).
Главное правило: никогда не вызывайте метод Записать() для объекта того же типа внутри обработчиков событий записи (ПередЗаписью, ПриЗаписи) этого же объекта без явного условия выхода из рекурсии. Если требуется модифицировать записываемые данные в момент сохранения, нужно работать напрямую с текущим набором через контекст ЭтотОбъект.
Выясним, как корректно обновить значения ресурсов во всем регистре сведений или по определенному отбору. Логика перезаписи зависит от того, где и когда должна выполняться операция.
Если задача заключается в периодическом обновлении данных по расписанию (например, раз в день или каждый час), весь программный код должен располагаться в общем модуле, а не в модуле регистра.
Рассмотрим пошаговый алгоритм считывания и обновления данных через набор записей:
СоздатьНаборЗаписей().Отбор.Прочитать(), чтобы загрузить существующие записи из базы данных.Записать().Посмотрим на пример правильной реализации процедур обновления в общем модуле:
// Процедура размещается в Общем Модуле со свойствами "Сервер" и "Вызов сервера"
Процедура ОбновитьРесурсРегистра() Экспорт
// 1. Создаем набор записей
НаборЗаписей = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
// 2. Устанавливаем отбор по нужному измерению
ОрганизацияСсылка = Справочники.Организации.НайтиПоКоду("1111");
Если ЗначениеЗаполнено(ОрганизацияСсылка) Тогда
НаборЗаписей.Отбор.ПодразделениеОрганизации.Установить(ОрганизацияСсылка);
КонецЕсли;
// 3. Считываем текущие записи из базы
НаборЗаписей.Прочитать();
// 4. Модифицируем ресурсы
Для Каждого Запись Из НаборЗаписей Цикл
Запись.ДатаРедактирования = ТекущаяДата();
КонецЦикла;
// 5. Записываем обновленный набор (Замещение = Истина по умолчанию)
НаборЗаписей.Записать();
КонецПроцедуры
После написания процедуры в общем модуле ее необходимо подключить к регламентному заданию. Разберем особенности запуска и отладки фоновых процессов.
Часто разработчики сталкиваются с проблемой: расписание регламентного задания настроено, но точка останова в коде не срабатывает. Разберем основные причины и способы их устранения:
Экспорт).ragent на сервере 1С должна быть запущена с ключом -debug, иначе точки останова на стороне сервера срабатывать не будут.Рекомендация по тестированию: Чтобы убедиться в корректности работы кода, перед окончательным включением регламентного задания отладку рекомендуется проводить путем прямого вызова процедуры из внешней обработки или из формы через запуск в обычном сеансе.