Досвід використання ADO для доступу до баз даних форматів MS Access xBase і Paradox

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Іванов Денис Михайлович

Спонукало мене на написання цієї статті та обставина, що коли я приступав до цієї роботи (я маю на увазі використання ADO), я розміщував свої запитання у багатьох конференціях, а відповідей на них не отримано до цих пір і, більш того, ці ж питання стали задаватися за новою, а відповідей на них як не було, так і немає. На деякі з них я відповідав, а потім подумав, що не всі будуть переглядати конференцію цілком, та й коли все зведено в одному місці воно і краще. Крім того, розумної літератури з використання ADO практично немає ніякої. Наприклад, мені не вдалося знайти в солідних за обсягом книгах пана Архангельського необхідну мені інформацію. Або ще приклад - Microsoft Press 'Довідник по OLE DB'. Тут інший ухил - інформації багато, надто багато, а прикладів ніяких (але це взагалі проблема довідок від Microsoft - написано багато, а прикладів використання майже немає).

Сподіваюся, що ті відомості, які я наведу тут, допоможуть колегам по цеху у вирішенні його завдань.

Причини переходу від BDE до ADO

Отже, щоб було зрозуміло що до чого, спочатку поясню, навіщо ж знадобився перехід до ADO. Я працюю програмістом в компанії, яка займається написанням оболонки для створення геоінформаційних систем (ГІС). Тобто є якась красива карта і необхідне отримання якихось атрибутивних даних по об'єктах на цій карті розміщеним. При цьому атрибутивні таблиці не мають заздалегідь встановленої структури - тільки якісь встановлені поля, де користувач не бачить, але які використовуються для зв'язку об'єктів на карті і записів в базі даних.

Отже, для зберігання атрибутивної інформації був обраний формат MS Access, який має та обставина, що всі таблиці зберігаються в одному файлі (на відміну від Paradox і Dbase) і не вимагає при цьому запущеного сервера, як, приміром, Interbase. Необхідна також зв'язок з файлами форматів dbf і db для завантаження / вивантаження даних до / з БД. Для написання програми ми використовуємо Delphi 4, а для підключення до файлів БД використано BDE. І все це було чудово, але ось з'явилися дві важливі обставини:

Вийшов MS Access 2000. BDE відмовляється працювати з цим форматом. Як мені вдалося знайти відповідь після довгих пошуків на сайті Inprise - Inprise не знає як робити коннект до цього формату. Цитата: 'Для доступу до даних MS Access ми використовуємо DAO 2.5, який не може працювати з форматом MS Access 2000. Якщо Вам необхідний доступ до БД формату MS Access 2000, використовуйте, будь ласка, компоненти ADO Delphi 5. За нашою (можливо невірної) інформації причина тут у відсутності офіційної документації від Microsoft.

2. Була знайдена цікава особливість поведінки BLOB потоків під управлінням Windows NT 4. Припустимо, нам необхідний доступ до BLOB полів таблиць в БД формату MS Access 97. Як зробити підключення через BDE до MS Access 97 я говорити не буду, тому що багато хто знає, а хто не знає, той легко знайде цю інформацію. Отже, підключення вироблено. Дуже добре. Ось фрагмент програми:

Var

AStream: TBLOBStream;

Data: Integer;

Begin

/ / Відкриваємо таблицю (звичайний TTable)

ATable.Open;

/ / Створюємо потік.

AStream: = TBLOBStream (ATable.CreateBLOBStream (ATable.FieldByName ('Поле')));

/ / Що-небудь читаємо з нього.

AStream.Read (Data, SizeOf (Data));

/ / Звільняємо потік і закриваємо таблицю.

AStream.Free;

ATable.Close;

End;

Здавалося б - абсолютно тривіальний код. АЛЕ! Рядок, де проводиться читання з потоку, викликає виняткову ситуацію - 'External error -

EEFFACE '. І у вихідних текстах VCL від Delphi 5 ми знаходимо приголомшливе пояснення - це, виявляється, 'C + + Exception'. Цікаво, а при чому тут C + +? Єдина відповідь, який я знаю, - Delphi написана на C + +.

Плюс до всього, якщо ви запускаєте цю програму з-під Delphi - помилка не виникає, а якщо запускаєте її прямо в Windows - помилка буде неодмінно. Я дійшов у своїх пошуках до викликів прямих викликів BDE API - ось там-то помилка і виникає, так що я думаю тут чергова помилка BDE, хоча я використав на той момент саму останню версію з сайту Inprise - BDE 5.11.

Так що, панове, якщо Ви використовуєте щось подібне у своїх програмах, то знайте, що під Windows NT 4.0/Windows 2000 Ваші програми працювати не будуть. Найцікавіше, що компоненти з бібліотеки VCL, які використовують подібний метод для отримання даних (наприклад, TDBRichEdit) теж не працюють!

Отже, цих двох причин виявилося достатньо для нашої фірми, щоб розпочати перехід від BDE до ADO.

ADO і файли формату MS Access

До чого я навів цю цитату - в результаті всієї цієї роботи я прийшов до висновку, що у нас, програмістів, і у Microsoft різний погляд на фразу 'Забезпечується доступ до даних'. Ми (ну або, принаймні, я) у цій фразі бачимо наступне зміст 'забезпечується доступ до даних для їх перегляду і редагування (тобто редагування, видалення і додавання нових даних) ". Що має на увазі Microsoft можна тільки здогадуватися, але явно, що без особливих проблем досягається тільки перегляд даних. Крім того, практично всі приклади в літературі обмежуються отриманням даних саме для перегляду, після чого слід кілька бадьорих фраз і все закінчується. Як говориться вище - різні точки зору ...

Отже, перш за все, робота була обмежена умовою розробки в Delphi 4. Причин цього багато, але до цієї статті це відношення не має. Просто - програма, розроблена в Delphi 4 повинна працювати через ADO. Тому приступили до пошуку компонент, що забезпечують таку роботу. Знайшли їх досить багато, як платних, так і безкоштовних. Все, що буде написано, однаково і для всіх варіантів і навіть для Delphi5. Виняток становить тільки робота з закладками в Delphi 5.

ADO була взята на той момент сама остання версія з сайту Microsoft - це ADO 2.6.

Отже, візьмемо файл mdb формату MS Access 97. Його можна зробити з допомогою хоча б самого Access. І створимо там невелику таблицю, наприклад, таку:

Object_ID Integer - ідентифікатор об'єкта на карті

Object_Description Text (50) - опис об'єкта на карті

Введемо туди будь-які дані (абсолютно все одно які). Тільки треба врахувати, що в силу специфіки роботи у нас можуть бути описи, яким поки об'єкти не відповідають. Така зв'язка буде виконана пізніше користувачем. Ну, спробуємо вивести вміст таблиці в DBGrid. Ага, вийшло. Наприклад, як на картинці:

Досвід використання ADO для доступу до баз даних форматів MS Access, xBase і Paradox

Ніби як все нормально і доступ до даних ми отримали.

А тепер давайте, уявимо себе користувачами і спробуємо що-небудь виправити або додати. Наприклад, додамо кілька порожніх записів і спробуємо внести туди дані. Додаємо. Нормально. Тепер внесемо дані і натиснемо POST. І що ми бачимо?

Досвід використання ADO для доступу до баз даних форматів MS Access, xBase і Paradox

Ага. Цікаво, а при чому тут ключ, якщо у нас на таблицю ключ не накладено? Пробуємо додати новий запис, видалити запис без Object_ID. Результат однаковий - все те саме повідомлення про помилку. І що ж робити? Запускаємо MS Access, пробуємо там, і бачимо, що там все відмінно. Стало бути, що щось не так ми робимо з ADO. І тут ми згадуємо, що коли ми створювали таблицю в MS Access, він пропонував створити ключові поля для цієї таблиці. А після довгих пошуків в ADO SDK я знайшов цьому таке пояснення: ADO припускає, що таблиця буде в першій нормальній формі. Якщо хто не пам'ятає головна вимога першої форми - відсутність повторюваних записів.

