При интеграции конфигураций 1С через COM-соединение разработчики часто сталкиваются с ситуацией, когда прямое сравнение двух ссылок удаленной базы через стандартный оператор = возвращает Ложь, даже если обе переменные указывают на один и тот же элемент справочника или документ. Разберем природу такого поведения платформы, рассмотрим эффективные способы сравнения ссылочных данных и выясним, как оптимизировать быстродействие межпроцессных вызовов.
Проанализируем механизм передачи данных через COM-коннектор. При получении ссылки из удаленной базы (например, при обращении к реквизиту Банк.Родитель) платформа 1С возвращает в вызывающий сеанс не саму внутреннюю ссылку, а внешнюю COM-обертку — интерфейсный указатель IDispatch.
Когда мы пытаемся выполнить операцию:
Если Ссылка1 = Ссылка2 Тогда
// Условие никогда не выполнится
КонецЕсли;
Платформа сравнивает не логическую идентичность объектов базы данных 1С (их GUID или внутренние ссылки), а указатели на COM-объекты в оперативной памяти текущего процесса. Так как каждое обращение к свойству удаленного объекта порождает новый экземпляр интерфейсной обертки, их адреса в памяти различаются, и оператор равенства всегда возвращает Ложь.
Самый надежный и универсальный метод для сравнения любых типов данных (включая ссылки) — инициализация встроенного объекта СравнениеЗначений непосредственно в контексте удаленной базы.
Посмотрим на пример кода:
// Создаем объект сравнения один раз перед циклом
Сравнилка = БазаCOM.NewObject("СравнениеЗначений");
// Выполняем сравнение двух значений из базы COM
Результат = Сравнилка.Сравнить(Ссылка1ИзCOM, Ссылка2ИзCOM);
Если Результат = 0 Тогда
// Ссылки указывают на один и тот же объект
Сообщить("Ссылки совпадают");
Иначе
Сообщить("Ссылки различаются");
КонецЕсли;
Метод Сравнить() возвращает:
Важная рекомендация: создавайте объект БазаCOM.NewObject("СравнениеЗначений") один раз перед началом итераций, а не внутри цикла. Это позволит избежать лишних накладных расходов на инициализацию COM-объектов.
Если требуется сравнить две ссылки без создания дополнительных объектов сравнения, можно сопоставить их строковые представления GUID. Для исключения лишних обращений к таблицам базы данных используем системную функцию XMLСтрока на стороне COM-соединения.
Разберем пример:
ГУИД1 = БазаCOM.XMLСтрока(Ссылка1ИзCOM);
ГУИД2 = БазаCOM.XMLСтрока(Ссылка2ИзCOM);
Если ГУИД1 = ГУИД2 Тогда
// Объекты идентичны
КонецЕсли;
Функция XMLСтрока извлекает UUID ссылки напрямую, не выполняя неявного считывания реквизитов объекта из базы данных, что дает высокую скорость работы при точечных операциях.
Еще один рабочий способ — сравнение внутренней строковой сериализации платформы 1С с помощью функции ЗначениеВСтрокуВнутр.
Посмотрим, как выглядит реализация:
Если БазаCOM.ЗначениеВСтрокуВнутр(Ссылка1ИзCOM) = БазаCOM.ЗначениеВСтрокуВнутр(Ссылка2ИзCOM) Тогда
// Ссылки равны
КонецЕсли;
Данный вариант работает корректно, однако метод ЗначениеВСтрокуВнутр формирует длинную служебную строку с описанием типа метаданных, поэтому по быстродействию и лаконичности уступает объекту СравнениеЗначений и методу XMLСтрока.
Если в процессе обработки требуется сопоставить большой массив ссылок (например, проверить наличие ссылки в заранее подготовленном списке), наиболее производительным решением будет использование коллекции Соответствие внутри COM-сеанса.
Разберем по шагам:
ТаблицаСоответствий = БазаCOM.NewObject("Соответствие");
// Заполняем коллекцию в удаленной базе
ТаблицаСоответствий.Вставить(СсылкаCOM_А, Истина);
// Проверяем наличие элемента по ключу
Если ТаблицаСоответствий.Получить(СсылкаCOM_Б) <> Неопределено Тогда
// Ссылка найдена в коллекции
КонецЕсли;
Внутри удаленного сеанса платформа 1С рассчитывает внутренний хэш ссылки, благодаря чему поиск по ключу выполняется мгновенно и без поштучного вызова внешних функций сравнения.
При работе со ссылками через COM критически важно понимать особенности обращения к полям объектов:
Банк.Родитель) платформа 1С считывает из СУБД всю порцию данных объекта (все реквизиты шапки и табличные части) и помещает её в кэш ссылок удаленного сеанса. Последующие обращения к другим реквизитам этой же ссылки будут считываться уже из локального кэша сеанса COM.БазаCOM.NewObject("Запрос"), передайте параметры и выполните всю логику фильтрации и сопоставления на уровне сервера СУБД удаленной базы, получив в вызывающий код уже готовый результат.При проектировании обменов данными следует учитывать системные ограничения технологии COM:
comcntr.dll зарегистрирована в 32-битной среде (или наоборот), прямое подключение завершится системной ошибкой. Потребуется настройка промежуточного пула приложений COM+ (dllhost.exe), что снижает производительность.Для современных высоконагруженных интеграций рекомендуется заменять COM-соединения на межсерверные HTTP-сервисы, протокол OData (REST API) или пакетную выгрузку через XML/JSON, где сравнение и сопоставление данных выполняется по стандартным строковым идентификаторам UUID.