При переходе на 64-битную версию платформы 1С:Предприятие и 64-битный клиент Oracle разработчики часто сталкиваются с ошибками при попытке использовать привычные COM-объекты ADODB.Connection и ADODB.Command. Если стандартное выполнение запроса через объект RecordSet проходит успешно, то связывание команды с соединением через свойство ActiveConnection или создание параметров может вызывать ошибку COM:
Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another (0x800A0BB9).
Разберем причины возникновения этой ошибки в 64-разрядной среде и рассмотрим надежные способы решения задачи передачи параметров и вызова процедур СУБД Oracle.
Проанализируем технические особенности работы с OLE DB в 64-битной архитектуре:
adInteger, adParamInput, adCmdStoredProc). В 32-битном окружении или при определенных типах драйверов некоторые значения могли интерпретироваться по умолчанию, однако в 64-битном клиенте передача пустых значений (Неопределено) немедленно приводит к исключению несоответствия типов.ActiveConnection объекта ADODB.Command принимает как ссылку на объект Connection, так и строку подключения. При позднем связывании (IDispatch) в 64-битном драйвере OraOLEDB.Oracle передача ссылки на другой COM-объект может вызывать сбой сопоставления типов.MSDAORA и OraOLEDB: Устаревший Microsoft OLE DB Provider for Oracle (MSDAORA) существует исключительно в 32-битной версии. При переходе на 64-битный провайдер Oracle (OraOLEDB.Oracle) меняются требования к синтаксису вызова процедур и передаче параметров.Рассмотрим основной и наиболее надежный способ интеграции 1С с СУБД Oracle, не зависящий от COM-библиотек Windows. Платформа 1С:Предприятие 8.3 позволяет подключить внешнюю базу данных напрямую через механизм внешних источников данных (ВИД).
Разберем по шагам порядок настройки:
СтрокаПодключения = "DRIVER={Oracle in OraClient12home1};UID=имя_пользователя;PWD=пароль;DBQ=TEST";
ПараметрыПодключения = Новый ПараметрыПодключенияВнешнегоИсточникаДанных;
ПараметрыПодключения.СтрокаСоединения = СтрокаПодключения;
ВнешниеИсточникиДанных.ВнешняяБДOracle.УстановитьПараметрыПодключения(ПараметрыПодключения);
ВнешниеИсточникиДанных.ВнешняяБДOracle.УстановитьСоединение();
// Вызов хранимой функции/процедуры внешнего источника
Результат = ВнешниеИсточникиДанных.ВнешняяБДOracle.ХранимыеПроцедуры.ИмяПроцедуры(ЗначениеПараметра1, ЗначениеПараметра2);
// Выполнение запроса с параметрами к таблице внешнего источника
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Таблица.Поле1,
| Таблица.Поле2
|ИЗ
| ВнешнийИсточникДанных.ВнешняяБДOracle.Таблица.ТаблицаOracle КАК Таблица
|ГДЕ
| Таблица.Идентификатор = &Идентификатор";
Запрос.УстановитьПараметр("Идентификатор", ИскомыйИД);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Если архитектура проекта требует сохранить работу через COM-объект ADODB, необходимо строго соблюдать типы параметров и правила передачи соединения.
Посмотрим на пример правильной инициализации констант ADO и вызова параметризованного запроса:
// Объявляем числовые эквиваленты констант ADO
adInteger = 3;
adVarChar = 200;
adParamInput = 1;
adCmdText = 1;
СтрокаСоединения = "Provider=OraOLEDB.Oracle;Data Source=TEST;User Id=ххх;Password=хххх;";
objCon = Новый COMОбъект("ADODB.Connection");
objCon.ConnectionString = СтрокаСоединения;
objCon.Open();
objCmd = Новый COMОбъект("ADODB.Command");
// Если прямая передача objCon вызывает ошибку, передаем строку подключения
objCmd.ActiveConnection = objCon;
objCmd.CommandType = adCmdText;
objCmd.CommandText = "SELECT COUNT(1) FROM ss s WHERE s.id_promr = ?";
// Передаем точные числовые типы констант
ПараметрИД = objCmd.CreateParameter("id_prom", adInteger, adParamInput, , Число(ИскомыйИД));
objCmd.Parameters.Append(ПараметрИД);
RecordSet = objCmd.Execute();
Пока НЕ RecordSet.EOF Цикл
// Обработка данных
RecordSet.MoveNext();
КонецЦикла;
RecordSet.Close();
objCon.Close();
При возникновении конфликтов с коллекцией Parameters объекта Command вызов процедур СУБД Oracle можно осуществить напрямую через метод Execute объекта Connection с помощью анонимного блока PL/SQL:
ТекстPLSQL =
"BEGIN
| имя_схемы.имя_процедуры(" + Формат(Число(ИскомыйИД), "ЧГ=0") + ");
|END;";
objCon.Execute(ТекстPLSQL);
Этот способ позволяет гарантированно передавать вызовы процедур на сервер Oracle без использования промежуточного объекта ADODB.Command.