При разработке механизмов автоматизации в 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда объект (например, группа номенклатуры) успешно создается в коде, его можно увидеть при отладке, он даже фиксируется в Журнале регистрации, но после завершения работы алгоритма объект бесследно исчезает. Вместо него в системе остаются лишь «битые» ссылки вида <Объект не найден>. Рассмотрим подробно, почему так происходит, проанализируем внутренние механизмы платформы и разберем правильный подход к программному созданию элементов в сложных конфигурациях, таких как 1С:Комплексная автоматизация 2.5 или 1С:ERP.
Представим ситуацию: мы пишем обработку для загрузки структуры каталога номенклатуры. Код выглядит логично, используется метод СоздатьГруппу(), заполняются реквизиты, вызывается метод Записать(). В процессе выполнения мы видим сообщение в консоли: «Создана новая группа». Однако, открыв справочник в пользовательском интерфейсе, мы не обнаруживаем созданного элемента. Проверка Журнала регистрации подтверждает: событие «Добавление» было зафиксировано, указан GUID нового объекта, но при попытке перейти по ссылке мы получаем ошибку.
Проанализируем причину. Основная причина такого поведения — незавершенная транзакция. В платформе 1С работа с данными организована по принципу транзакционности. Если в коде был вызван метод НачатьТранзакцию(), все последующие изменения в базе данных (запись справочников, документов, регистров) носят предварительный характер. Физически данные попадают в таблицы СУБД, но они не будут «видны» другим сеансам и не станут постоянными до тех пор, пока не будет выполнен метод ЗафиксироватьТранзакцию().
Выясним, почему Журнал регистрации вводит в заблуждение. Журнал регистрации фиксирует факт обращения к объекту в момент вызова метода Записать(). Если после этого выполнение кода прерывается (например, из-за ошибки) или процедура просто завершается без явной фиксации открытой транзакции, платформа инициирует автоматический откат (Rollback). При откате записи из таблиц базы данных удаляются, но запись в Журнале регистрации, которая уже была сформирована, остается неизменной. В итоге мы имеем запись о создании объекта, которого фактически нет в базе.
Рассмотрим пример кода, который часто используется для подобных задач, и разберем его по шагам, выявляя слабые места:
Нов = Справочники.Номенклатура.НайтиПоКоду(Код);
Если НЕ нов.Пустая() Тогда
Продолжить;
Иначе
Нов = Справочники.Номенклатура.СоздатьГруппу();
Нов.Код = Код;
// В КА 2.5 важно заполнять служебные реквизиты
Нов.КодДляПоиска = СокрЛП(Число(Код));
Нов.Наименование = Наим;
// Поиск родительской группы
ННН = Справочники.Номенклатура.НайтиПоКоду(КодРодительскихПапок, Истина);
// ... логика поиска родителя ...
Нов.Родитель = ННН.Ссылка;
Попытка
Нов.Записать();
Сообщить("Создана новая группа: " + Нов.Наименование);
Исключение
Сообщить("Ошибка при создании: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
В приведенном коде на первый взгляд все верно. Однако, если эта логика вложена в другую процедуру, где ранее была вызвана функция НачатьТранзакцию(), и разработчик забыл закрыть её парой ЗафиксироватьТранзакцию(), то выполнение Нов.Записать() пройдет успешно, но результат не сохранится.
Проанализируем лучшие практики управления транзакциями. При написании сложных обработок загрузки данных рекомендуется придерживаться следующей структуры:
Попытка...Исключение для гарантированного завершения или отката.Посмотрим на пример безопасного блока записи:
НачатьТранзакцию();
Попытка
// Логика создания объекта
НовыйОбъект = Справочники.Номенклатура.СоздатьГруппу();
// Заполнение реквизитов...
НовыйОбъект.Записать();
ЗафиксироватьТранзакцию();
Сообщить("Данные успешно сохранены.");
Исключение
ОтменитьТранзакцию();
Сообщить("Произошла ошибка, изменения отменены: " + ОписаниеОшибки());
КонецПопытки;
Справочник Номенклатура в современных конфигурациях на базе подсистемы «Библиотека стандартных подсистем» (БСП) имеет свои особенности, которые нужно учитывать при программном создании элементов:
1. Реквизит КодДляПоиска. В конфигурации Комплексная автоматизация 2.5 этот реквизит используется для индексации и быстрого подбора. Если вы создаете элементы программно и не заполняете его (или заполняете некорректно), это может привести к проблемам при работе в формах списка. Рекомендуется дублировать в него очищенный от префиксов числовой код или использовать типовые методы конфигурации для генерации этого значения.
2. Режим ОбменДанными.Загрузка. При массовом создании групп номенклатуры крайне важно устанавливать свойство Нов.ОбменДанными.Загрузка = Истина. Это отключает «тяжелые» проверки в модуле объекта и модуле менеджера, а также предотвращает запуск дополнительных подписок на события, которые могут инициировать собственные транзакции или проверки прав доступа (RLS).
Рассмотрим, как это выглядит в коде:
НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
НоваяГруппа.ОбменДанными.Загрузка = Истина;
НоваяГруппа.Наименование = "Новая папка";
НоваяГруппа.Записать();
3. Иерархия. Убедитесь, что реквизит Родитель является ссылкой именно на группу (иерархия групп и элементов). В 1С:КА 2.5 справочник номенклатуры поддерживает иерархию групп, поэтому при программной установке родителя важно предварительно найти его и убедиться, что ссылка ЭтоГруппа = Истина.
Если вы столкнулись с проблемой исчезновения объектов, разберем шаги по диагностике:
НачатьТранзакцию во всем модуле или конфигурации. Проверьте, что на каждый вызов этого метода существует соответствующий вызов ЗафиксироватьТранзакцию или ОтменитьТранзакцию. Часто ошибка кроется в использовании условий (Если...Тогда), из-за которых код обходит строку фиксации.Если ТранзакцияАктивна() Тогда ВызватьИсключение "Транзакция не закрыта!"; КонецЕсли;. Это позволит моментально обнаружить проблему на этапе разработки.<Объект не найден>, хотя в базе он существует. Попробуйте проверить наличие объекта под пользователем с полными правами.Мы проанализировали ситуацию, когда программно созданная группа номенклатуры в 1С:КА 2.5 исчезает из базы. Основной причиной является незавершенная транзакция, которая откатывается платформой по завершении выполнения кода. Помните, что запись в Журнал регистрации не гарантирует физического сохранения данных в таблицах СУБД, если не была выполнена команда фиксации.
Для стабильной работы ваших алгоритмов всегда используйте явное управление транзакциями, устанавливайте флаг ОбменДанными.Загрузка = Истина для снижения нагрузки на систему и корректно заполняйте специфические реквизиты конфигурации, такие как КодДляПоиска. Такой подход гарантирует целостность данных и отсутствие «битых» ссылок в справочниках.