У даному випадку ми не можемо створити ключ на те, що є. Що ж робити? І тут приходить на розум просте рішення: додамо ще одне поле, щоб кожна запис була однозначно визначена (тобто якийсь внутрішній ідентифікатор). Щоб не думати про вміст цього нового поля, робимо зовсім просто - нехай це буде автоінкрементні полі, і створимо на нього первинний ключ. Дуже добре! Робимо, - все працює. Поки ми не додаємо більше одного запису. Якщо ми їх додамо поспіль кілька, ми побачимо дуже цікаву ситуацію як на картинці.

Що тут цікавого? А те, що вміст Internal_ID для всіх цих записів дорівнює нулю, хоча це автоінкрементні полі! І Table.Refresh тут не допомагає! Тільки закриття і подальше відкриття таблиці призводить до того, що ми бачимо те, що і очікувалося.

А поки ми не маємо правильних ідентифікаторів, наявність такого поля не дає нічого. Вище наведені помилки будуть продовжувати сипатися як з рогу достатку. Але от тільки закривати - відкривати таблицю щоразу після додавання нового запису для того, щоб автоінкрементні поле приймало правильні значення - це сильно. Так не піде. Ось так ADO, подумав я, а давай-но спробуємо MS Access 2000. І тут виявилося, що там все нормально працює: додаємо запис, робимо збереження (Post) автоінкрементні поле відразу приймає правильне значення.

У результаті я можу зробити тільки один висновок - Microsoft активно, всіма доступними засобами, намагається змусити користувачів переходити до своїх нових продуктів.

А ось чому в Access все нормально працює - це загадка. Я думаю, що сам-то він користується якимись своїми методами, або в процесі роботи у нього є якийсь ідентифікатор запису типу щойно придуманого нами.

Ну а щоб користувач не бачив цього внутрішнього ідентифікатора (адже він потрібен тільки нам) робимо це поле невидимим. Сподіваюся, що всі знають, що це робиться через TField.Visible: = FALSE.

Хто-небудь може заперечити: а навіщо нам такий ідентифікатор, ми можемо запису ідентифікувати з яких-небудь своїх полях. Заради Бога! Але тут є ще одна проблема і ця проблема називається закладки.

Проблеми закладок немає в 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_MACHINESoftwareMicrosoftJet4.0ISAM 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

Запустимо на виконання. Ого, а що це ми бачимо? Ось ті на - чергове повідомлення про помилку. При цьому повідомлення як завжди дуже змістовне стосовно нашого випадку.

Досвід використання ADO для доступу до баз даних форматів MS Access, xBase і Paradox

Неправильних символів немає, синтаксис правильний, довжина назви ключа теж нормальна. Я так думаю тому, що якщо виконати це через BDE, все буде працювати зі свистом.

Висновок один - знову чергову вимогу ADO, яке одразу не зрозумієш. Гаразд, запускаємо он-лайн MS MSDN і робимо запит на PARADOX. Бачимо щось близько 50 документів. І десь в 35-36 документі я знайшов відповідь маленькими літерами внизу екрану! Зараз я вам скажу в чому проблема - тримайтеся міцніше: ім'я первинного ключа повинно збігатися з назвою таблиці, а імена індексів з іменами полів. Неслабо.

Виправляємо SQL:

CREATE INDEX ExpTable ON ExpTable (InternalID) WITH PRIMARY

Запускаємо, дивимося - все відмінно.

Щоб ніхто більше мучився з цією справою, я хотів би навести самі значущі обмеження для драйвера PARADOX, які я знайшов в MSDN:

Для того, щоб Ви мали можливість проводити дії по додаванню, видалення записів або редагування даних у таблиці, таблиця повинна мати первинний ключ.

Первинний ключ повинен бути визначений для перших 'n' полів таблиці.

