Введення в ADO h2>
1. Введення. H2>
ADO - інтерфейс, покликаний забезпечити клієнтське
додаток доступом і можливостями маніпулювання зовнішніми даними. ADO
є інтерфейсом програмного рівня до OLE DB (інтерфейсом надзвичайно
зручним і високопродуктивним). ADO і OLE DB складають разом технологію
Універсального доступу до даних (UDA). При цьому, будучи інтерфейсом високого
рівня до OLE DB, ADO використовує OLE DB постачальники даних (на даний момент це,
в основному, провайдери реляційних баз даних, хоча вже з'являються постачальники
для нереляціонних джерел даних і систем електронної пошти). p>
Варто відзначити, що корпорація Microsoft під
публічно заявляє, що ADO найближчим часом замінить велике розмаїття
моделей і технологій доступу до даних, включаючи такі методи самої Microsoft,
як DAO, RDO. p>
Примітка: p>
Надалі в статті мається на увазі, що читач
знайомий з інтерфейсами OLE DB, такими поняттями, постачальник і споживач даних,
має базові знання з COM. p>
Також хотілося б відзначити, що ця стаття з'явилася
результатом спроби автора ретельно розібратися в технології ADO і
систематизувати отримані в результаті знання (а також відомості з
літ.істочніков) і, природно, стаття не може на щось претендувати (крім
критики J,) тим більше на оригінальність. p>
2. Об'єктна модель ADO. H2>
ADO складається з наступних основних компонентів: p>
Об'єкти: p>
Connection. ADO використовує об'єкти Connection для
надання окремих сполук з джерелом даних. p>
Command. Об'єкти Command використовуються для
надання конкретних команд, що виконуються над джерелом даних. Ці
об'єкти використовуються для відстеження параметрів, пов'язаних з командою. p>
Parameter. Об'єкти Command містять колекцію
Parameters, що включає всі пов'язані з командою параметри. Кожен окремий
об'єкт Parameter служить для зберігання інформації про параметр, переданому в
виконувану команду або повертається в ній. p>
Recordset. Об'єкти Recordset забезпечують
взаємодія з даними. Вони використовуються для зберігання набору записів,
що повертається з джерела даних. p>
Field. Об'єкти Recordset містять колекцію об'єктів
Field, що використовуються для для роботи з окремими стовпчиками групи рядків. P>
Property. Об'єкти Connection, Command, Recordset, Field містять колекцію Properties об'єктів Property. Об'єкти Property служать
для подання додаткових параметрів або властивостей об'єкта ADO, які не
можуть управлятися вбудованими властивостями об'єкта. p>
Error. Призначені для представлення інформації про
помилки, які можуть відбуватися в рамках однієї операції. p>
Колекції: p>
Fields. p>
Properties. p>
Parameters. p>
Errors. p>
3.Немного про директиву # import h2>
Директива препроцесора # import дозволяє
автоматично створювати бібліотеку типів COM до класів С + + для COM
інтерфейсів. Це дуже зручно, якщо у вас не маєте доступу до MIDL-файлів.
Використання цієї директиви Visual C + + істотно спрощує роботу з
об'єктами, методами і властивостями ADO. p>
При включенні директиви # import препроцесор
компілятора формує два заголовків файлу, що містять бібліотеку типів в
вигляді вихідного тексту на С + +. Головний заголовки (з розширенням. Tlh)
містить опис класів плюс оголошення інтелектуального покажчика (smart
pointer - _com_ptr_t): p>
_COM_SMARTPTR_TYPEDEF (INameOfInterface,
__uuidof (INameOfInterface )); p>
При подібному використанні макросу
_COM_SMARTPTR_TYPEDEF Компілятор оголошує інтелектуальний покажчик
INameInterfacePtr. p>
Примітка: _com_ptr_t - шаблонний клас,
інкапсулює покажчик на COM-інтерфейс. Об'єкт _com_ptr_t автоматично
викликає методи інкапсульованими в ньому інтерфейсу AddRef () при створенні
об'єкта і Release () при виході об'єкта з області видимості, коректно керуючи
існуванням COM-об'єкта. p>
Допоміжний заголовки (. tli) містить
реалізацію класів бібліотеки типів. p>
Директива # import має вигляд: p>
# import "ім'я_файлу" [атрибути] p>
або p>
# import <ім'я файлу> [атрибути] p>
ім'я_файлу - зазвичай файл наступних типів:. tlb,. odl,
. dll,. exe,. ocx. p>
атрибути: p>
exclude - виключає генерується в заголовків
файлах коду певні елементи або бібліотеки типів p>
high_method_prefix - задає префікс, який буде
ставиться на початку імен методів і властивостей верхнього рівня p>
high_property_prefixes - задає префікс для
стандартних імен Get, Put і PutRef, яка буде поставлена на початку імені
методу при зверненні до властивості. p>
implementation_only - забороняє створення основного
заголовки p>
include (...) - включає об'яви інших бібліотек
типів, визначення яких зустрічаються в інших системних файлах p>
inject_statement - поміщає рядок тексту на початку
оголошення оголошення простору імен заголовки для бібліотеки
типів. p>
named_guides - вказує компілятору визначити і
ініціалізувати змінні зі старими GUID p>
no_auto_exclude - забороняє автоматичне виключення
визначень елементів p>
no_implementation - забороняє генерацію файлу. tli p>
no_namespace - Не використовується простір імен,
специфікація якого знаходиться в операторі library p>
raw_dispinterfaces - вказує компілятору
генерувати всі виклики методів і властивостей за допомогою функції Invoke і
повертати код помилки HRESULT. Оболонки верхнього рівня не генеруються. P>
raw_interfaces_only - дозволяє надати
вміст бібліотеки типів тільки нижнього рівня, пригнічуючи генерацію заготовок
функцій верхніх рівнів p>
raw_method_prefix - приєднує до заданого імені
префікс raw_, який зазвичай підключається до функцій-членів низького рівня p>
raw_native_types - змушує використовувати типи даних
нижнього рівня (замість _bstr_t - BSTR, замість _variant_t - VARIANT) p>
raw_property_prefixes - дозволяє задати префікс
нижнього рівня для методів-властивостей put, get та putref p>
rename - перейменовує бібліотеку типів і
запобігти повторне використання імен p>
rename_namespace - вказує простір імен,
що містить інформацію про бібліотеку тіпов.Ітак, після наданих роз'яснень з
директиві # import, розглянемо, яким чином її (директиву) можна використовувати
для включення інтерфейсів ADO в наш додаток. p>
пропишемо в файл stdafx.h (наприклад) горезвісну
директиву в такий спосіб: p>
# import
"c: Program FilesCommon FilesSystemADOmsado15.dll" p>
no_namespace
rename ( "EOF", "ADOEOF") p>
У даному випадку створюються класи з бібліотеки типів
msado15.dll, що реалізує об'єкти ADO і що поставляється в рамках OLE DB SDK. p>
У параметрі rename доводиться перейменовувати ADO
константу EOF, так як вона вже використовується в заголовних файлах stdio.h,
ios.h, stream.h, включених до afxwin.h. p>
4. Ініціалізація COM. h2>
Тут все просто: p>
перед роботою з об'єктами ADO необхідно
ініціалізувати середу COM. Робиться це за допомогою виклику API функції p>
HRESULT CoInitialize (LPVOID pvReserved); p>
де p>
pvReserved пареметр, що дорівнює NULL. p>
Для вивантаження COM застосовується функція p>
void CoUninitialize (); p>
5. Встановлення з'єднання з джерелом даних. P>
Для цих цілей, як зазначалося вище, використовується
об'єкт Connection (підключення до джерела даних і керування цим
підключенням здійснюється за допомогою методів Open (), Close () об'єкта
Connection). Хоча, варто помітити, що ви можете не створювати його
самостійно. Можна просто дозволити ADO створити з'єднання, що використовується
об'єктами Recordset і Command. Проте, вам необхідно створити об'єкт Connection,
якщо передбачається управління транзакціями (для створення та управління
транзакціями призначені наступні методи Connection: BeginTrans (),
CommitTrans () і RoolbackTrans ()). p>
Отже, створення з'єднання. Для цього робимо
наступні кроки: p>
1. Оголошуємо покажчик на з'єднання: p>
_ConnectionPtr pConn; p>
2. Створюємо об'єкт Connection за допомогою функції
CreateInstance (): p>
HRESULT
CreateInstance (const CLSID & rclsid, IUnknown * pOuter = NULL, DWORD
dwClsContext = CLSCTX_ALL) p>
де p>
rclsid - CLSID об'єкта; p>
pUnknown - покажчик на зовнішній інтерфейс при
агрегування; p>
dwClsContext - контекст запуску виконуваного коду. p>
Приклад: p>
HRESULT hr; p>
hr =
pConn.CreateInstance (__uuidof (Connection )); p>
або p>
hr =
pConn.CreateInstance (__uuidof (Connection), NULL, CLSCTX_INPROC_SERVER); p>
3. після створення екземпляра класу Connection створюємо
з'єднання. З цією метою викликаємо метод Open об'єкта Connection. p>
HRESULT
Open (_bstr_t ConnectionString, _bstr_t UserID, _bstr_t Password, long
Options = NULL); p>
ConnectionString - рядок з'єднання (см.табл.1.1 і
1.2). p>
UserID - ім'я користувача для підключення до джерела
даних p>
Password - пароль користувача p>
Options - дозволяє вказати, яким чином буде
здійснюватися з'єднання - синхронно (adConnectUnspecified) або
асинхронно (adAsyncConnect). p>
Таблиця 1.1. Вид рядка з'єднання, що передається в
метод Open (...) об'єкта Connection для різних OLE DB постачальників (MSDN) p>
Джерело даних p>
Рядок з'єднання OLE DB p>
Microsoft ® Access p>
Provider = Microsoft.Jet.OLEDB.4.0; Data Source = physical path to. mdb
file p>
Microsoft SQL Server p>
Provider = SQLOLEDB.1; Data Source = path to database on server p>
Oracle p>
Provider = MSDAORA.1; Data Source = path to database on server p>
Microsoft Indexing Service p>
Provider = MSIDXS.1; Data Source = path to file p>
p>
Таблиця 1.2. Вид рядка з'єднання, що передається в
метод Open (...) об'єкта Connection для різних ODBC постачальників даних (MSDN) p>
Джерело даних p>
Рядок з'єднання ODBC p>
Microsoft Access p>
Driver = (Microsoft Access Driver (*. mdb)); DBQ = physical path to. mdb
file p>
SQL Server p>
DRIVER = (SQL Server); SERVER = path to server p>
Oracle p>
DRIVER = (Microsoft ODBC for Oracle); SERVER = path to server p>
Microsoft Excel p>
Driver = (Microsoft Excel Driver (*. xls)); DBQ = physical path to. xls
file; DriverID = 278 p>
Microsoft Excel 97 p>
Driver = (Microsoft Excel Driver (*. xls)); DBQ = physical path to. xls
file; DriverID = 790 p>
Paradox p>
Driver = (Microsoft Paradox Driver (*. db)); DBQ = physical path to. db
file; DriverID = 26 p>
Text p>
Driver = (Microsoft Text Driver (*. txt; *. csv)); = DefaultDir physical path
to. txt file p>
Microsoft Visual FoxPro ® (with a database container) p>
Driver = (Microsoft Visual FoxPro Driver); SourceType = DBC; SourceDb = physical
path to. dbc file p>
Microsoft Visual FoxPro (without a database container) p>
Driver = (Microsoft Visual FoxPro
Driver); SourceType = DBF; SourceDb = physical path to. Dbf file p>
p>
Наступний приклад показує установку з'єднання з базою
даних pubs, що входить в стандартний пакет поставки MS SQL Server 7.0 за допомогою OLE DB постачальника: p>
_ConnectionPtr
pConn = NULL; p>
_bstr_t strConn =
"Provider = sqloledb; Data Source = (local); Initial Catalog = pubs"; p>
try p>
( p>
pConn.CreateInstance (__uuidof (Connection )); p>
pConn-> Open (strConn, "sa ","", adConnectUnspecified); p>
) p>
catch (_com_error e) p>
( p>
// Обробка помилок з'єднання p>
) p>
Примітка: p>
Виключення в ADO. Для обробки виключень ADO
необхідно забезпечити блок catch для об'єкта _com_error. Цей клас
використовується для повернення помилок з класів, згенерованих директивою
# import. Клас _com_error інкапсулює генеруються значення HRESULT і будь-які
об'єкти IErrorInfo, згенеровані постачальником OLE DB. p>
Приклад обробників винятків ADO: p>
void PrintComError (_com_error & e) p>
( p>
_bstr_t
bstrSource (e.Source ()); p>
_bstr_t
bstrDescription (e.Description ()); p>
// Print COM
errors. p>
printf ( "Error
"); p>
printf ( "Code
=% 08lx ", e.Error ()); p>
printf ( "Code
meaning =% s ", e.ErrorMessage ()); p>
printf ( "
Source =% s ", (LPCSTR) bstrSource); p>
printf ( "
Description =% s ", (LPCSTR) bstrDescription); p>
) p>
void
PrintProviderError (_ConnectionPtr pConnection) p>
( p>
// Print Provider
Errors from Connection object. P>
// pErr is a record
object in the Connection's Error collection. p>
ErrorPtr pErr =
NULL; p>
if (
(pConnection-> Errors-> Count)> 0) p>
( p>
long nCount =
pConnection-> Errors-> Count; p>
// Collection
ranges from 0 to nCount -1. p>
for (long i = 0; i
( p>
pErr =
pConnection-> Errors-> GetItem (i); p>
printf ( "Error
number:% x% s ", pErr-> Number, p>
pErr-> Description); p>
) p>
) p>
) p>
За замовчуванням при встановленні з'єднання час очікування
становить 15 сек. Змінити це значення можна завданням перед відкриттям
з'єднання властивості ConnectionTimeout. p>
Якщо потрібно обмежити доступ програми до
джерела даних, перед відкриттям з'єднання необхідно встановити режим
конекту (властивість Mode об'єкта Connection). Mode може містити комбінацію
(порозрядне АБО) наступних значень: p>
adModeRead - Тільки для читання p>
adModeReadWrite - Для читання/запису. p>
adModeShareDenyNone - Дозволити іншим проводити
читання/запис p>
adModeShareDenyRead - Заборонити іншим читання. p>
adModeShareDenyWrite - Заборонити іншим запис p>
adModeShareExclusive - Заборонити іншим читання/запис p>
adModeUnknown - Ні дозволів (за замовчуванням) p>
adModeWrite - Тільки для запису p>
6. Закриття з'єднання p>
Завершується робота з джерелом даних закриттям
з'єднання - викликом методу Close () об'єкта Connection. p>
pConn-> Close (); p>
Частина 2. p>
Отже, продовжимо. p>
7. Набори записів. P>
З'єднання з джерелом даних встановлено. Далі
необхідно власне ці дані отримати і як-то ними керувати. З цією метою
створюється об'єкт Recordset, який інкапсулює набір записів, що повертаються
джерелом. За допомогою цього об'єкта ми зможемо додавати, видаляти, змінювати
запису, в цей об'єкт включений механізм переміщень по записах в наборі даних. p>
7.1. Створення набору записів. P>
Об'єкт Recordset можна створити кількома способами:
в результаті виконання команди (використання методу Execute () об'єкта Command
або Connection), або за допомогою методу Open () безпосередньо об'єкта Recordset.
Розглянемо детальніше останній варіант. Отже, метод Open (). p>
HRESULT Open (const
_variant_t & Source, const _variant_t & ActiveConnection, enum
CursorTypeEnum CursorType, enum LockTypeEnum LockType, long Options); p>
Source - джерело вибірки (набору записів). Може бути
як SQL рядок (запит), так і ім'я таблиці або збереженої процедури на SQL
сервер. p>
ActiveConnection - З'єднання, що використовується для
створення набору записів (вибірки). Може бути передано або у вигляді рядка
з'єднання (при цьому відпадає необхідність створення об'єкта Connection - ADO
автоматично створює з'єднання, яке буде використано для даного
об'єкта Recordset. Покажчик на таке з'єднання можна отримати за допомогою
властивості об'єкта Recordset ActiveConnection), або у вигляді покажчика на вже
створене активне з'єднання. p>
CursorType - тип курсору для створюваного об'єкту
Recordset. Може приймати одне з наступних значень: p>
adOpenUnspecified - невизначений тип курсору. p>
adOpenForwardOnly - односторонній курсор (значення за
замовчуванням). Не підтримує методи MoveFirst () (до початку вибірки), MoveLast ()
(до останнього запису у вибірці), MovePrevious () (до попереднього запису у вибірці).
Також не підтримує використання властивості RecordCount (кількість записів у
вибірці). Чи не відстежуються зміни та доповнення, зроблені іншими
користувачами. p>
adOpenKeyset - курсор, керований по ключовому
численности, який може вільно переміщатися і знаходить деякі види
змін, внесені в строки вибірки. Число записів в такому наборі незмінно.
Ви не зможете побачити доданих іншими користувачами записів, віддалені
іншими користувачами записи залишаються видимі в такій вибірці, хоча і
стають недоступними. p>
adOpenDynamic - динамічний курсор, який може
переміщатися і визначати всі зміни, внесені в дані, що містяться в
вибірці. Найбільш багатофункціональний, але і найдорожчий по витраті пам'яті тип
курсору. p>
adOpenStatic - статичний курсор. На відміну від DAO,
дозволяється модифіковані все ADO Recordset, що навіть мають курсори
adForwardOnly і adOpenStatic. Проте при виборі таких курсорів для вибірки все
зміни, внесені іншими користувачами для вас невидимі. p>
LockType - Тип блокування, що використовується даними набором
записів. Варіанти: p>
adLockReadOnly - тільки читання. p>
adLockPessimistic - блокує рядки, коли ви
починаєте редагування (якщо постачальник підтримує даний тип). p>
adLockOptimistic - блокує зміни тільки при
передачі змін до БД (підтримується всіма постачальниками даних). p>
adLockBatchOptimistic - використовується для пакетних
операцій модифікації. Пакетна модифікація дозволяє вивантажувати безліч
записів, модифікувати їх локально і відсилати зміни постачальника в одному
пакеті. Большінсто провайдерів не підтримують цю блокування. P>
Options - використовується для вказівки виду Source.
Варіанти: p>
adCmdText - текстова команда (в SQL угоді). p>
adCmdTable - таблиця або подання (вона ж --
"вьюха", т.е.view). p>
adCmdStoredProc - збережена процедура p>
adCmdUnknown - невідомий тип (за замовчуванням). p>
Ну що ж, спробуємо відкрити таблицю authors нашої
багатостраждальної бази даних pubs. Попередньо ще треба визначити, чи буде
курсор серверних або клієнтських. Зробимо ми це за допомогою властивості
CursorLocation об'єкта Recordset (варіанти - adUseClient, adUseServer, adUseNone).
Можна також обмежити число що повертаються записів (властивість MaxRecords),
задавати кількість локально Кешована рядків у наборі записів (властивість
CacheSize - за замовчуванням дорівнює одиниці). P>
Приклад: p>
_RecordsetPtr pRst; p>
_bstr_t
strTableName = "authors"; p>
pRst.CreateInstance (__uuidof (Recordset )); p>
pRst-> CursorLocation
= AdUseClient; p>
pRst-> MaxRecords
= 50; p>
pRst-> CacheSize
= 30; p>
pRst-> Open (strTableName, _variant_t ((IDispatch *) pConn, true), adOpenDynamic,
adLocjOptimistic, adCmdTable); p>
7.2. Встановлення фільтра в наборі записів. P>
У ADO є механізм обмеження за будь-яким
критерієм що повертається набору записів - фільтрація вибірки. Саме для цілей
фільтрації об'єкт Recordset має властивість Filter. p>
Властивість Filter являє собою розширення запиту,
заданого в параметрі Source Recordset'a. Рядок, що передається в властивість
Filter, повинна мати вигляд ім'я_поля (стовпця) - Оператор - Значення, наприклад p>
pRst-> Filter =
"au_lname = 'White AND' au_fname LIKE 'J *'"; p>
ім'я_поля - ім'я стовпця з вибірки Recordset. p>
Оператор - <,>, <=,> =, <>, =, або
LIKE p>
Значення - значення, з яким порівнюється значення
поля. Причому для строкових типів даних?? наченням повинна бути укладена в
одинарні лапки, для дати значення укладається між символами #. Допускається
використання (як і в SQL синтаксисі) символів * та%, наприклад при
використанні оператора LIKE. Також допускається застосування логічних
операторів AND і OR для складання комбінованого критерію фільтрації. p>
Властивість Filter також може приймати значення однієї
з нижчеперелічених констант: p>
adFilterNone - Відміняє поточне значення властивості
Filter. P>
adFilterPendingRecords - У режимі пакетної модифікації
(см.ниже) це значення можна використовувати для вибору тільки з тих рядків,
які були змінені, але ще не модифіковані в базі даних. p>
adFilterAffectedRecords - Вибирає рядки, для яких
виконувалася остання операція Delete (), Resync (), UpdateBatch (),
CancelBatch (). p>
adFilterFetchedRecords - вибирає рядки, які в
даний час утримуються в локальному буфері. p>
7.3. Доступ до даних набору записів. P>
Інформацію про рядках (записах) можна отримати,
використовуючи об'єкти Field колекції Fields створеного і відкритого Recordset'a. p>
Колекція Fields містить дві властивості: p>
Count - кількість стовпців у вибірці (більше
правильно, звичайно говорити про кількість об'єктів Field в колекції Fields). p>
Item - надає доступ (повертає посилання) до
об'єкту Field на ім'я або порядковим номером, тобто вам стають доступні
такі властивості об'єкта Field, як ім'я поля, розмір, тип і значення поля. p>
Покажемо це все на прикладі: p>
int nNumFields =
pRst-> Fields-> Count; p>
for (int
i = 0; i
( p>
_bstr_t strName =
pRst-> Fields-> Item [(_variant_t) I] -> Name; p>
_bstr_t strValue =
pRst-> Fields-> Item [(_variant_t) I] -> Value; p>
TRACE ( "% S =
% S (тип:% d) ",
(LPCTSTR) strName, (LPCTSTR) strValue, (short)
pRst-> Fields-> Item (_variant_t) I] -> Type); p>
) p>
// Або те ж саме, але із створенням об'єктів FieldsPtr і
FieldPtr p>
FieldsPtr pFields; p>
FieldPtr pField; p>
pFields =
pRst-> Fields; p>
int nNumFields =
pFields-> Count; p>
for (int
i = 0; i
( p>
pField =
pFields-> GetItem ((_variant_t) i); p>
_bstr_t strName
= pField-> Name; p>
_bstr_t strValue =
pField-> Value; p>
TRACE ( "% S =
% S (тип:% d) ", (LPCTSTR) strName,
(LPCTSTR) strValue, (short) pField-> Type); p>
) p>
У прикладі ми виводимо дані про полях одного запису (за
умовчанням це перший рядок вибірки). Розглянемо методи переміщення по вибірці
даних. p>
Щоб перейти до першого рядку набору записів можна
застосувати метод MoveFirst () об'єкта Recordset. Методи MoveNext (), MoveLast () і
MovePrevious () дозволяють переміщатися по вибірці, відповідно, до наступної
запису, до останньої і попередньої (якщо ці переміщення допускає тип курсору). p>
Об'єкт Recordset має властивості EOF і BOF (назва
властивості EOF ми змінили при підключенні msado15.dll - див. вище), які
дозволяють визначити, що під час переміщення по набору записів досягнута
остання (EOF) або перших (BOF) запис. Відбувається це таким чином: якщо
при переміщенні за вибіркою досягнута перший запис, то при наступному виклику
MovePrevious () властивість BOF набуває значення TRUE, аналогічно, якщо
позиціонована останній запис, то при використанні MoveNext () значення TRUE
набуває властивості EOF об'єкта Recordset. p>
Приклад: p>
int nNumFields =
pRst-> Fields-> Count; p>
while (! pRst-> ADOEOF) ( p>
for (int
i = 0; i
( p>
_bstr_t strName =
pRst-> Fields-> Item [(_variant_t) I] -> Name; p>
_bstr_t strValue =
pRst-> Fields-> Item [(_variant_t) I] -> Value; p>
TRACE ( "% S =
% S (тип:% d) ", (LPCTSTR) strName,
(LPCTSTR) strValue, (short) pRst-> Fields-> Item (_variant_t) I] -> Type); p>
) p>
pRst-> MoveNext (); p>
) p>
Також для переміщення по вибірці даних можна
скористатися методом p>
HRESULT Move (long
NumRecords, const _variant_t & Start = vtMissing); p>
Знакова ціле NumRecords показує, на скільки
записів необхідно переміститься за вибіркою (якщо NumRecords> 0, то
переміститися вперед, якщо NumRecords <0, то назад). p>
Параметр Start задає початкове положення покажчика
поточного запису (якщо Start = 0, то переміщення відбудеться щодо поточної
запису, інакше в Start треба передавати так звану закладку p>
(Значення закладки для поточного рядка можна отримати
з властивості Bookmark вибірки. Якщо зберегти це значення в будь-якій
змінної, то потім його можна привласнити властивості Bookmark і знову зробити це
рядок поточної. Перевірити, що набір записів підтримує закладки можна з
допомогою методу Support () об'єкта Recordset.) p>
на необхідну початкову запис). p>
ADO Recordset дозволяє робити так званий
посторінковий перегляд вибірки. Для цього необхідно властивості в PageSize об'єкта
Recordset вказати кількість рядків, що складають одну сторінку. При цьому з
властивості PageCount можна дізнатися про кількість сторінок у вибірці. p>
7.4. Модифікація даних. P>
Вставка рядків у Recordset здійснюється за допомогою
методів AddNew () і Update (). p>
Метод AddNew () безпосередньо додає новий рядок
(і робить її поточної) в наборі записів. p>
HRESULT
AddNew (const _variant_t & FieldList, const _variant_t & Values); p>
FieldList - масив імен або номерів ініціалізіруемих в
рядку полів. p>
Values - масив ініціалізувалися значень для цих
полів. p>
Далі рядок можна модифікувати за допомогою об'єктів
колекції Fields (якщо це необхідно), після чого зміни можна зберегти в
базі даних, викликавши метод Update () (якщо при виклику методу AddNew () в нього
передавалися ініціалізувалися значення, Update () викликати не треба). p>
HRESULT
Update (const _variant_t & FieldList, const _variant_t & Values); p>
Як видно з визначення, в Update (...), так само як і в
AddNew (...) можна передавати масив імен (або номерів) модифікується полів і
нові значення. p>
Приклад додавання запису: p>
pRst-> AddNew (); p>
pRst-> Fields-> Item [ "au_lname"] -> Value
= _bstr_t ( "Усов "); p>
pRst-> Fields-> Item [ "au_fname"] -> Value
= _bstr_t ( "Віталій М. "); p>
pRst-> Update (); p>
Видалити запис в наборі записів можна за допомогою методу
Delete (...) об'єкта Recordset. P>
HRESULT Delete (enum
AffectEnum AffectRecords); p>
AffectRecords приймає одне з наступних значень: p>
adAffectCurrent - видалити поточний рядок (за замовчуванням) p>
adAffectGroup - видаляє всі рядки, що задовольняють
критерієм властивості Filter. p>
adAffectAll - видаляє всі записи. p>
adAffectAllChapters - видаляє всі записи голови.
(посилання на діапазон рядків джерела даних. Як правило, посилання на інший
Recordset. Глава дозволяє реалізувати відносини спадкоємець-батько між
об'єктами Recordset.) p>
Якщо Recordset знаходиться в режимі безпосереднього
редагування, то помічені рядки видаляються негайно в джерелі даних.
Якщо ж застосовується режим пакетної модифікації (нарешті-то й до нього дійшли), то
рядка втечуть після виклику методу UpdateBatch (). p>
Що ж таке "режим пакетної модифікації"???
Все дуже просто - деякі постачальники даних дозволяють кешувати вибірки
локально, вносити до них зміни і потім передавати всю вибірку (або зміни
в ній) джерела даних одночасно в одному пакеті (а не по одному рядку). Як
зазначалося вище, для використання пакетної модифікації необхідно при створенні
об'єкта Recordset використовувати прапор adLockBatchOptimistic. Для передачі
змін у вибірці джерела даних в пакетному режимі необхідно викликати метод
p>
HRESULT
UpdateBatch (AffectEnum AffectRecords); p>
Де AffectRecords: p>
adAffectCurrent - оновити поточний рядок (по
замовчуванням) p>
adAffectGroup - оновити всі рядки, що задовольняють
критерієм властивості Filter. p>
adAffectAll - оновити всі записи. p>
adAffectAllChapters - оновити всі записи голови.
(посилання на діапазон рядків джерела даних. Як правило, посилання на інший
Recordset. Глава дозволяє реалізувати відносини спадкоємець-батько між
об'єктами Recordset.) p>
Якщо після модифікації даних ви вирішили скасувати
зміни, зробити це можна за допомогою методів CancelUpdate () і
CancelBatch (AffectEnum AffectRecords) для режимів невідкладної модифікації та
пакетної, відповідно. p>
Список літератури h2>
Для підготовки даної роботи були використані
матеріали з сайту http://www.realcoding.net/
p>