В процессе разработки часто возникает задача интеграции нескольких информационных баз 1С. Типичный сценарий: основная база должна «заглянуть» во вспомогательную (неосновную) базу, выбрать там определенные документы (например, СчетаНаОплатуПокупателю), проверить наличие специфической номенклатуры и на основании этих данных создать записи в основной базе. Основная сложность здесь заключается не в самом подключении, а в корректном сопоставлении ссылочных данных, таких как Контрагенты или Номенклатура, которые в разных базах имеют разные внутренние идентификаторы (GUID).
В данной статье мы подробно разберем, как организовать этот процесс, используя COM-соединение, и как правильно сопоставить объекты, если их уникальные идентификаторы не совпадают, но коды идентичны.
Для начала нам необходимо инициировать подключение к внешней базе. Мы используем V83.COMConnector для создания сессии. После успешного подключения мы можем создавать объекты во внешней базе так же, как и в локальной, но обращаясь к ним через переменную COM-объекта.
Рассмотрим пример кода для инициализации подключения и выполнения запроса. Обратите внимание, что текст запроса пишется на языке запросов 1С, но сам объект запроса создается через внешнее соединение.
// Устанавливаем соединение
ПараметрыСоединения = "Srvr=""ServerName"";Ref=""TradeBase"";Usr=""Admin"";Pwd=""Password"";";
Connector = Новый COMОбъект("V83.COMConnector");
Попытка
ВнешняяБаза = Connector.Connect(ПараметрыСоединения);
Исключение
Сообщить("Не удалось подключиться: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Создаем запрос во внешней базе
ЗапросВнешний = ВнешняяБаза.NewObject("Запрос");
ЗапросВнешний.Текст =
"ВЫБРАТЬ
| Счет.Ссылка КАК Ссылка,
| Счет.Контрагент.Код КАК КонтрагентКод,
| Счет.СуммаДокумента КАК Сумма
|ИЗ
| Документ.СчетНаОплатуПокупателю КАК Счет
|ГДЕ
| Счет.Товары.Номенклатура.Артикул = &Артикул
| И Счет.Проведен = ИСТИНА";
ЗапросВнешний.УстановитьПараметр("Артикул", "ТОВ-001");
РезультатЗапроса = ЗапросВнешний.Выполнить().Выгрузить();
Важный момент: Мы выбираем не саму ссылку Счет.Контрагент, а его Код (или УникальныйИдентификатор в строковом виде). Это критически важно, так как ссылка из внешней базы не будет иметь смысла в локальной — поиск по ней ничего не даст.
Проанализируем ситуацию: мы получили таблицу с кодами контрагентов из внешней базы. Теперь нам нужно найти этих контрагентов в нашей локальной базе. Самая распространенная ошибка новичков — искать контрагента в цикле. Это создает избыточную нагрузку на систему.
Правильный подход заключается в использовании временных таблиц или пакетных запросов в локальной базе. Разберем, как это сделать эффективно:
ТаблицаЗначений.РегистромСведений, где хранится информация о менеджерах.Рассмотрим реализацию этого алгоритма:
// 1. Формируем локальную таблицу из COM-результата
ЛокальнаяТЗ = Новый ТаблицаЗначений;
ЛокальнаяТЗ.Колонки.Добавить("КонтрагентКод", Новый ОписаниеТипов("Строка"));
ЛокальнаяТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
Для Каждого СтрокаВнешняя Из РезультатЗапроса Цикл
НоваяСтрока = ЛокальнаяТЗ.Добавить();
НоваяСтрока.КонтрагентКод = СтрокаВнешняя.КонтрагентКод;
НоваяСтрока.Сумма = СтрокаВнешняя.Сумма;
КонецЦикла;
// 2. Ищем данные в локальной базе одним запросом
ЗапросЛокальный = Новый Запрос;
ЗапросЛокальный.Текст =
"ВЫБРАТЬ
| ВТ_ВнешниеДанные.КонтрагентКод КАК КонтрагентКод,
| ВТ_ВнешниеДанные.Сумма КАК Сумма
|ПОМЕСТИТЬ ВТ_Счета
|ИЗ
| &ЛокальнаяТЗ КАК ВТ_ВнешниеДанные
|;
|
|ВЫБРАТЬ
| Контрагенты.Ссылка КАК КонтрагентСсылка,
| ВТ_Счета.Сумма КАК Сумма,
| ЗакрепленныеМенеджеры.Менеджер КАК Менеджер
|ИЗ
| ВТ_Счета КАК ВТ_Счета
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
| ПО ВТ_Счета.КонтрагентКод = Контрагенты.Код
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗакрепленныеМенеджеры КАК ЗакрепленныеМенеджеры
| ПО Контрагенты.Ссылка = ЗакрепленныеМенеджеры.Контрагент";
ЗапросЛокальный.УстановитьПараметр("ЛокальнаяТЗ", ЛокальнаяТЗ);
Выборка = ЗапросЛокальный.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Здесь мы уже имеем и локальную ссылку на контрагента, и менеджера из РС
// Добавляем запись в документ или ТЧ
КонецЦикла;
При работе с внешними соединениями необходимо учитывать несколько технических нюансов. Выясним основные причины возможных проблем и способы их решения:
Управление ресурсами: После завершения работы с внешней базой обязательно нужно обнулять переменную COM-объекта. В противном случае сессия на сервере может «зависнуть», потребляя лицензию и оперативную память. Используйте конструкцию ВнешняяБаза = Неопределено;.
Лицензирование: Каждое COM-подключение — это отдельный сеанс, который требует клиентскую лицензию. Если ваша задача выполняется регламентным заданием каждые 5 минут, убедитесь, что у вас достаточно свободных лицензий, чтобы не блокировать работу пользователей.
Альтернативные методы: Рассмотрим использование современных HTTP-сервисов. В отличие от COM, HTTP-сервисы работают быстрее, не зависят от разрядности операционной системы (32/64 бит) и более стабильны при обрывах связи. Если вы планируете долгосрочную поддержку интеграции, рекомендуем настроить в «НеОсновной» базе простейший REST API (OData) или собственный HTTP-сервис, который будет отдавать данные в формате JSON.
Безопасность: Никогда не храните пароли к базам в открытом виде внутри кода. Проанализируем ситуацию: если злоумышленник получит доступ к конфигурации, он узнает доступы ко всем смежным системам. Используйте БезопасноеХранилищеДанных или хотя бы закрытые константы с ограниченными правами доступа.
Для успешного решения задачи нам потребовалось:
V83.COMConnector.Запроса во внешней базе, обязательно извлекая строковые идентификаторы (Код или GUID).Регистра Сведений.Такой подход обеспечивает высокую скорость работы и надежность сопоставления объектов между независимыми информационными системами.