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