9.5.2 Настройки курсора и другие параметры открытия Recordset
Свойства объекта Recordset CursorType, CursorLocation, LockType, параметры открытия Recordset
При открытии объекта Recordset есть возможность определить еще несколько очень важных его свойств (их можно определить как напрямую перед открытием, так и как дополнительные параметры метода Open()):
- первое свойство — CursorType, тип курсора. Это свойство определяется только перед открытием Recordset (после открытия оно доступно только на чтение). Курсор можно представить себе как указатель на записи в Recordset. В зависимости от типа курсора мы определяем возможности работы с Recordset и производительность выполняемых операций (чем больше возможностей, тем меньше производительность, и наоборот). Какие варианты значений возможны:
- adOpenForwardOnly — это значение используется по умолчанию. Оно оптимизировано для достижения максимальной производительности (он возможности будут минимальными). Курсор может двигаться только вперед, изменения, вносимые другими пользователями, видны не будут.
- adOpenStatic — тоже, что и предыдущий, за исключением того, что можно двигаться во всех направлениях;
- adOpenKeyset — позволяет двигаться в любом направлении, видны только изменения существующих записей другими пользователями (удаление старых и добавление новых не видны);
- adOpenDynamic — обеспечивает максимальные возможности: позволяет двигаться в любых направлениях, видны любые изменения в записях, производимые другими пользователями. К сожалению, провайдер Microsoft.Jet.OLEDB.4.0 этот тип курсора не поддерживает, поэтому с Access и Excel его использовать не получится.
Свойство Recordset.RecordCount нормально функционирует только для курсоров типа Static и Keyset. Для курсоров типа ForwardOnly и Dynamic оно возвращает (-1), поскольку драйвер подключения не может определить количество записей.
- второе важное свойство — CursorLocation. Оно определяет, где будет создан курсор — на сервере или на клиенте. По умолчанию используется значение adUseServer — создавать на сервере. Есть возможность использовать значение adUseClient — создавать на клиенте. В целом практически во всех ситуациях удобнее и производительнее использовать серверные курсоры, за одним исключением — в реализации серверных курсоров на разных источниках данных больше отличий, поэтому если вы планируете работать с разными источниками, есть смысл подумать о клиентских курсорах.
- третье важное свойство — LockType. Это свойство определяет тип блокировок, которые будут наложены на записи на источнике, помещенные в Recordset. Можно использовать следующие значения:
- adLockReadOnly — записи в Recordset будут доступны только на чтение, вы не сможете их изменять. Это значение используется по умолчанию.
- adLockPessimistic — наиболее надежный с точки зрения целостности данных вид блокировки. Вы можете изменять записи в Recordset, но при начале изменения записи она блокируется на источнике таким образом, что другие пользователи не смогут обратиться к ней ни на чтение, ни на запись, пока вы не вызовете методы Update() или CancelUpdate().
- adLockOptimistic — это значение позволяет выиграть в производительности за счет проигрыша в надежности обеспечения целостности данных. Запись на источнике блокируется только на время выполнения метода Update(). Остальные пользователи могут одновременно с вами читать и изменять данные на источнике.
- adLockBatchOptimistic — то же самое, что обычное оптимистичное, но вместо немедленного обновления по одной записи используется пакетное обновление. В ситуации, когда изменяется большое число записей, такое решение позволяет выиграть в производительности.
Первый параметр метода Open() в наших примерах был именем таблицы и командой SQL (могут использоваться и другие варианты). Поскольку драйвер OLE DB не знает, чем может быть передаваемый текст, он взаимодействует с сервером баз данных, чтобы выяснить этот вопрос. На практике такое выяснение может сильно тормозить работу приложения, поэтому есть смысл перед открытием Recordset явно указать тип передаваемых данных. Это делается при помощи параметра Options, который передается этому методу. Наиболее часто используемые значения таковы:
- adCmdText — передаваемый текст — команда SQL;
- adCmdTable — сгенерировать команду SQL, которая вернет все записи из таблицы (передается только имя таблицы);
- adCmdTableDirect — получить все записи из таблицы напрямую (без выполнения SQL-запроса), если источник поддерживает такую операцию.
- adCmdStoredProc — выполнить хранимую процедуру и использовать то, что она вернет, для заполнения Recordset.
С практической точки зрения важно запомнить следующее. Если вам нужно обеспечить себе возможность перемещения по Recordset в любом направлении и изменять в нем записи, код на открытие Recordset должен быть таким:
Dim rs As New ADODB.Recordset
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open … 'Пишем, что именно мы открываем
На практике я пишу строки
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
совершенно автоматически, поскольку они нужны в подавляющем большинстве случаев. Какие-то другие значения этих свойств нужно только в специальных ситуациях (например, когда важнее всего производительность).