При организации интеграции между информационными базами 1С нередко возникает задача односторонней выгрузки данных, когда в целевую конфигурацию нельзя вносить доработки (например, база находится на типовой поддержке или доступ к ней ограничен). В таких сценариях часто применяют прямое подключение через V83.COMConnector. Однако при попытке найти существующий элемент и получить объект для редактирования разработчики часто сталкиваются с ошибками вида «Метод объекта не обнаружен» или исключениями при выборке данных. Разберем детально, как устроена объектная модель при работе через COM и как правильно изменять и создавать элементы.
Выясним, почему стандартные попытки вызова методов менеджера или корня соединения приводят к ошибкам в коде:
Соединение.Справочники.ФизическиеЛица.GetObject(...) или Соединение.ПолучитьОбъект(...) завершаются ошибкой «Метод объекта не обнаружен». У менеджера справочника в платформе 1С:Предприятие нет метода ПолучитьОбъект(). Этот метод доступен только у объекта ссылки (СправочникСсылка) или выборки.Выбрать(,, СтруктураОтбора) с ключом "Ссылка" или "Ref" вызывает ошибку «Недопустимое значение параметра». Метод Выбрать() у менеджеров справочников поддерживает отбор только по полям "Код", "Наименование", "Родитель", "Владелец" или по реквизитам, для которых в метаданных включено свойство индексирования.РезультатЗапроса (например, РезультатЗапроса.Ссылка). Это приводит к ошибке «Поле объекта не обнаружено», так как сначала необходимо спозиционировать выборку через Выбрать() и вызвать Следующий() либо применить метод Выгрузить().Рассмотрим базовый сценарий: в удаленной базе ссылка уже найдена (например, стандартным методом поиска по реквизиту). Чтобы получить возможность изменять ее данные, необходимо вызвать метод ПолучитьОбъект() непосредственно у полученной внешней ссылки:
// Поиск элемента в удаленной базе по реквизиту
КонтрагентСсылкаВнеш = Соединение.Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ИННПоиска);
Если ЗначениеЗаполнено(КонтрагентСсылкаВнеш) Тогда
// Получаем объект справочника удаленной базы
КонтрагентОбъектВнеш = КонтрагентСсылкаВнеш.ПолучитьОбъект();
// Модифицируем необходимые реквизиты
КонтрагентОбъектВнеш.ИндивидуальныйПредприниматель = Истина;
КонтрагентОбъектВнеш.НаименованиеПолное = "ИП Иванов Иван Иванович";
// Записываем изменения в удаленной базе
КонтрагентОбъектВнеш.Записать();
КонецЕсли;
Когда требуется обеспечить строгое соответствие элементов между базами без дублирования, оптимально выполнять сопоставление по УникальныйИдентификатор. Метод Справочники.<Имя>.ПолучитьСсылку(УИД) генерирует ссылку на основе переданного идентификатора даже в том случае, если самого элемента в базе еще физически нет.
Посмотрим на алгоритм: мы вычисляем ссылку по УИД, проверяем факт существования элемента с помощью ПолучитьОбъект() и в зависимости от результата либо редактируем его, либо создаем новый с тем же самым идентификатором.
// Получаем строковое представление УИД из базы-источника
СтрокаУИД = Строка(СсылкаИсточник.УникальныйИдентификатор());
// Воссоздаем объект УникальныйИдентификатор в контексте базы-приемника
УИДНаПолучателе = Соединение.NewObject("УникальныйИдентификатор", СтрокаУИД);
// Формируем ссылку в удаленной базе
СсылкаНаПолучателе = Соединение.Справочники.ФизическиеЛица.ПолучитьСсылку(УИДНаПолучателе);
// Проверяем наличие объекта в удаленной информационной базе
ОбъектНаПолучателе = СсылкаНаПолучателе.ПолучитьОбъект();
Если ОбъектНаПолучателе = Неопределено Тогда
// Элемент отсутствует — создаем новый объект
ОбъектНаПолучателе = Соединение.Справочники.ФизическиеЛица.СоздатьЭлемент();
// Жестко привязываем заранее рассчитанную ссылку для сохранения одинакового УИД
ОбъектНаПолучателе.УстановитьСсылкуНового(СсылкаНаПолучателе);
КонецЕсли;
// Заполняем реквизиты объекта
ОбъектНаПолучателе.Наименование = СсылкаИсточник.Наименование;
// Отключаем платформенные и прикладные проверки удаленной конфигурации
ОбъектНаПолучателе.ОбменДанными.Загрузка = Истина;
// Фиксируем запись в транзакции удаленной базы
Попытка
ОбъектНаПолучателе.Записать();
Исключение
ОписаниеОшибки = ОписаниеОшибки();
// Обработка исключительной ситуации при блокировках или ошибках записи
КонецПопытки;
Проанализируем технические особенности, которые необходимо учитывать при промышленной эксплуатации COM-обмена:
ОбменДанными.Загрузка = Истина является критически важным при записи в неизменяемую удаленную базу. Оно отключает выполнение тяжелых проверок в обработчиках событий ПередЗаписью и ПриЗаписи модуля объекта, позволяя избежать сбоев из-за незаполненных второстепенных реквизитов.Записать() через COM неявно инициирует транзакцию в удаленной базе. Все операции модификации объектов следует обязательно помещать в конструкцию Попытка ... Исключение, так как любая блокировка таблицы базой данных приведет к падению текущего сеанса.V83.COMConnector чувствителен к битности операционной системы и сервера 1С. Если вызов выполняется из 64-разрядного процесса сервера, а библиотека зарегистрирована как 32-битная, подключение завершится системным сбоем. Для корректной работы требуется настройка компонента через Службы компонентов (DCOM / dllhost).Соединение = Неопределено;.