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