![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Опыт использования ADO для доступа к базам данных форматов MS Access, xBase и ParadoxDelphi , Базы данных , ADO
Оформил: DeeCo Автор: Иванов Денис Михайлович Данная статья не является каким-либо учебным пособием, а просто попыткой обобщить некий опыт, полученный в течение некоторого времени при использовании ADO. Подвигло меня на написание этой статьи то обстоятельство, что когда я приступал к этой работе (я имею в виду использование ADO), я размещал свои вопросы во многих конференциях, а ответов на них не получено до сих пор и, более того, эти же вопросы стали задаваться по новой, а ответов на них как не было, так и нет. На некоторые из них я отвечал, а потом подумал, что не все будут просматривать конференцию целиком, да и когда все сведено в одном месте оно и лучше. Кроме того, толковой литературы по использованию ADO практически нет никакой. Например, мне не удалось найти в солидных по объему книгах г-на Архангельского необходимую мне информацию. Или еще пример - Microsoft Press 'Справочник по OLE DB'. Здесь другой уклон - информации много, слишком много, а примеров никаких (но это вообще проблема справок от Microsoft - написано много, а примеров использования почти нет). Надеюсь, что те сведения, которые я приведу здесь, помогут коллегам по цеху в решении его задач. Причины перехода от BDE к ADO Итак, чтобы было понятно что к чему, сначала поясню, зачем же понадобился переход к ADO. Я работаю программистом в компании, которая занимается написанием оболочки для создания геоинформационных систем (ГИС). То есть имеется некая красивая карта и необходимо получение каких-то атрибутивных данных по объектам на этой карте размещенным. При этом атрибутивные таблицы не имеют заранее установленной структуры - только некие предустановленные поля, которых пользователь не видит, но которые используются для связи объектов на карте и записей в базе данных. Итак, для хранения атрибутивной информации был выбран формат MS Access, который имеет то обстоятельство, что все таблицы хранятся в одном файле (в отличие от Paradox и Dbase) и не требует при этом запущенного сервера, как, к примеру, Interbase. Необходима также связь с файлами форматов dbf и db для загрузки/выгрузки данных в/из БД. Для написания программы мы используем Delphi 4, а для подключения к файлам БД использовалась BDE. И все это было отлично, но вот появились два важных обстоятельства:
- Учитель, почему ты обманул меня? Ты сказал, что Вейдер предал и
убил моего отца, а теперь оказалось, что он и есть мой отец!
![]() А теперь давайте, вообразим себя пользователями и попробуем что-нибудь исправить или добавить. Например, добавим несколько пустых записей и попробуем внести туда данные. Добавляем. Нормально. Теперь внесем данные и нажмем POST. И что мы видим? ![]() ![]() Что здесь интересного? А то, что содержимое Internal_ID для всех этих записей равно нулю, хотя это автоинкрементное поле! И Table.Refresh здесь не помогает! Только закрытие и последующее открытие таблицы приводит к тому, что мы видим то, что и ожидалось. ![]() Проблемы закладок нет в Delphi 5, потому что там вокруг Bookmark сделан класс ими управляющий, а я имею в виду работу с закладками через ADO. Смотрим опять же в ADO SDK и видим там такое описание: 'Recordset.Bookmark: Устанавливает или возвращает закладку, которая однозначно определяет текущую запись в Recordset. При создании или открытии объекта Recordset каждая из его записей получает уникальную закладку. Для того чтобы запомнить положение текущей записи, следует присвоить текущее значение свойства Bookmark переменной. Для быстрого возвращения к сохраненному в переменной указателю текущей записи в любое время после перехода на другую запись следует указать в значении свойства Bookmark объекта Recordset значение этой переменной'.Казалось бы, какие проблемы? А вот какие: возвращаемое значение всегда одно и тоже для любой записи. И когда мы устанавливаем этот, с позволения сказать, Bookmark, ничего не происходит. И только наш внутренний идентификатор поможет в такой ситуации, кроме того, его значение всегда имеет смысл, даже после закрытия и повторного открытия таблицы, что, в общем-то, удобно. После того как все заработало, я решил проверить скорость работы ADO. У нас может быть ситуации, когда в таблицу добавляется сразу большое количество записей, к примеру, 50-60 тысяч записей за раз. Так вот, когда использовалась BDE, такая операция занимала максимум 10 минут. Угадайте, чему стало равно это время при использовании ADO? Минимум 25 минут на той же самой машине. Если после этого мне будут говорить, что ADO быстрее BDE чуть ли не в 2 раза - позвольте мне с Вами не согласиться. Итак, для нормальной работы мы должны иметь таблицы в первой нормальной форме, для этого делаем автоинкрементное поле с уникальным индексом. Кроме того, если мы можем добавлять больше одной записи за один раз и потом сразу возможно будем их редактировать, нам надо использовать файлы MS Access 2000. ADO и файлы xBASE и Paradox Итак, мы смогли наладить работу через ADO к файлам формата MS Access. Но ведь мы можем и должны использовать файлы xBase и Paradox в качестве обменных файлов. Попробуем это сделать. Все примеры какие я видел в книгах работают одинаково - через 'Microsoft OLE DB provider for ODBC'. А все редакторы, которые делают строку подключения, всегда показывают только mdb файлы в диалоге, в котором задается путь к файлу БД. Что-то тут нечисто, подумал я - а как же тот же самый Access это делает? Ведь явно не через ODBC, стало быть, есть какая-то хитрость. После примерно недельных поисков в Интернете решение было найдено. Да, действительно можно использовать 'Microsoft Jet 4.0 OLE DB Provider'. Чтобы не рассказывать долго, представим, что у нас на диске D в корне лежит файл Test.dbf формата dBase 5.0. Строка коннекта для этого случая будет выглядеть так: {'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\; Extended Properties = dBase 5.0; Mode = Read|Write|Share Deny None; Persist Security Info = True';}И это все. Самое интересное во всей это строке - секция 'Extended Properties'. Чтобы знать, что конкретно для разных форматов надо писать в Extended properties, загляните в реестр Windows на следующую ветку: HKEY_LOCAL_MACHINE\Software\Microsoft\Jet\4.0\ISAM Formats Там перечислены все поддерживаемые в данном случае форматы. После опытов над форматом dbf оказалось, что все выше сказанное для формата mdb совершенно не относится к этому формату - и все требования про первую форму можно и не соблюдать! В общем, загадка природы. А вот формат Paradox - это оказалась песня на меньшая, чем mdb. И вот почему - здесь все требования о первой форме таблицы в действии, но ведь мы не можем создавать таблицу, потом говорить пользователю 'Слышь, мужик, а теперь метнулся, запустил Paradox и создал первичный ключ на эту таблицу. А потом нажмешь на ОК и мы продолжим'. Это несерьезно. Стало быть, этот ключ надо создавать нам самим. Хорошо, запускаем справку по MS Jet SQL и ищем раздел создания индексов или первичных ключей. Находим следующее:CREATE INDEX имя_индекса on название_таблицы(название_поля)with PRIMARY. ALTER TABLE название_таблицы ADD CONSTRAINT имя_ограничения PRIMARY KEY(название_поля)Все далее сказанное абсолютно одинаково для обоих вариантов. Предположим, что наша таблица называется ExpTbl.db и поле, на которое мы хотим наложить первичный ключ, называется IntrernalID. Хорошо, подключаемся к таблице и задаем такую строку SQL для исполнения: CREATE INDEX My_Index ON ExpTable (InternalID) WITH PRIMARYЗапустим на выполнение. Ого, а что это мы видим? Вот те на - очередное сообщение об ошибке. При этом сообщение как всегда очень содержательное применительно к нашему случаю. ![]() Исправляем SQL: CREATE INDEX ExpTable ON ExpTable (InternalID) WITH PRIMARYЗапускаем, смотрим - все отлично. Чтобы никто больше мучился с этим делом, я хотел бы привести самые значащие ограничения для драйвера PARADOX, которые я нашел в MSDN:
Для добавления данных в эти таблицы, мы можем вставлять их по одной (Table.Append (Insert); Table.Post), а можем воспользоваться вариантом SELECT … INTO, INSERT … INTO. Поговорим теперь именно о втором варианте работы. Смотрим файл справки MS Jet SQL. SELECT поле_1[, поле_2[, ...]]INTO новаяТаблица[in внешняяБазаДанных] FROM источникЛадно, пробуем. Пусть мы имеем в качестве источника данных mdb файл и хотим сохранить данные из таблицы SourceTable в таблицу формата Paradox 7.0 TestTable.db, расположенную в корне диска D:. Казалось бы: SELECT * INTO[TestTable.DB] in 'D:\' FROM SourceTable Нет, очередная ошибка. Вот, что мы видим. ![]() SELECT * INTO[TestTable] in 'D:\ TestTable.DB' FROM SourceTable Получим очередное сообщение об ошибке. ![]() Ага, стало быть, файл для экспорта должен уже существовать? Ладно, не проблема, давайте создадим его и попробуем еще раз. ![]() SELECT * INTO[Paradox 7. x; DATABASE = D: \]. [TestTable#0DB]FROMSourceTableСоздавать таблицу до операции экспорта нет надобности - таблица будет создана автоматически, все поля будут созданы правильного типа. В получившейся таблице будут все данные из SourceTable. Единственная проблема - Вы не сможете больше редактировать данные в этой таблице, потому (см. выше) для этого необходим первичный ключ, а создать его для таблицы, в которой уже есть записи нельзя. Самое потрясающее это название раздела MSDN, где я нашел этот ответ - 'Как, используя ADO, открыть таблицу Paradox, защищенную паролем'. Как ЭТО имеет отношение к этому синтаксису SQL, я так и не понял, честно говоря. Вот, в общем-то, все, что я хотел написать. Осталось еще много интересного в этой области. Чего стоит, например установка правильных кодовых страниц для результирующих файлов и много чего подобного. Это тема либо для продолжений этой статьи, либо для отдельных статей. Очень надеюсь, что кто-нибудь нашел тут полезные для себя сведения. При написании статьи использовались следующие материалы:
Опыт использования ADO для доступа к базам данных форматов MS Access, xBase и Paradox В статье автор делится своим опытом использования ActiveX Data Objects (ADO) для доступа к базам данных форматов MS Access, xBase и P Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |