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