Подключение к базе данных 1С и выполнение SQL запросов на примере работы со справочниками. Часть 3.
Сегодня, как мы и обещали, рассмотрим основные приемы работы с базой данных 1С с использованием средств Microsoft ActiveX Data Objects (ADO). Цитата из Microsoft Solution Developer Network Library (MSDN): "Microsoft ActiveX Data Objects (ADO) enable your client applications to access and manipulate data from a variety of sources through an OLE DB provider. Its primary benefits are ease of use, high speed, low memory overhead, and a small disk footprint. ADO supports key features for building client/server and Web-based applications." Краткий литературный перевод: "При помощи ADO легко и удобно работать с различными базами данных, и уж тем более с MS SQL Server."
Так как ADO является ключевой технологией Microsoft, то прилагать особых усилий для установки его на Ваш компьютер не придется. В 99% он уже присутствует.
Объектная модель ADO довольна обширна, но в рамках нашего цикла статей мы будет использовать только два объекта "Connection" и "Recordset". За описанием других объектов ADO Вам следует обратится к MSDN (любимая фраза преподавателей различный компьютерных курсов). Более того, в этой статье мы не ставим целью описать все тонкости работы с упомянутыми объектами, а рассмотрим только ту часть информации, которая позволит нам подключаться и получать данные из 1С. Если у Вас появится желание стать экспертом по использованию ADO, то... совершенно верно: Вам следует обратиться к MSDN.
И так, продолжим...
Объект "Connection"
Объект предназначен для представления сервисов по подключению к базе данных. Необходимые нам свойства и методы объекта:
Наименование
Описание
Свойства
ConnectionString
Cтрока подключения к базе данных. Имеет вид: "Driver={SQL Server};Server=ИмяСервера;Uid=ИмяПользователя;Pwd=Пароль(или пусто);DataBase=ИмяБазыДанныхНаСервере;".
ConnectionTimeOut
Время ожидания соединения (в секундах) с сервером, по истечении которого генерируется ошибка. По умолчанию равно 15 сек.
CommandTimeOut
Время ожидания (в секундах) выполнения команды (SQL запроса),по истечении которого генерируется ошибка.
По умолчанию равно 30 сек.
Примечания:
если предполагаются операции с большими или очень большими объемами данных, то данное время крайне желательно увеличить;
если Вам пришлось увеличить данное время, подумайте все ли Вы правильно делаете.
Методы
Open(СтрокаПодключенияКБазеДанных)
Открывает соединение с базой данных
Execute(СтрокаЗапроса)
Выполняет SQL запрос. Имеет смысл применять в том случае, если необходимо выполнить запрос, не возвращающий данные клиену. Например, обновление или вставка новых строк в таблицу.
Close()
Закрывает соединение с базой данных.
Объект "Recordset"
Объект предназначен для выполнения запросов к базе данных и возврата итоговой выборки клиенту. Основные свойства и методы:
Наименование
Описание
Свойства
ActiveConnection
Содержит объект Connection, с помощью которого мы можем подключиться к серверу.
State
Свойство указывает открыт или закрыт объект. Например, если был выполнен запрос, но в итоговой выборке нет строк, то в свойстве State будет 0. Учтите, что нельзя открывать еще раз уже открытый объект и закрывать уже закрытый. Так что перед выполнением соответствующих методов лучше проверять значение свойства State. Вы уверены, что всегда знаете закрыт Ваш объект или открыт? В таком случае Вы либо еще очень молоды (это пройдет), либо жизнь Вас ни чему не учит (а вот это едва ли).
Fields(ИмяПоля).Value
Возвращает значение ИмяПоля из выборки (строго говоря это коллекция, но отнесем ее к свойствам мы же не коллекционеры).
EOF
Возвращает 1, если в результате перебора дошли до конца выборки.
Методы
Open(СтрокаЗапроса)
Открывает выборку данных.
MoveNext()
Получить следующее значение выборки.
Close()
Закрыть выборку.
Работа с ADO
В общем случае ADO более предпочтительно в использовании, однако есть большой недостаток: ADO, в отличии от "Rainbow", не работает в монопольном режиме. Если Вы будете применять его при проведении документов, то Вам придется отказаться от системного перепроведения.
Первая проблема с которой Вы столкнетесь при использовании ADO это проблема формирования строки подключения. Если имя пользователя и пароль всегда известны (в 90% случаев это "sa" и пустой пароль), то с именами сервера и базы данных возникает небольшая проблема. Есть три пути решения данной проблемы:
"Зашить" строку подключения в код (откажитесь сразу).
Использовать константы (уже лучше, но есть недостаток. При загрузке данных в другую базу Вам придется не забывать менять эти константы, иначе в лучшем случае Ваши пользователи будут получать неправильные отчеты, в худшем... тут фантазия рисует жуткие картины всемирного апокалипсиса).
Написать функцию, которая при помощи "Rainbow" сформирует нужную строку подключения. (лучший вариант).
Недостатки первых двух методов очевидны. Что касается третьего метода, то может возникнуть вопрос, а зачем использовать ADO, если есть "Rainbow"? Ответ простой - ADO обладает рядом преимуществ перед "Rainbow":
Ошибка в ADO не вызывает аварийного закрытия 1С. "Rainbow" в этом случае закрывает 1С со страшным сообщением "Невосстановимая ошибка базы данных". Не верьте. Очень даже восстановимая.
ADO быстрее (без комментариев).
ADO при наличии одного открытого объекта Connection позволяет использовать в разных объектах Recordset временные таблицы (бывает очень нужно).
При открытом объекте Recordset нет никаких ограничений на работу с базой данных самой 1С. Проще говоря, если вы открыли выборку при помощи "Rainbow", то, пока не закроете, не сможете пользоваться методами 1С для доступа к данным. При применении ADO делайте, что хотите, хоть документ проводите, хоть справочник меняйте.
Правда, повторимся, за это приходится жертвовать монопольным режимом.
Попробуем перейти от теории к практике.
Написать функцию глПолучитьСтрокуПодключения(), возвращающую строку подключения по материалам прошлых статей не должно составить труда.
Подсказка: запрос имеет следующий вид:
-- @@SERVERNAME - имя сервера, NAME - имя базы данных
SELECT @@SERVERNAME, NAME
FROM master.dbo.sysprocesses pr, master.dbo.sysdatabases db
WHERE pr.dbid = db.dbid AND pr.spid = @@SPID