Почему не работает УстановитьСсылкуНового в 1С и как это исправить

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

При разработке бизнес-логики в 1С часто возникает задача сохранить связь между новым элементом и объектом-источником (например, при копировании). Начинающие разработчики пытаясь получить ссылку на еще не записанный объект, вызывают метод УстановитьСсылкуНового() и пытаются сразу записать связанные данные в регистр сведений. Однако после сохранения элемента оказывается, что ссылка в базе данных отличается или вызов не приносит ожидаемого результата.

Рассмотрим, почему возникает эта проблема, проанализируем ошибки в коде и разберем правильные архитектурные подходы 1С.

Анализ исходной проблемы и типичного ошибочного кода

Проанализируем пример кода, в котором разработчик пытается при копировании соглашения с поставщиком зафиксировать ссылку на исходный объект в регистре сведений:


Процедура ПриКопировании(ОбъектКопирования)
    Статус = Перечисления.СтатусыСоглашенийСПоставщиками.НеСогласовано;
    Согласован = Ложь;
    ДатаНачалаДействия = '00010101';
    ДатаОкончанияДействия = '00010101';
    ИнициализироватьСправочник(Ложь);
    
    УстановитьСсылкуНового(Справочники.СоглашенияСПоставщиками.ПолучитьСсылку(Новый УникальныйИдентификатор));    
    НоваяЗапись = РегистрыСведений.ДополнительныеСведения.СоздатьМенеджерЗаписи();
    НоваяЗапись.Объект = ПолучитьСсылкуНового();
    НоваяЗапись.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ПредыдущееСоглашение");
    НоваяЗапись.Значение = ОбъектКопирования.Ссылка.УникальныйИдентификатор();
    НоваяЗапись.Записать();
КонецПроцедуры

При таком подходе возникают две ключевые проблемы:

  1. Особенность управляемых форм: При открытии управляемой формы объект платформы преобразуется в реквизит формы с типом ДанныеФормыСтруктура. Ссылка, сформированная с помощью УстановитьСсылкуНового() в обработчике модуля объекта, теряется при выгрузке в форму. При последующем нажатии кнопки «Записать» форма снова преобразует данные в объект, и платформа генерирует совершенно новый идентификатор ссылки.
  2. Опасность битых ссылок в регистре: Если создать запись в регистре сведений до фактической записи самого элемента, а пользователь затем закроет форму без сохранения, в базе данных останется «мусорная» запись регистра, указывающая на несуществующий элемент с представлением <Объект не найден>.

Решение 1: Использование параметров управляемой формы

В управляемом приложении нет необходимости вручную генерировать ссылку для нового объекта, чтобы узнать исходный элемент. Платформа 1С автоматически передает объект копирования в параметры формы под именем ЗначениеКопирования.

Выясним, как правильно получить эту ссылку на сервере в форме элемента:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Ключ.Пустая() И ЗначениеЗаполнено(Параметры.ЗначениеКопирования) Тогда
        // Получаем ссылку на объект, из которого выполняется копирование
        СсылкаНаИсточник = Параметры.ЗначениеКопирования;
        
        // Сохраняем ссылку во временный реквизит формы или структуры для дальнейшей обработки
        Объект.ДополнительныеСвойства.Вставить("ИсточникКопирования", СсылкаНаИсточник);
    КонецЕсли;
    
КонецПроцедуры

Благодаря этому подходу нет необходимости вызывать УстановитьСсылкуНового() при инициализации. Ссылка на копируемый объект уже доступна в параметрах формы.

Решение 2: Запись зависимых данных в событии ПриЗаписи или ПередЗаписьюНаСервере

Запись в подчиненные регистры сведений должна выполняться строго в момент или после транзакции записи основного объекта, когда элемент гарантированно существует в базе данных.

Рассмотрим по шагам правильную схему работы:

  1. В обработчике ПередЗаписьюНаСервере формы или в обработчике ПередЗаписью модуля объекта вызываем метод УстановитьСсылкуНового(), если требуется принудительно задать конкретный УникальныйИдентификатор.
  2. Формирование записей независимых регистров сведений переносим в событие ПриЗаписи модуля объекта или в подписку на событие. В этот момент свойство Источник.Ссылка уже содержит действительную физическую ссылку.

Пример кода в модуле объекта для безопасной записи сведений:


Процедура ПриЗаписи(Отказ)
    
    Если ЭтоНовый() Или ДополнительныеСвойства.Свойство("ПредыдущееСоглашение") Тогда
        ЗаписьРС = РегистрыСведений.ДополнительныеСведения.СоздатьМенеджерЗаписи();
        ЗаписьРС.Объект = Ссылка; // Здесь Ссылка гарантированно валидна
        ЗаписьРС.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ПредыдущееСоглашение");
        ЗаписьРС.Значение = ДополнительныеСвойства.ПредыдущееСоглашение;
        ЗаписьРС.Записать();
    КонецЕсли;
    
КонецПроцедуры

Подводим итоги

Метод УстановитьСсылкуНового() предназначен для программного формирования объектов в серверных процедурах без участия форм или непосредственно в момент сохранения (в ПередЗаписьюНаСервере / ПередЗаписью). Не следует записывать данные в регистры до момента физического сохранения основного объекта, а для получения источника копирования в управляемых формах следует использовать стандартный параметр Параметры.ЗначениеКопирования.

← На главную