При разработке сложных механизмов в 1С программисты часто сталкиваются с необходимостью получить ссылку на документ еще до того, как он будет физически записан в базу данных. Типичный сценарий: создание нового документа, заполнение его данными и привязка к нему записей регистров или других объектов в рамках одной транзакции. Однако при использовании стандартного метода УстановитьСсылкуНового() многие замечают, что в отладчике свойство Ссылка объекта остается пустым. Разберемся, почему это происходит и как правильно работать с зарезервированными ссылками.
Выясним причину, по которой прямое обращение к свойству Ссылка не дает результата. В платформе 1С объект типа ДокументОбъект и его ссылка в базе данных — это разные сущности. Свойство Ссылка (Ref) заполняется платформой автоматически только в момент фактической фиксации записи в таблицах СУБД.
Когда мы вызываем метод УстановитьСсылкуНового(), мы не меняем текущее состояние свойства Ссылка. Мы лишь даем платформе команду: «Когда этот объект будет записываться, используй вот этот конкретный УникальныйИдентификатор (GUID)». До момента вызова Записать() ссылка считается «виртуальной».
Рассмотрим пример кода, который часто вызывает вопросы у разработчиков:
НовыйДокумент = Документы.ОперацияБух.СоздатьДокумент();
НоваяСсылка = Документы.ОперацияБух.ПолучитьСсылку(Новый УникальныйИдентификатор());
НовыйДокумент.УстановитьСсылкуНового(НоваяСсылка);
// В этой точке НовыйДокумент.Ссылка все еще будет пустой (00000000-0000-0000-0000-000000000000)
Важный момент: Для проверки того, какая ссылка была зарезервирована для объекта, необходимо использовать специальный метод ПолучитьСсылкуНового(). Проанализируем разницу: Ссылка — это то, что уже есть в базе, а ПолучитьСсылкуНового() — это то, что будет записано.
Разберем по шагам корректный алгоритм генерации и установки ссылки. Нам не обязательно использовать метаданные и менеджеры через общие модули, если тип документа известен заранее. Посмотрим на оптимизированный пример:
// 1. Создаем объект
ДокументОбъект = Документы.ОперацияБух.СоздатьДокумент();
// 2. Формируем будущую ссылку (можно передать свой GUID)
БудущаяСсылка = Документы.ОперацияБух.ПолучитьСсылку(Новый УникальныйИдентификатор);
// 3. Бронируем эту ссылку за объектом
ДокументОбъект.УстановитьСсылкуНового(БудущаяСсылка);
// 4. Проверяем. Внимание: смотрим НЕ Ссылка, а ПолучитьСсылкуНового()
ЗарезервированныйИдентификатор = ДокументОбъект.ПолучитьСсылкуНового();
Если ЗарезервированныйИдентификатор = БудущаяСсылка Тогда
Сообщить("Ссылка успешно забронирована!");
КонецЕсли;
Рассмотрим ситуацию, когда разработчик пытается записать набор записей регистра (например, РегистрБухгалтерии), используя в качестве регистратора ссылку, которая еще не существует в базе. Проанализируем последствия: на уровне СУБД существует контроль ссылочной целостности. Если вы попытаетесь вызвать НаборЗаписей.Записать(), где Регистратор — это незаписанный документ, система выдаст ошибку.
Однако существует легальный способ сделать это в рамках одной транзакции. Проанализируем последовательность действий:
НачатьТранзакцию().УстановитьСсылкуНового().ДокументОбъект.Записать(). Теперь ссылка физически существует в базе, но видна только внутри вашей транзакции.ЗафиксироватьТранзакцию().Если в процессе возникнет ошибка или пользователь передумает, ОтменитьТранзакцию() удалит и документ, и его движения из базы полностью.
Если ваша задача — открыть форму нового документа, который уже «знает» свою будущую ссылку, использование УстановитьСсылкуНового() на сервере перед открытием может не сработать напрямую, так как при вызове ОткрытьФорму() платформа создает новый экземпляр объекта.
Рассмотрим правильный подход для управляемого приложения: использование параметров заполнения. Вместо ручной манипуляции GUID-ами, лучше передать данные в структуру ЗначениеЗаполнения. Но если ссылка принципиально важна (например, для сложной интеграции), следует передавать её в параметрах формы и обрабатывать в событии ПриСозданииНаСервере на стороне формы документа, вызывая там УстановитьСсылкуНового() для основного реквизита Объект.
Подведем итоги нашего анализа:
Записать(). Это нормальное поведение платформы.ПолучитьСсылкуНового().ПолучитьСсылку() менеджера документа просто создает ссылку заданного типа с определенным GUID, но никак не связывает её с конкретным объектом документа, пока вы не вызовете УстановитьСсылкуНового().Использование предопределенных ссылок — мощный инструмент, но он требует четкого понимания жизненного цикла объекта 1С. Помните, что пока документ не записан, он существует только в оперативной памяти, и любые попытки «сослаться» на него из других таблиц базы данных без транзакции приведут к ошибкам целостности.