При разработке механизмов интеграции между различными базами 1С через COM-соединение программисты часто сталкиваются с ситуацией, когда инициализированное соединение внезапно «пропадает». В коде это проявляется ошибкой «Значение не является значением объектного типа (NewObject)» (или любым другим методом, вызываемым у объекта соединения). Рассмотрим детально, почему это происходит и как правильно организовать работу с внешними источниками данных.
Проанализируем типичный сценарий: разработчик создает COM-объект (например, через V83.COMConnector), успешно выполняет несколько запросов к внешней базе, но при передаче управления в другую процедуру или функцию объект «теряет» свои свойства. Вызов метода NewObject() или попытка обратиться к метаданным внешней базы возвращает ошибку, так как переменная, содержащая соединение, становится равной Неопределено.
Выясним основную причину: в 1С при работе в режиме управляемого приложения существует жесткое разделение контекстов выполнения кода — клиент и сервер. COM-объекты относятся к категории объектов, которые не могут быть сериализованы. Это значит, что их невозможно передать по сети с клиентского компьютера на сервер предприятия или наоборот.
Рассмотрим пошагово, что происходит в коде, когда возникает подобная ошибка:
ПодключитьсяКИБ() на стороне клиента и сохраняете результат в переменную, объект COM-соединения живет в памяти клиентского приложения.ОбработатьРеализацияТоваровУслуг(ВыборкаУТ.Ссылка)), платформа пытается передать параметры.УТ на сервере будет пустой, даже если на клиенте вы ее заполнили.Наиболее правильным и надежным способом решения проблемы является выполнение всей цепочки действий (подключение, выборка данных, обработка) в одном контексте — на сервере. Разберем пример правильной структуры кода:
&НаСервере
Процедура ВыполнитьИнтеграциюНаСервере()
ПараметрыПодключения = Новый Структура;
ПараметрыПодключения.Вставить("ВариантРаботыИнформационнойБазы", 1);
// ... заполнение остальных параметров ...
СообщениеОбОшибке = "";
СоединениеУТ = ОбщегоНазначенияКлиентСервер.УстановитьВнешнееСоединение(ПараметрыПодключения, СообщениеОбОшибке);
Если СоединениеУТ = Неопределено Тогда
ЗаписатьЛогОшибки(СообщениеОбОшибке);
Возврат;
КонецЕсли;
// Вся работа происходит внутри одной серверной процедуры или
// передается в другие серверные процедуры в пределах одного вызова
ОбработатьДанныеЧерезCOM(СоединениеУТ);
КонецПроцедуры
В данном случае объект СоединениеУТ создается на сервере и передается в подчиненные процедуры в пределах серверного контекста. Это исключает необходимость передачи «тяжелого» объекта через границу «клиент-сервер».
Если архитектура решения требует обращения к COM-соединению из разных мест серверного кода, рекомендуется реализовать функцию, которая будет проверять наличие активного соединения и возвращать его. Рассмотрим этот подход:
Перем мСоединениеУТ; // Внутренняя переменная модуля для кэширования
Функция ПолучитьСоединениеУТ()
// Проверяем, инициализировано ли соединение ранее в этом серверном вызове
Если мСоединениеУТ <> Неопределено Тогда
Возврат мСоединениеУТ;
КонецЕсли;
// Логика подключения
// мСоединениеУТ = ПодключитьсяКБазе();
Возврат мСоединениеУТ;
КонецФункции
Процедура ОбработатьДокумент(СсылкаНаДокумент)
УТ = ПолучитьСоединениеУТ();
ЗапросУТ = УТ.NewObject("Запрос");
// Дальнейшая работа с запросом
КонецПроцедуры
Такой подход гарантирует, что в рамках одного серверного вызова (одного сеанса работы сервера) соединение будет установлено один раз и будет доступно всем процедурам.
Проанализируем еще одну частую ошибку: передачу ссылок типа COMОбъект (например, ВыборкаУТ.Ссылка).
Нужно понимать, что ВыборкаУТ.Ссылка — это не обычная ссылка 1С, а прокси-объект, который жестко связан с конкретным экземпляром соединения УТ.
Рекомендации по работе со ссылками:
COMОбъект (ссылку из внешней базы) между клиентом и сервером.String(Ссылка.UUID()) или УникальныйИдентификатор(), чтобы получить строку.Документы.РеализацияТоваровУслуг.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаUUID)).Иногда ошибка NewObject возникает не из-за программной логики, а из-за технических ограничений среды. Например, если сервер 1С работает в 64-битном режиме, а COM-компонента внешней базы (или драйвер) — 32-битная.
В этом случае проанализируем возможность использования Служб компонентов (COM+):
dcomcnfg на сервере.V83.COMConnector.Это позволит выделить COM-соединение в отдельный процесс dllhost.exe, что предотвратит падение рабочего процесса 1С при ошибках в COM и решит проблему несовместимости разрядности.
Таким образом, мы выяснили, что ключ к исправлению ошибки «Значение не является значением объектного типа» лежит в строгом соблюдении контекстности исполнения кода. Работайте с COM-объектами исключительно на стороне сервера, не пытайтесь передавать их между контекстами и всегда проверяйте состояние объекта перед вызовом его методов.