Курсоры в ADO
( перевод одноимённой статьи с сайта delphi.about.com )
В Delphi компоненты ADOExpress довольно приятны в
использовании. Однако программирование
компонент ADOExpress весьма отличается от
традиционного Delphi программирования в
компонентах TTable и TQuery, основанных на BDE.
Естевственно, что если Вы привыкли к компонентам
BDE dataset, то сразу же заметите различие в
количестве возможностей и свойств, а так же в
стиле программирования BDE и ADO.
В основе ADO лежит объект Recordset (aka Dataset). Этот
объект является результатом Query команды (например,
выражение SELECT компонента TADOQuery). Когда ADO-приложение
получает строки из базы данных, то объект ADO Recordset
формирует необходимую информацию и операции,
допустимые для получаемых данных. При этом ADO
использует курсоры, чтобы хранить набор
строк для обработанной записи. Так же курсор
содержит в себе текущую позицию в записи (recordset).
Обычно, при разработке приложения, курсоры
используются при создании записей, а так же при
перемещении по записям (вперёд или назад).
В ADO курсоры имеют три функции. Первая, это тип
курсора, определющая допустимые перемещения в
пределах курсора, а так же будут ли отражаться
изменения пользователей в записи. Вторая, это
местоположение курсора, определяющая место
хранения записи, в то время, пока курсор остаётся
открытым. Третья, это тип блокировки курсора,
которая определяет как ADO datastore будет блокировать
строки, если Вам потребуется внести изменения.
Каждый раз когда мы будем открывать
определённую запись ADO, то мы будем открывать её с
определённым типом курсора.
Класс TCustomADODataSet содержит набор свойств, событий
и методов, для работы с данными, доступными через
ADO datastore. Все классы-потомки от TCustomADODataSet (такие
как TADODataSet, TADOTable, TADOQuery, и TADOStoredProc) совместно
используют некоторые общие свойства. В каждом из
этих классов присутствуют три свойства,
соответствующие функциям курсоров, описанным
выше: CursorType, CursorLocation, и LockType. Давайте
рассмотрим эти свойства по-подробнее.
CursorType
ADO содержит четы опции для данного типа курсора:
dynamic, keyset, forward-only и static. Так как каждый тип курсора
ведёт себя работает по разному, то несомненно Вы
извлечёте пользу из каждого из этих видов
курсоров.
Свойство CursorType указывает на то, каким образом
Вы будете перемещаться по записям а так же какие
изменения будут видны в записях базы данных,
после того как Вы получите из неё данные. В Delphi
классах ADO типы курсоров задаются в TCursorType.
ctDynamic
Позволит Вам видеть добавления, изменения и
удаления, сделанные другими пользователями, а
также позволит делать все типы перемещения по
записи (Recordset) не полагаясь на закладки. Однако
закладки можно использовать, если они
поддерживаются. Для этого существует метод Supports
в ADODataset, который сигнализирует о поддержке
определённых типов операций. Следующее
выражение позволяет определить, поддерживаются
закладки или нет:
if ADOTable1.Supports(coBookmark) then ...
Если несколько пользователей одновременно
вставляют (insert), апдейтят (update), или удаляют (delete)
строки в базе данных, то лучше всего выбрать
курсор dynamic.
ctKeyset
Ведет себя подобно динамическому курсору, за
исключением того, что Вы не сможете видеть записи,
которые добавляют другие пользователи, а так же
не сможете получить доступ к записям, которые
удаляются другими пользователями. Изменение
данных другими пользователями будет все еще
видимо. Этот тип всегда поддерживает закладки и
поэтому позволяет все типы перемещения по
записям (Recordset).
ctStatic
Обеспечивает статическую копию набора записей,
чтобы использовать её для поиска данных и
генерации отчётов. Данный тип всегда разрешает
закладки и поэтому позволяет все типы движения
по записям. Добавления, изменения, или удаления
другими пользователями не будут видимы.
Статический курсор ведет себя подобно
компоненту BDE Query со свойством RequestLive
установленным в False.
ctForward-only
Ведет себя идентично динамическому курсору за
исключением того, что позволяет Вам пролистывать
по записям только вперед. Это увеличивает
производительность в ситуациях, где Вы
необходимо делать только один проход по набору
записей (Recordset).
Обратите внимание: если свойство CursorLocation в
компоненте ADO dataset установлено в clUseClient, то Вы
сможете использовать только опцию ctStatic.
Так же обратите внимание: что если Вы запросите
тип курсора неподдерживаемый базой данных, то
она может вернуть другой тип курсора. То есть
если Вы пробуете установить CursorLocation в clUseServer и
CursorType в ctDynamic, в базе данных Access, то Delphi заменит
CursorType на ctKeyset.
CursorLocation
Свойство CursorLocation определяет, где будет создан
набор записей (recordset) когда он будет открыт — у
клиента или на сервере.
Данные в клиентском (client-side) курсоре не
сязаны постоянно ("inherently disconnected") с базой
данных. ADO получает результаты запроса (все
строки) и копирует данные клиенту перед тем, как
Вы начнёте использовать их (в курсоре ADO). После
того, как Вы сделаете изменения в наборе записей (Recordset),
ADO преобразует эти изменения в запрос и
отправляет этот запрос в Вашу базу данных через
OLE DB. Клиентский (client-side) курсор ведёт себя подобно
локальному кэшу.
В большинстве случаев, клиентский (client-side) курсор
предпочтителен, потому что перемещения и
обновления быстрее и более эффективны. Но,
соответственно, увеличивается сетевой трафик
при возвращении данных клиенту.
Использование серверного (server-side) курсора
означает получение только необходимых записей.
Естевственно, что на сервер падает большая
нагрузка. Серверные (Server-side) курсоры полезны при
вставке, модификации, удалении записей. Данный
тип курсоров иногда обеспечивает лучшую
производительность чем клиентский курсор,
особенно когда сеть перегружена.
При выборе типа курсора Вам необходимо
продумать множество факторов, таких как: будет ли
у Вас большое количество обновлений либо Вы
будете производить только выборку из базы данных;
будете ли Вы использовать ADO как настольное
приложение или Ваше приложение будет Internet-ориентированным;
размер получаемых данных и т.д. Так же есть
некоторое ограничения: например, MS Access не
поддерживает динамических курсоров; вместо
этого он использует keyset. Некоторые средства
доступа к данным автоматически мастабируют
свойства CursorType и CursorLocation, в то время как другие
генерируют ошибку при использовании
неподдерживаемых CursorType или CursorLocation.
LockType
Свойство LockType сообщает провайдеру о блокировках,
которые будут помещены в записи в процессе
редактирования. Блокировка позволяет
предотвратить чтение данных одним пользователем
в то время как другой пользователь изменяет эти
данные, а так же не дать пользователю изменить
данные, если они были изменены другим
пользователем.
Такой эффект наблюдается в базе данных Access,
которая блокирует некоторые соседние записи.
Дело в том, что Access использует так называемую
стратегию фиксации страницы. Поэтому, если
пользователь редактирует запись, то другой
пользователь уже не сможет получить доступ к
изменению данной записи и, даже не сможет
модифицировать ближе стоящие записи (до или
после неё).
В Delphi, для этой цели используется TADOLockType в
которой указывается тип блокировки, которая
будет использоваться. Вы можете управлять
строкой и блокировкой страницы, устанавливая
соответствующую опцию блокировки курсора. Чтобы
использовать определенную схему блокировки,
провайдер и тип базы данных должны поддержать
эту схему.
ltOptimistic
Оптимистическая блокировка блокирует запись
только в том случае, если она была физически
изменена. Этот тип блокировки полезен, если
существует очень маленький шанс того, что второй
пользователь может модифицировать строку в
интервале между тем, когда курсор открыт, и когда
строка окончательно модифицирована. Текущие
значения в строке сравниваются со значением
полученным когда строка была последний раз
выбрана.
ltPessimistic
Пессимистическая блокировка блокирует каждую
запись, до тех пор пока она находится в процессе
редактирования. Эта опция заставляет ADO
устанавливать исключительную блокировку на
строку, когда пользователь делает любое
изменения в любом столбцу записи. Компоненты
ADOExpress непосредственно не поддерживают
пессимистическую блокировку записей, потому что
сама ADO не имеет возможности произвольно
блокировать данную запись и до сих пор
поддерживает навигацию в другие записи.
ltReadOnly
Данная блокировка просто не позволяет
редактировать данные. Полезна в тех случаях,
когда Ваше приложение должно временно
предотвратить изменение данных, при этом чтение
данной записи разрешено. Самый идеальный способ
использования данной блокировки для создания
отчётов, если установить CursorType как ctForwardOnly.
ltBatchOptimistic
Блокировка BatchOptimistic используется в клиентских
курсорах. Наборы записей с данным курсором
апдейтятся локально и все изменения
отправляются в базу данных пакетами.
|