В практике интеграции систем на платформе 1С:Предприятие часто возникает необходимость связать legacy-системы (например, базы на платформе 1С 7.7) с современными конфигурациями на платформе 1С 8.3. Наиболее быстрым и производительным способом для этого является использование технологии OLE/COM через компонент V83.ComConnector.
Однако при работе с внешними соединениями разработчики часто сталкиваются со странным поведением запросов: в консоли запросов на стороне 1С 8.3 данные выбираются корректно, а при выполнении того же запроса через COM-соединение возвращается пустая выборка. В этой статье мы подробно разберем, почему возникает такая проблема, как правильно передавать параметры в COM-запросы, и разрушим миф о том, что внешние соединения невозможно отлаживать.
---
Как показывает практика, простейшая и самая распространенная причина «внезапного» исчезновения данных после определенной даты — это подключение к устаревшей копии базы данных или тестовому контуру. Если строка соединения прописана жестко в коде или берется из старых настроек, вы можете успешно авторизоваться под администратором, но опрашивать базу, в которой просто нет свежих документов и движений.
Проанализируем, как можно программно защититься от этой ошибки на стороне 1С 7.7 при инициализации соединения. Рекомендуется выводить в лог или на экран параметры базы, к которой произошло фактическое подключение:
// Пример проверки имени базы данных на стороне 1С 7.7
СтрокаСоединения = "Srvr=""Server1C"";Ref=""WorkDB"";";
Попытка
V8 = СоздатьОбъект("V83.ComConnector");
Соединение = V8.Connect(СтрокаСоединения);
// Получим имя текущей базы данных для сверки
ИмяБазыПриемника = Соединение.СтрокаСоединенияИнформационнойБазы();
Предупреждение("Успешное подключение к базе: " + ИмяБазыПриемника, 2);
Исключение
Предупреждение("Ошибка подключения: " + ОписаниеОшибки());
КонецПопытки;
---
В запросе автора темы используется жесткое ограничение по периоду:
ЦеныНоменклатуры.Период МЕЖДУ ДатаВремя(2019,10,30) И ДатаВремя(2019,10,30)
Разберем, к чему приводит такая конструкция. Функция ДатаВремя(2019,10,30) создает дату с нулевым временем, то есть 30.10.2019 00:00:00. Таким образом, условие МЕЖДУ фактически ищет записи, которые были записаны строго в первую секунду дня — 30 октября 2019 года ровно в полночь.
Если в регистр сведений данные записываются регистратором (документом), то время записи всегда будет соответствовать времени проведения документа (например, 30.10.2019 14:35:22). Такие записи гарантированно не попадут в указанный интервал. Чтобы избежать этой проблемы, всегда указывайте конечную границу периода с точностью до секунды или используйте параметры.
Правильный вариант фильтрации за день в тексте запроса:
ЦеныНоменклатуры.Период МЕЖДУ ДатаВремя(2019,10,30,0,0,0) И ДатаВремя(2019,10,30,23,59,59)
---
В исходном запросе автора присутствует крайне неоптимальная конструкция фильтрации по наименованию вида цен:
И ЦеныНоменклатуры.ВидЦены.Наименование ПОДОБНО "Розница"
Использование текстового оператора ПОДОБНО (аналог LIKE в SQL) для фильтрации ссылочных типов — это грубейшая ошибка проектирования по нескольким причинам:
Выясним, как правильно передавать ссылки в качестве параметров через COM-границу. Передавать напрямую объекты ссылочных типов из 1С 7.7 в 1С 8.3 невозможно из-за различия архитектур платформ. Однако мы можем найти нужный объект на стороне 1С 8.3 через COM-соединение, а затем передать полученную COM-ссылку в качестве параметра запроса.
Рассмотрим правильный шаблон реализации этой логики на стороне 1С 7.7:
// 1. Находим нужный элемент справочника на стороне 1С 8.3 через COM
ВидЦеныСсылка = Соединение.Справочники.ВидыЦен.НайтиПоНаименованию("Розница");
Если Соединение.ЗначениеЗаполнено(ВидЦеныСсылка) = 0 Тогда
Предупреждение("Вид цены 'Розница' не найден в базе 1С 8.3!");
Возврат;
КонецЕсли;
// 2. Создаем объект запроса
Запрос8 = Соединение.NewObject("Query");
Запрос8.Текст =
"ВЫБРАТЬ
| ЦеныНоменклатуры.Регистратор КАК Ссылка,
| ЦеныНоменклатуры.Цена КАК Цена,
| ЦеныНоменклатуры.Номенклатура.Наименование КАК НоменклатураНаименование
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
|ГДЕ
| ЦеныНоменклатуры.Период МЕЖДУ &НачалоПериода И &КонецПериода
| И ЦеныНоменклатуры.ВидЦены = &ВидЦены";
// 3. Устанавливаем типизированные параметры
// Передаем даты (строковый формат 1С 7.7 автоматически преобразуется в дату 1С 8.3 через COM)
Запрос8.УстановитьПараметр("НачалоПериода", '20191030000000');
Запрос8.УстановитьПараметр("КонецПериода", '20191030235959');
// Передаем COM-ссылку, полученную на шаге 1
Запрос8.УстановитьПараметр("ВидЦены", ВидЦеныСсылка);
Выборка = Запрос8.Выполнить().Выбрать();
Пока Выборка.Следующий() = 1 Цикл
Сообщить("Товар: " + Выборка.НоменклатураНаименование + " | Цена: " + Выборка.Цена);
КонецЦикла;
---
Существует распространенное заблуждение (отраженное в сообщении №10 на форуме), что отладить код или посмотреть результаты выполнения запроса при обращении из стороннего приложения через COM-соединение невозможно. Это не так. Платформа 1С 8.3 полностью поддерживает сквозную отладку внешних соединений.
Разберем по шагам, как настроить сервер и конфигуратор для перехвата управления в точках останова при COM-вызовах:
Шаг 1. Включение отладки на сервере приложений 1С
Если ваша база 1С 8.3 работает в клиент-серверном режиме, сервер приложений должен быть запущен с разрешением отладки. Для Windows-службы в реестре в параметрах запуска службы 1C:Enterprise 8.3 Server Agent должен присутствовать ключ -debug. Для Linux-сервера в конфигурационном файле должна быть установлена переменная SRV1CV8_DEBUG=1.
Шаг 2. Создание файла comcntrcfg.xml
Для того чтобы COM-процесс на стороне клиента «знал», куда отправлять отладочную информацию, необходимо создать конфигурационный файл с именем comcntrcfg.xml. Этот файл нужно разместить на том компьютере, где запускается база 1С 7.7, инициирующая подключение.
Путь для размещения файла (для 64-разрядной версии платформы 1С 8):
C:\Program Files\1cv8\conf\comcntrcfg.xml
Содержимое файла comcntrcfg.xml должно быть следующим:
<config xmlns="http://v8.1c.ru/v8/comcntrcfg">
<debugconfig debug="true" protocol="tcp" debuggerURL="tcp://localhost:1562"/>
</config>
В параметре debuggerURL укажите адрес компьютера, на котором запущен ваш Конфигуратор 1С 8.3, и порт отладки (по умолчанию используется порт 1562 для протокола TCP).
Шаг 3. Настройка автоматического подключения в Конфигураторе 1С 8
Теперь вы можете поставить точку останова в любом общем модуле (у которого взведен флаг «Внешнее соединение») или в МодулеВнешнегоСоединения. Как только код из 1С 7.7 обратится к методам 1С 8.3 через COM, выполнение приостановится на точке останова, и вы сможете использовать табло, вычислять любые выражения и анализировать результаты запросов в реальном времени.
---
Если настроить отладчик по каким-то причинам невозможно (например, на рабочем сервере запрещено включать режим отладки), вы можете перехватить текст запроса и проанализировать возвращаемые им данные с помощью технологических инструментов.
Рассмотрим два наиболее эффективных метода:
Вы можете настроить ТЖ на сервере 1С для логирования событий баз данных (SDBL). Для этого создайте файл logcfg.xml в каталоге C:\Program Files\1cv8\conf\ на сервере 1С со следующим содержимым:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/techlog/logcfg">
<log location="C:\v8logs\com_queries" history="24">
<event>
<eq property="Name" value="DBMSSQL"/>
</event>
<event>
<eq property="Name" value="SDBL"/>
</event>
<property name="all"/>
</log>
</config>
Платформа запишет в лог все запросы к СУБД MS SQL Server, включая те, что приходят из COM-сессий. Вы сможете увидеть точный SQL-текст запроса, количество задействованных таблиц и строк в результате выборки.
Поскольку внешнее соединение под капотом обращается к SQL-серверу, запустите утилиту SQL Server Profiler (для MS SQL). Настройте фильтр по имени базы данных и типу события SQL:BatchCompleted. При запуске COM-запроса из 1С 7.7 вы увидите чистый SQL-запрос, отправленный процессом rphost. Это позволит моментально определить, какие именно условия на даты или виды цен были переданы на уровень СУБД.
---
В завершение разберем важный нюанс использования COM-технологий. Для программного взаимодействия между базами часто используют два разных класса: V83.ComConnector и V83.Application. Понимание разницы между ними критично для стабильности интеграционного решения.
| Критерий оценки | V83.ComConnector | V83.Application |
|---|---|---|
| Тип процесса | Внутрипроцессный сервер (in-process). Выполняется в адресном пространстве вызывающей программы (или dllhost). | Внепроцессный сервер (out-of-process). Запускает полноценный фоновый процесс 1cv8.exe. |
| Потребление ресурсов | Минимальное. Не загружает графическую подсистему, формы и лишние библиотеки. | Высокое. Потребляет сотни мегабайт оперативной памяти на каждый сеанс. |
| Инициализация модулей | Выполняется только МодульВнешнегоСоединения. Инициализация интерфейсных модулей игнорируется. |
Выполняются абсолютно все модули: МодульПриложения, МодульУправляемогоПриложения, заполняются глобальные переменные. |
| Скорость работы | Максимально высокая. Идеально подходит для бэкэнд-интеграций и вызова серверных методов. | Низкая за счет длительного времени старта тяжелого EXE-процесса. |
Таким образом, выбор автора темы в пользу V83.ComConnector абсолютно оправдан. Соблюдая правила типизации параметров запроса и умея правильно настраивать сквозную отладку, вы сможете легко диагностировать и решать любые проблемы обмена данными.