При переходе с тонкого или толстого клиента 1С на работу через веб-клиент разработчики часто сталкиваются с неприятным сюрпризом: проверенный временем код для работы с внешними источниками данных через COM-соединение внезапно перестает работать. При попытке инициализации объекта, например, с помощью привычной конструкции Новый COMОбъект("ADODB.Connection") или Новый COMОбъект("ADOX.Catalog"), система выдает критическое исключение: "Невозможно создание объекта сервером программирования объектов".
В этой статье мы подробно проанализируем, почему возникает данная проблема, рассмотрим архитектурные ограничения современных веб-технологий и разберем четыре эффективных, современных и безопасных способа реализации этого функционала в веб-среде.
Технология COM (Component Object Model) является проприетарной разработкой компании Microsoft и тесно интегрирована с операционной системой Windows. Тонкий и толстый клиенты 1С запускаются как полноценные операционные процессы локального компьютера, имеющие прямой доступ к системным API вашей ОС. Именно поэтому в них создание COM-объектов проходит без каких-либо затруднений.
Веб-клиент 1С работает совершенно по другим принципам. Он исполняется внутри веб-браузера (Google Chrome, Mozilla Firefox, Яндекс.Браузер, Microsoft Edge, Safari) и полностью подчиняется его правилам безопасности. Разберем по шагам ключевые ограничения:
Таким образом, попытка вызвать метод Новый COMОбъект непосредственно в коде клиентской формы при работе через веб-клиент всегда будет приводить к ошибке. Нам необходимо пересмотреть архитектуру нашего решения.
Самый простой шаг, если вам необходимо сохранить существующую кодовую базу с минимальными изменениями, — перенести создание COM-объекта и всю логику взаимодействия с базой SQLite на сервер 1С. Серверная часть платформы работает как полноценное приложение операционной системы и имеет доступ к COM-технологиям (если сервер 1С работает под управлением ОС Windows).
Проанализируем пример перевода клиентской логики на серверную. Вместо того чтобы открывать соединение на клиенте, мы передаем необходимые параметры на сервер, выполняем там все ресурсоемкие операции по выборке или записи данных, а на клиент возвращаем уже готовый результат в виде универсальной коллекции (например, массива структур).
Рассмотрим пример кода для серверного подключения к SQLite через ADODB:
&НаСервереБезКонтекста
Функция ПолучитьДанныеИзSQLiteНаСервере(ПутьКБазе)
РезультатТаблица = Новый ТаблицаЗначений;
РезультатТаблица.Колонки.Добавить("Код");
РезультатТаблица.Колонки.Добавить("Наименование");
Попытка
// Инициализируем COM-объект на стороне сервера
Connection = Новый COMОбъект("ADODB.Connection");
RecordSet = Новый COMОбъект("ADODB.Recordset");
// Строка подключения к SQLite через ODBC-драйвер
СтрокаПодключения = "Driver={SQLite3 ODBC Driver};Database=" + ПутьКБазе + ";";
Connection.Open(СтрокаПодключения);
ТекстЗапроса = "SELECT id, name FROM users LIMIT 100;";
RecordSet.Open(ТекстЗапроса, Connection);
Пока НЕ RecordSet.EOF Цикл
НоваяСтрока = РезультатТаблица.Добавить();
НоваяСтрока.Код = RecordSet.Fields("id").Value;
НоваяСтрока.Наименование = RecordSet.Fields("name").Value;
RecordSet.MoveNext();
КонецЦикла;
RecordSet.Close();
Connection.Close();
Исключение
ЗаписьЖурналаРегистрации("ВнешнееПодключениеSQLite",
УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка при работе с SQLite на сервере: " + ОписаниеОшибки());
ВызватьИсключение "Не удалось получить данные из внешней базы. Подробности в журнале регистрации.";
КонецПопытки;
// Преобразуем ТаблицуЗначений в массив структур для передачи на клиент
МассивРезультатов = Новый Массив;
Для Каждого СтрокаТЗ Из РезультатТаблица Цикл
НоваяСтруктура = Новый Структура("Код, Наименование", СтрокаТЗ.Код, СтрокаТЗ.Наименование);
МассивРезультатов.Добавить(НоваяСтруктура);
КонецЦикла;
Возврат МассивРезультатов;
КонецФункции
Важные подводные камни при использовании COM на сервере:
IUSR или DefaultAppPool). Убедитесь, что у этого пользователя есть права доступа к файлу базы данных SQLite и к веткам реестра, отвечающим за DCOM.Для того чтобы не писать низкоуровневый код работы с COM-объектами вручную, платформа 1С предоставляет встроенный декларативный механизм — Внешние источники данных. Это архитектурно правильный способ интеграции со сторонними СУБД.
Посмотрим на преимущества этого подхода:
Разберем по шагам, как настроить внешние источники данных для SQLite:
После этого вы сможете писать простые запросы на сервере 1С, которые будут одинаково успешно отрабатывать при вызове с любого клиента:
&НаСервере
Функция ПолучитьСписокПользователейИзВИД()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Пользователи.Код КАК Код,
| Пользователи.Наименование КАК Наименование
|ИЗ
| ВнешнийИсточникДанных.SQLiteБД.Таблица.users КАК Пользователи";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Если база данных SQLite находится на удаленном ресурсе или у вас распределенная архитектура, а также если сервер 1С работает под управлением Linux, идеальным решением будет создание легковесного веб-сервиса (на Python, Node.js, Go или C#), который будет выступать в роли посредника (API-обертки) между файлом SQLite и 1С.
Проанализируем этот сценарий:
HTTPСоединение и HTTPЗапрос. Они работают везде: и на клиенте в браузере, и на сервере, независимо от используемой операционной системы.Рассмотрим, как будет выглядеть отправка запроса к такому сервису из 1С:
&НаСервереБезКонтекста
Функция ВыполнитьЗапросКМикросервису(ПараметрыЗапроса)
// Настраиваем соединение с веб-сервисом
Сервер = "api.my-sqlite-service.local";
Порт = 8080;
Соединение = Новый HTTPСоединение(Сервер, Порт);
// Создаем запрос для выполнения SQL
Запрос = Новый HTTPЗапрос("/api/v1/query");
Запрос.Заголовки.Вставить("Content-Type", "application/json");
// Формируем тело запроса в формате JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ПараметрыЗапроса);
СтрокаТела = ЗаписьJSON.Закрыть();
Запрос.УстановитьТелоИзСтроки(СтрокаТела, КодировкаТекста.UTF8);
Попытка
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
// Читаем полученные данные
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Возврат Данные;
Иначе
ВызватьИсключение "Сервер вернул код ошибки: " + Ответ.КодСостояния;
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("HTTP_SQLite", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
ВызватьИсключение "Ошибка сетевого взаимодействия с базой SQLite.";
КонецПопытки;
КонецФункции
Данный подход считается промышленным стандартом интеграции в веб-ориентированных архитектурах. Он полностью решает проблемы безопасности, разрядности драйверов и привязки к операционной системе Windows.
Для тех ситуаций, когда необходимо работать с файлом SQLite локально на компьютере пользователя или непосредственно на сервере без развертывания дополнительных служб, отлично подходит использование внешних компонент, созданных по технологии Native API.
В отличие от устаревших COM-объектов, Native API компоненты:
Для работы с SQLite в сообществе 1С широкую популярность получила внешняя компонента v8sqlite. Она предоставляет разработчику объектный интерфейс для выполнения SQL-запросов и чтения результатов напрямую из файла базы данных, избавляя от необходимости настраивать системные ODBC-драйверы и регистрировать COM-библиотеки в реестре Windows.
Посмотрим на пример использования такой компоненты на сервере 1С:
&НаСервере
Процедура ВыполнитьЗапросЧерезNativeAPI(ПутьКФайлуБД)
// Подключаем внешнюю компоненту из макета конфигурации
Попытка
ПодключитьВнешнююКомпоненту("ОбщийМакет.v8sqlite", "SQLiteComp", ТипВнешнейКомпоненты.Native);
ДрайверSQLite = Новый("AddIn.SQLiteComp.v8sqlite");
Исключение
ВызватьИсключение "Не удалось загрузить внешнюю компоненту SQLite: " + ОписаниеОшибки();
КонецПопытки;
// Открываем файл базы данных
Если ДрайверSQLite.ОткрытьБазу(ПутьКФайлуБД) Тогда
// Выполняем SQL-запрос
ТаблицаРезультатов = ДрайверSQLite.ВыполнитьЗапрос("SELECT * FROM products;");
// Обрабатываем полученные данные
Для Каждого СтрокаТаблицы Из ТаблицаРезультатов Цикл
// Логика обработки бизнес-данных
КонецЦикла;
ДрайверSQLite.ЗакрытьБазу();
Иначе
ВызватьИсключение "Не удалось открыть файл базы данных SQLite: " + ДрайверSQLite.ПолучитьТекстОшибки();
КонецЕсли;
ПроцедураКонец
Использование Native API компонент позволяет создавать максимально автономные и переносимые решения, которые легко разворачивать у конечных пользователей без предварительной ручной настройки их рабочих станций.
Для того чтобы вам было проще сделать правильный архитектурный выбор для вашего проекта, проанализируем сравнительную таблицу всех рассмотренных подходов:
| Метод интеграции | Сложность реализации | Кроссплатформенность | Требования к настройке инфраструктуры | Рекомендуемая область применения |
|---|---|---|---|---|
| Перенос кода на Сервер (&НаСервере) | Низкая (минимальный рефакторинг исходного кода) | Нет (привязка сервера 1С к ОС Windows и разрядности процессов) | Установка ODBC-драйвера нужной разрядности на сервере 1С. Настройка DCOM прав при необходимости. | Быстрое решение для существующих монолитных Windows-систем при переходе на веб-клиент. |
| Внешние источники данных (ВИД) | Средняя (требует изменения структуры конфигурации 1С) | Да (поддержка на стороне сервера, запросы пишутся на языке 1С) | Настройка ODBC-соединения на сервере 1С. | Регулярный импорт/экспорт больших объемов структурированных данных, построение сложных СКД-отчетов по внешним таблицам. |
| HTTP/REST Микросервис | Высокая (требуется разработка внешнего веб-приложения) | Да (абсолютная независимость от ОС и платформы) | Развертывание и поддержка веб-сервиса на любом хостинге или локальном сервере. | Крупные распределенные системы, облачные решения, работа с мобильными клиентами 1С, интеграция с Linux-серверами. |
| Внешняя компонента Native API | Средняя (требует внедрения компоненты в макеты конфигурации) | Да (зависит от сборки компоненты под конкретные ОС) | Добавление бинарных файлов компоненты в конфигурацию. Не требует прав администратора на сервере. | Создание тиражируемых конфигураций и расширений, требующих локальной автономной работы с SQLite "из коробки". |
Подводя итоги нашего анализа, выделим ключевые правила для разработчиков при проектировании интеграций с внешними СУБД в системах 1С, работающих через веб-клиент:
&НаКлиенте), если планируется использование веб-клиента. Браузер гарантированно заблокирует выполнение этой операции из соображений безопасности.