Как исправить ошибку «Операция не может быть выполнена из-за несоответствия версии» при заполнении доп. реквизитов в КД 2.0?

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

При перегрузке данных между конфигурациями 1С с помощью правил «Конвертации данных 2.0» (КД 2.0) разработчики часто сталкиваются со следующей проблемой: при попытке заполнить дополнительные реквизиты объекта в обработчике «После загрузки» вылетает ошибка вида «Операция не может быть выполнена из-за несоответствия версии или отсутствия записи базы данных».

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

Выясним причину ошибки

Проанализируем механики работы Конвертации данных и Библиотеки Стандартных Подсистем (БСП):

  1. Обработчик «После загрузки» в правилах конвертации объектов (ПКО) выполняется до того, как новый объект физически записывается в базу данных. В этот момент у элемента ещё нет сохранённой ссылки в БД.
  2. Если в этом обработчике вызывается процедура БСП УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(Объект.Ссылка, ТЗ_Доп), она пытается прочитать объект из базы данных по его ссылке. Так как объект ещё не создан в БД, вызов завершается ошибкой.
  3. Если попытаться решить проблему «в лоб» и вызвать перед процедурой БСП принудительный метод Объект.Записать(), то при завершении алгоритма загрузки сама КД 2.0 попытается повторно записать этот же объект. В результате возникает конфликт версий (оптимистическая блокировка): версия объекта в памяти становится неактуальной по отношению к уже записанной версии в базе данных.

Способ 1. Прямое заполнение табличной части «ДополнительныеРеквизиты» (Рекомендуемый подход)

В конфигурациях на базе БСП (1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей) дополнительные реквизиты хранятся непосредственно в табличной части ДополнительныеРеквизиты самого справочника или документа. Поэтому для их заполнения вовсе не требуется вызывать методы сервисной записи БСП или принудительно сохранять объект.

Достаточно заполнить строки табличной части напрямую в обработчике «После загрузки». Механизм КД 2.0 сам зафиксирует изменения и запишет объект вместе со всеми доп. реквизитами за одну транзакцию.

Рассмотрим пример правильного кода в обработчике «После загрузки»:


// Заполнение основного направления деятельности
Если ПараметрыОбъекта["НаправлениеДеятельности"] <> Неопределено И НЕ ПустаяСтрока(ПараметрыОбъекта["НаправлениеДеятельности"]) Тогда 
    Объект.НаправлениеДеятельности = Справочники.НаправленияДеятельности.НайтиПоНаименованию(ПараметрыОбъекта["НаправлениеДеятельности"]);
Иначе    
    Объект.НаправлениеДеятельности = Справочники.НаправленияДеятельности.ПустаяСсылка();
КонецЕсли;

Объект.ПорядокРасчетов = Перечисления.ПорядокРасчетов.ПоДоговорамКонтрагентов;
Объект.Статус = Перечисления.СтатусыДоговоровКонтрагентов.Действует;

// Заполнение дополнительного реквизита "НомерДоговораКонтрагента"
ДопРеквизитНомер = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("НомерДоговораКонтрагента");
Если ЗначениеЗаполнено(ДопРеквизитНомер) И ПараметрыОбъекта["НомерДоговора"] <> Неопределено Тогда
    НайденныеСтроки = Объект.ДополнительныеРеквизиты.НайтиСтроки(Новый Структура("Свойство", ДопРеквизитНомер));
    Если НайденныеСтроки.Количество() = 0 Тогда
        СтрокаТЧ = Объект.ДополнительныеРеквизиты.Добавить();
        СтрокаТЧ.Свойство = ДопРеквизитНомер;
    Иначе
        СтрокаТЧ = НайденныеСтроки[0];
    КонецЕсли;
    
    СтрокаТЧ.Значение = ПараметрыОбъекта["НомерДоговора"];
КонецЕсли;

// Заполнение дополнительного реквизита "ОсновнойПроект"
ДопРеквизитПроект = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ОсновнойПроект");
Если ЗначениеЗаполнено(ДопРеквизитПроект) И ПараметрыОбъекта["ПроектКод"] <> Неопределено Тогда
    НайденныеСтроки = Объект.ДополнительныеРеквизиты.НайтиСтроки(Новый Структура("Свойство", ДопРеквизитПроект));
    Если НайденныеСтроки.Количество() = 0 Тогда
        СтрокаТЧ = Объект.ДополнительныеРеквизиты.Добавить();
        СтрокаТЧ.Свойство = ДопРеквизитПроект;
    Иначе
        СтрокаТЧ = НайденныеСтроки[0];
    КонецЕсли;
    
    СтрокаТЧ.Значение = Справочники.Проекты.НайтиПоКоду(СокрЛП(ПараметрыОбъекта["ПроектКод"]));
КонецЕсли;

Способ 2. Перенос кода в обработчик «После записи»

Если специфика логики требует вызова сервисных процедур БСП (например, УправлениеСвойствами.ЗаписатьСвойстваУОбъекта), перенесите этот код из обработчика «После загрузки» в обработчик «После записи».

В момент вызова события «После записи» ссылка Объект.Ссылка уже физически существует в базе данных, и повторная перезапись объекта через процедуры БСП пройдут без ошибки несоответствия версии.

Важное различие: Дополнительные реквизиты и Дополнительные сведения

При работе со свойствами БСП важно различать два понятия:

  1. Дополнительные реквизиты: хранятся в табличной части самого объекта (Объект.ДополнительныеРеквизиты). Заполняются в событии «После загрузки» через прямую работу с ТЧ.
  2. Дополнительные сведения: хранятся отдельно от объекта в независимом регистре сведений ДополнительныеСведения. Их запись должна выполняться исключительно в событии «После записи», когда у объекта уже есть валидная ссылка в БД.
← На главную