ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

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

     

    Інформатика, програмування

    Досвід використання 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. Ага, вийшло. Наприклад, як на зображення:

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

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

    Ага. Цікаво, а при чому тут ключ, якщо у нас на таблицю ключ не накладено? Пробуємо додати новий запис, видалити запис без 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

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

    Неправильних символів немає, синтаксис правильний, довжина назви ключа теж нормальна. Я так думаю тому, що якщо виконати це через 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

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

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

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

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

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

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

    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'

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status