При разработке бизнес-логики в 1С часто возникает задача сохранить связь между новым элементом и объектом-источником (например, при копировании). Начинающие разработчики пытаясь получить ссылку на еще не записанный объект, вызывают метод УстановитьСсылкуНового() и пытаются сразу записать связанные данные в регистр сведений. Однако после сохранения элемента оказывается, что ссылка в базе данных отличается или вызов не приносит ожидаемого результата.
Рассмотрим, почему возникает эта проблема, проанализируем ошибки в коде и разберем правильные архитектурные подходы 1С.
Проанализируем пример кода, в котором разработчик пытается при копировании соглашения с поставщиком зафиксировать ссылку на исходный объект в регистре сведений:
Процедура ПриКопировании(ОбъектКопирования)
Статус = Перечисления.СтатусыСоглашенийСПоставщиками.НеСогласовано;
Согласован = Ложь;
ДатаНачалаДействия = '00010101';
ДатаОкончанияДействия = '00010101';
ИнициализироватьСправочник(Ложь);
УстановитьСсылкуНового(Справочники.СоглашенияСПоставщиками.ПолучитьСсылку(Новый УникальныйИдентификатор));
НоваяЗапись = РегистрыСведений.ДополнительныеСведения.СоздатьМенеджерЗаписи();
НоваяЗапись.Объект = ПолучитьСсылкуНового();
НоваяЗапись.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ПредыдущееСоглашение");
НоваяЗапись.Значение = ОбъектКопирования.Ссылка.УникальныйИдентификатор();
НоваяЗапись.Записать();
КонецПроцедуры
При таком подходе возникают две ключевые проблемы:
ДанныеФормыСтруктура. Ссылка, сформированная с помощью УстановитьСсылкуНового() в обработчике модуля объекта, теряется при выгрузке в форму. При последующем нажатии кнопки «Записать» форма снова преобразует данные в объект, и платформа генерирует совершенно новый идентификатор ссылки.В управляемом приложении нет необходимости вручную генерировать ссылку для нового объекта, чтобы узнать исходный элемент. Платформа 1С автоматически передает объект копирования в параметры формы под именем ЗначениеКопирования.
Выясним, как правильно получить эту ссылку на сервере в форме элемента:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Ключ.Пустая() И ЗначениеЗаполнено(Параметры.ЗначениеКопирования) Тогда
// Получаем ссылку на объект, из которого выполняется копирование
СсылкаНаИсточник = Параметры.ЗначениеКопирования;
// Сохраняем ссылку во временный реквизит формы или структуры для дальнейшей обработки
Объект.ДополнительныеСвойства.Вставить("ИсточникКопирования", СсылкаНаИсточник);
КонецЕсли;
КонецПроцедуры
Благодаря этому подходу нет необходимости вызывать УстановитьСсылкуНового() при инициализации. Ссылка на копируемый объект уже доступна в параметрах формы.
Запись в подчиненные регистры сведений должна выполняться строго в момент или после транзакции записи основного объекта, когда элемент гарантированно существует в базе данных.
Рассмотрим по шагам правильную схему работы:
ПередЗаписьюНаСервере формы или в обработчике ПередЗаписью модуля объекта вызываем метод УстановитьСсылкуНового(), если требуется принудительно задать конкретный УникальныйИдентификатор.ПриЗаписи модуля объекта или в подписку на событие. В этот момент свойство Источник.Ссылка уже содержит действительную физическую ссылку.Пример кода в модуле объекта для безопасной записи сведений:
Процедура ПриЗаписи(Отказ)
Если ЭтоНовый() Или ДополнительныеСвойства.Свойство("ПредыдущееСоглашение") Тогда
ЗаписьРС = РегистрыСведений.ДополнительныеСведения.СоздатьМенеджерЗаписи();
ЗаписьРС.Объект = Ссылка; // Здесь Ссылка гарантированно валидна
ЗаписьРС.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ПредыдущееСоглашение");
ЗаписьРС.Значение = ДополнительныеСвойства.ПредыдущееСоглашение;
ЗаписьРС.Записать();
КонецЕсли;
КонецПроцедуры
Метод УстановитьСсылкуНового() предназначен для программного формирования объектов в серверных процедурах без участия форм или непосредственно в момент сохранения (в ПередЗаписьюНаСервере / ПередЗаписью). Не следует записывать данные в регистры до момента физического сохранения основного объекта, а для получения источника копирования в управляемых формах следует использовать стандартный параметр Параметры.ЗначениеКопирования.