При межбазовом обмене данными через COM-соединение часто возникает необходимость передать таблицу значений во внешнюю базу и использовать её в качестве параметра запроса (например, для взаимодействия с временной таблицей). Однако при попытке сформировать колонки локально или без явного указания типов платформа выдает ошибку. Разберем, как правильно объявить типы данных для колонок таблицы значений в контексте COM-базы.
Основная проблема заключается в **разделении контекстов объектов**. Объект ТаблицаЗначений, её колонки и описывающие их объекты ОписаниеТипов должны быть созданы строго в контексте внешнего COM-соединения. Если попытаться передать локально созданный объект ОписаниеТипов во внешнюю базу, платформа выдаст ошибку несоответствия типов.
Кроме того, если в таблице значений хотя бы одна колонка окажется нетипизированной, попытка поместить такую таблицу во временную таблицу в запросе завершится ошибкой («Тип не может быть выбран в запросе»). Все колонки таблицы значений, передаваемой в запрос внешней базы, обязаны иметь четкое описание типов.
Для корректного задания типа колонки используем метод NewObject внешнего соединения. Описание типов задается с помощью строки с наименованием типа данных на русском или английском языке.
Рассмотрим базовый пример создания таблицы значений и типизации её колонок во внешней базе:
// Подключаемся к внешней базе
БухБД = Новый COMОбъект("V83.COMConnector");
Соединение = БухБД.Connect("Srvr=""ServerName"";Ref=""BaseName"";");
// Создаем таблицу значений в контексте внешней базы
ТаблицаТоваров = Соединение.NewObject("ТаблицаЗначений");
// Добавляем колонку со строковым типом данных
ТаблицаТоваров.Колонки.Добавить("УпрГуид", Соединение.NewObject("ОписаниеТипов", "Строка"));
// Добавляем колонку с числовым типом данных
ТаблицаТоваров.Колонки.Добавить("Количество", Соединение.NewObject("ОписаниеТипов", "Число"));
Проанализируем этот код: вызов Соединение.NewObject("ОписаниеТипов", "Строка") инстанцирует объект описания типов внутри внешней базы, что полностью исключает конфликт контекстов.
Чтобы избежать неограниченной длины строк или некорректной точности чисел при формировании временных таблиц во внешней базе, рекомендуем явно задавать квалификаторы типов через COM.
Разберем по шагам, как задать типы с квалификаторами и ссылочные типы:
КвалификаторыЧисла во внешней базе и передаем их в конструктор ОписаниеТипов.КвалификаторыСтроки."СправочникСсылка.Номенклатура".Посмотрим на пример кода с квалификаторами и ссылками:
// Создание числовой колонки с длиной 15 и точностью 2
КвалифЧисла = Соединение.NewObject("КвалификаторыЧисла", 15, 2);
ТипЧисло = Соединение.NewObject("ОписаниеТипов", "Число", КвалифЧисла);
ТаблицаТоваров.Колонки.Добавить("Сумма", ТипЧисло);
// Создание ссылочной колонки на справочник внешней базы
ТипНоменклатура = Соединение.NewObject("ОписаниеТипов", "СправочникСсылка.Номенклатура");
ТаблицаТоваров.Колонки.Добавить("Номенклатура", ТипНоменклатура);
После того как таблица значений создана и правильно типизирована, её можно передать в параметр COM-запроса. Обратите внимание, что в тексте запроса внешнюю таблицу значений необходимо помещать во временную таблицу.
ЗапросCOM = Соединение.NewObject("Запрос");
ЗапросCOM.Текст =
"ВЫБРАТЬ
| ТЗ.УпрГуид КАК УпрГуид,
| ТЗ.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ
| &ПараметрТЗ КАК ТЗ";
ЗапросCOM.УстановитьПараметр("ПараметрТЗ", ТаблицаТоваров);
РезультатЗапроса = ЗапросCOM.Выполнить();
Если таблица значений уже сформирована в текущей базе и содержит только примитивные типы данных (строки, числа, даты, булево), чтобы не пересоздавать её вручную через COM, можно применить сериализацию в XML:
// В текущей базе сериализуем ТЗ в строку XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ЛокальнаяТЗ);
СтрокаXML = ЗаписьXML.Закрыть();
// Во внешней базе прочитываем XML и получаем ТЗ в контексте COM
ВнешняяТЗ = Соединение.СериализаторXDTO.ПрочитатьXML(
Соединение.ФабрикаXDTO.Создать(
Соединение.СериализаторXDTO.ПрочитатьXML(
Соединение.ЗаписьXML.УстановитьСтроку(СтрокаXML)
)
)
);
При сериализации тип каждой колонки сохраняется, а объект таблицы значений создается непосредственно в контексте приемника, что также позволяет передавать его в параметры COM-запросов.