Ви не можете створювати для таблиці індекси, якщо для нього не визначено первинний ключ.

Перший створюється для таблиці унікальний індекс буде створений як первинний ключ.

Первинний ключ може бути створений для таблиці тільки в тому випадку, якщо в ній немає жодного запису.

Дії з додавання або видалення полів у таблиці повинні бути зроблені до того, як для неї створено первинний ключ.

До речі, з мого досвіду видалити одного разу створений первинний ключ для таблиці неможливо.

Отже, для роботи через ADO з файлами xBase або Paradox, нам необхідно вказувати потрібний драйвер у секції Extended Properties і в секції Data Source тільки шлях до файлу. Для xBase на цьому всі труднощі закінчені, а от для Paradox необхідно завдання первинного ключа як для формату MS Access, при цьому є певні обмеження при завданні назв ключів, так само як і можливих індексів.

Те, про що мова піде далі вже не відноситься до організації роботи з таблицями xBase і Paradox через ADO, а скоріше згадка про один корисному досвіді.

Для додавання даних в ці таблиці, ми можемо вставляти їх по одній (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

Ні, чергова помилка. Ось, що ми бачимо.

Досвід використання ADO для доступу до баз даних форматів MS Access, xBase і Paradox

Ага, добре, давайте спробуємо вказати таблицю в дорозі:

SELECT * INTO [TestTable] IN 'D: TestTable.DB' FROM SourceTable

Одержимо чергове повідомлення про помилку.

Досвід використання ADO для доступу до баз даних форматів MS Access, xBase і Paradox

Ага, отже, файл для експорту повинен вже існувати? Гаразд, не проблема, давайте створимо його і спробуємо ще раз.

Досвід використання ADO для доступу до баз даних форматів MS Access, xBase і Paradox

Ну, загалом, бажаючі можуть ще поекспериментувати, а для інших я скажу як робиться:

SELECT * INTO [Paradox 7.x; DATABASE = D:]. [TestTable # DB] FROM SourceTable

Створювати таблицю до операції експорту немає потреби - таблиця буде створена автоматично, всі поля будуть створені правильного типу. У вийшла таблиці будуть всі дані з SourceTable.

Єдина проблема - Ви не зможете більше редагувати дані в цій таблиці, тому (див. вище) для цього необхідний первинний ключ, а створити його для таблиці, в якій вже є записи не можна.

Найбільш приголомшливе це назва розділу MSDN, де я знайшов цю відповідь - 'Як, використовуючи ADO, відкрити таблицю Paradox, захищену паролем'. Як ЦЕ має відношення до цього синтаксису SQL, я так і не зрозумів, чесно кажучи.

Ось, загалом-то, все, що я хотів написати. Залишилося ще багато цікавого в цій галузі. Чого вартий, наприклад установка правильних кодових сторінок для результуючих файлів і багато чого подібного. Це тема або для продовжень цієї статті, або для окремих статей. Дуже сподіваюся, що хто-небудь знайшов тут корисні для себе відомості.

Список літератури

Матеріали Королівства Delphi.

Довідкові файли Delphi 4 і Delphi 5.

Вихідні коди VCL Delphi 4 і Delphi 5.

MS ADO SDK і приклади MS ADO SDK.

MS MSDN.

А.Я. Архангельський 'Мова SQL у Delphi 5'


Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Реферат
34.4кб. | скачати


Схожі роботи:
Використання Internetintranet технологій для організації доступу до баз даних
Основи використання WWW - технологій для доступу до існуючих баз даних
Основи використання WWW - технологій для доступу до існуючих баз даних
Створення бази даних критичних властивостей речовин в редакторі баз даних MS Access
Проектування баз даних MS Access
Використання баз даних та інформаційно пошукових систем для раціона
Система баз даних MS Access Створення бази
Використання баз даних та інформаційно-пошукових систем для раціонального ведення діловодства
Засоби доступу до баз даних в Internet і вільно доступна СУБД POSTGRES95
© Усі права захищені
написати до нас