Как через COM-соединение получить, изменить и записать объект справочника в удаленной базе 1С?

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

При организации интеграции между информационными базами 1С нередко возникает задача односторонней выгрузки данных, когда в целевую конфигурацию нельзя вносить доработки (например, база находится на типовой поддержке или доступ к ней ограничен). В таких сценариях часто применяют прямое подключение через V83.COMConnector. Однако при попытке найти существующий элемент и получить объект для редактирования разработчики часто сталкиваются с ошибками вида «Метод объекта не обнаружен» или исключениями при выборке данных. Разберем детально, как устроена объектная модель при работе через COM и как правильно изменять и создавать элементы.

Анализ причин ошибок при получении объекта через COM

Выясним, почему стандартные попытки вызова методов менеджера или корня соединения приводят к ошибкам в коде:

  1. Попытка вызова метода у менеджера справочника: конструкции вида Соединение.Справочники.ФизическиеЛица.GetObject(...) или Соединение.ПолучитьОбъект(...) завершаются ошибкой «Метод объекта не обнаружен». У менеджера справочника в платформе 1С:Предприятие нет метода ПолучитьОбъект(). Этот метод доступен только у объекта ссылки (СправочникСсылка) или выборки.
  2. Использование выборки с отбором по ссылке: попытка отфильтровать выборку через Выбрать(,, СтруктураОтбора) с ключом "Ссылка" или "Ref" вызывает ошибку «Недопустимое значение параметра». Метод Выбрать() у менеджеров справочников поддерживает отбор только по полям "Код", "Наименование", "Родитель", "Владелец" или по реквизитам, для которых в метаданных включено свойство индексирования.
  3. Ошибочное обращение к результату запроса: в коде часто пытаются получить значение колонки напрямую из объекта РезультатЗапроса (например, РезультатЗапроса.Ссылка). Это приводит к ошибке «Поле объекта не обнаружено», так как сначала необходимо спозиционировать выборку через Выбрать() и вызвать Следующий() либо применить метод Выгрузить().

Правильный способ получения и изменения объекта по ссылке

Рассмотрим базовый сценарий: в удаленной базе ссылка уже найдена (например, стандартным методом поиска по реквизиту). Чтобы получить возможность изменять ее данные, необходимо вызвать метод ПолучитьОбъект() непосредственно у полученной внешней ссылки:


// Поиск элемента в удаленной базе по реквизиту
КонтрагентСсылкаВнеш = Соединение.Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ИННПоиска);

Если ЗначениеЗаполнено(КонтрагентСсылкаВнеш) Тогда
    // Получаем объект справочника удаленной базы
    КонтрагентОбъектВнеш = КонтрагентСсылкаВнеш.ПолучитьОбъект();
    
    // Модифицируем необходимые реквизиты
    КонтрагентОбъектВнеш.ИндивидуальныйПредприниматель = Истина;
    КонтрагентОбъектВнеш.НаименованиеПолное = "ИП Иванов Иван Иванович";
    
    // Записываем изменения в удаленной базе
    КонтрагентОбъектВнеш.Записать();
КонецЕсли;

Синхронизация элементов по уникальному идентификатору (UUID)

Когда требуется обеспечить строгое соответствие элементов между базами без дублирования, оптимально выполнять сопоставление по УникальныйИдентификатор. Метод Справочники.<Имя>.ПолучитьСсылку(УИД) генерирует ссылку на основе переданного идентификатора даже в том случае, если самого элемента в базе еще физически нет.

Посмотрим на алгоритм: мы вычисляем ссылку по УИД, проверяем факт существования элемента с помощью ПолучитьОбъект() и в зависимости от результата либо редактируем его, либо создаем новый с тем же самым идентификатором.


// Получаем строковое представление УИД из базы-источника
СтрокаУИД = Строка(СсылкаИсточник.УникальныйИдентификатор());

// Воссоздаем объект УникальныйИдентификатор в контексте базы-приемника
УИДНаПолучателе = Соединение.NewObject("УникальныйИдентификатор", СтрокаУИД);

// Формируем ссылку в удаленной базе
СсылкаНаПолучателе = Соединение.Справочники.ФизическиеЛица.ПолучитьСсылку(УИДНаПолучателе);

// Проверяем наличие объекта в удаленной информационной базе
ОбъектНаПолучателе = СсылкаНаПолучателе.ПолучитьОбъект();

Если ОбъектНаПолучателе = Неопределено Тогда
    // Элемент отсутствует — создаем новый объект
    ОбъектНаПолучателе = Соединение.Справочники.ФизическиеЛица.СоздатьЭлемент();
    
    // Жестко привязываем заранее рассчитанную ссылку для сохранения одинакового УИД
    ОбъектНаПолучателе.УстановитьСсылкуНового(СсылкаНаПолучателе);
КонецЕсли;

// Заполняем реквизиты объекта
ОбъектНаПолучателе.Наименование = СсылкаИсточник.Наименование;

// Отключаем платформенные и прикладные проверки удаленной конфигурации
ОбъектНаПолучателе.ОбменДанными.Загрузка = Истина;

// Фиксируем запись в транзакции удаленной базы
Попытка
    ОбъектНаПолучателе.Записать();
Исключение
    ОписаниеОшибки = ОписаниеОшибки();
    // Обработка исключительной ситуации при блокировках или ошибках записи
КонецПопытки;

Важные нюансы и рекомендации при разработке через COM

Проанализируем технические особенности, которые необходимо учитывать при промышленной эксплуатации COM-обмена:

  1. Использование режима загрузки данных: свойство ОбменДанными.Загрузка = Истина является критически важным при записи в неизменяемую удаленную базу. Оно отключает выполнение тяжелых проверок в обработчиках событий ПередЗаписью и ПриЗаписи модуля объекта, позволяя избежать сбоев из-за незаполненных второстепенных реквизитов.
  2. Обработка исключений: вызов метода Записать() через COM неявно инициирует транзакцию в удаленной базе. Все операции модификации объектов следует обязательно помещать в конструкцию Попытка ... Исключение, так как любая блокировка таблицы базой данных приведет к падению текущего сеанса.
  3. Разрядность компонентов: компонент V83.COMConnector чувствителен к битности операционной системы и сервера 1С. Если вызов выполняется из 64-разрядного процесса сервера, а библиотека зарегистрирована как 32-битная, подключение завершится системным сбоем. Для корректной работы требуется настройка компонента через Службы компонентов (DCOM / dllhost).
  4. Освобождение памяти и лицензий: каждое активное соединение удерживает клиентскую лицензию удаленной базы и накапливает кэш сеанса. После завершения сеанса передачи данных необходимо обязательно очищать переменную: Соединение = Неопределено;.
← На главную