Опубликован: 07.05.2010 | Уровень: специалист | Доступ: свободно
Лекция 4:

Наборы данных. Основные свойства, методы и события

< Лекция 3 || Лекция 4 || Лекция 5 >
Аннотация: На этой лекции вы познакомитесь с наиболее востребованными свойствами, методами и событиями, общими для всех наборов данных, потомков класса TDataSet. Кроме того, поговорим о методах блокировки данных при использовании файл-серверной архитектуры, а также о курсорах, специфичных для механизма ADO.
Ключевые слова: TADOTable, набор данных (DataSet), набор данных, базы данных, компонент, TADOQuery, сервер, Active, реальная таблица, класс, логический тип, CanModify, AutoCalcFields, значение, OnCalcFields, BOF, курсор, First, Prior, Bookmark, программирование, доступ, таблица, DatabaseName, адрес, псевдоним, BDE, DataSource, один-ко-многим, DefaultFields, редактор полей, Eof, Last, NEXT, FieldCount, Fields, FieldValues, Filter, Filtered, FilterOptions, регистр, точное совпадение, Modified, POST, recno, recordcount, State, режим вставки, append, запись, AppendRecord, параметр, Cancel, ClearFields, CLOSE, DELETE, Edit, изменение записей, FieldByName, явное преобразование, FindFirst, FindLast, FindNext, FindPrior, указатель, FreeBookmark, память, GotoBookmark, INSERT, InsertRecord, пользователь, IsEmpty, Locate, Lookup, OPEN, refresh, отмена изменений, программа, алгоритм, база данных, onfilterrecord, OnNewRecord, Архитектура файл-сервер, блокировка, LockTable, LockType, снятие блокировки, UnlockTable, пессимистическая блокировка, оптимистическая блокировка, производительность, CursorLocation, CursorType, компьютер, БД

До сих пор мы работали с таблицами с помощью компонента TADOTable. На самом деле мы работали не с самими таблицами, а с Набором данных (DataSet). Набор данных - это коллекция записей из одной или нескольких таблиц базы данных. Наборы данных можно получить с помощью компонент TADOTable, TADOQuery или TADOStoredProc, который необходим для архитектуры клиент-сервер. Каким образом получаются наборы данных? Когда мы открываем таблицу, то есть, присваиваем True свойству Active компонента TADOTable, например, специальный механизм делает выборку записей в соответствии с заданными параметрами, и возвращает нам эти записи в виде таблицы. Можно сказать, что наборы данных - это прослойка между нашим приложением и реальными таблицами, хранящимися в базе данных. Все указанные выше компоненты являются наборами данных, имеют общего предка - класс TDataSet и заимствовали от него свойства, методы и события, добавляя собственные возможности. Об этом и поговорим на этой лекции.

Свойства

Active - Свойство имеет логический тип и позволяет открыть или закрыть набор данных, если свойству присвоить True или False соответственно. В зависимости от свойства CanModify данные можно либо только просматривать, либо можно также редактировать их.

AutoCalcFields - Свойство логического типа. Если установить значение False, то возникновение события OnCalcFields будет подавляться, вычисляемые поля обрабатываться не будут. Значение True разрешает расчет вычисляемых полей.

Bof - Свойство имеет логический тип и содержит True, если курсор находится на первой записи набора данных, и False в противном случае. Bof содержит True, когда:

  • Не пустой набор данных открывается.
  • При вызове метода First.
  • При вызове метода Prior, если курсор при этом на первой записи набора данных.
  • При вызове метода SetRange в пустом наборе данных или диапазоне.

Bookmark - Свойство позволяет установить закладку на текущей записи набора данных. Количество закладок может быть неограниченно, работа с закладками рассматривалась на курсе "Введение в программирование на Delphi ". Свойство имеет тип TBookmarkStr.

CanModify - Свойство имеет логический тип, и показывает, можно ли редактировать полученный набор данных, или он доступен только для чтения. При открытии набора данных автоматически запрашивается доступ для редактирования. В таком доступе может быть отказано по разным причинам, например, таблица открыта другим пользователем в эксклюзивном режиме. В этом случае CanModify получает значение False, и мы можем только просматривать данные, но не вносить в них изменения.

DatabaseName - Свойство строкового типа, содержит адрес базы данных или ее псевдоним. Однако это справедливо к наборам данных BDE. В случае использования механизма ADO, это свойство недоступно - вместо него для подключения к базе данных следует использовать свойство Connection или ConnectionString.

DataSource - Свойство используется в наборах данных для указания детального набора данных в отношениях один-ко-многим.

DefaultFields - Свойство логического типа, содержит True, если программист не создал ни одного поля в редакторе полей набора данных. В этом случае все поля определяются автоматически, в соответствии с данной таблицей.

Eof - Свойство, противоположное свойству Bof. Имеет логический тип, и имеет значение True в случаях, когда:

  • Открыт пустой набор данных.
  • Вызван метод Last.
  • Вызван метод Next, если указатель при этом находится на последней записи таблицы.
  • При вызове метода SetRange в пустом наборе данных или диапазоне.

FieldCount - Свойство целого типа, содержит количество полей в наборе данных.

Fields - Свойство позволяет получить значение нужного поля по его индексу. Поля при этом индексируются с нуля. Например, получить значение седьмого по счету поля набора данных можно так:

Edit1.Text := CustTable.Fields[6].Value;

FieldValues - Свойство позволяет получить значение нужного поля по его имени. Это свойство используется по умолчанию, поэтому его можно не указывать. Примеры:

Edit1.Text := CustTable. FieldValues ['Order'];
Edit1.Text := CustTable['Order'];

Filter - Свойство строкового типа. Содержит строку, которая определяет правила фильтрации набора данных.

Filtered - Свойство логического типа. Если в свойстве Filter имеется строка, определяющая порядок фильтрации, то присвоение значения True свойству Filtered приводит к фильтрации набора данных. Присвоение этому свойству False отменяет фильтрацию.

FilterOptions - Свойство имеет тип TFilterOptions и применяется для строковых или символьных полей. Свойству можно присвоить значение foCaseInsensitive или foNoPartialCompare. В первом случае фильтрация будет учитывать регистр букв, во втором учитывается лишь точное совпадение образцу.

Modified - Очень важное свойство логического типа. Содержит True, если набор данных был изменен, и False в противном случае. Часто применяется для проверок: если набор данных изменен, то вызвать метод Post, чтобы сохранить изменения.

RecNo и RecordCount - Свойства целого типа. Первое содержит номер текущей записи в наборе данных, второе - общее количество записей.

State - Очень важное свойство, определяющее состояние набора данных. Может иметь следующие значения:

  • dsInactivate - набор данных закрыт.
  • dsBrowse - режим просмотра.
  • dsEdit - режим редактирования.
  • dsInsert - режим вставки.
  • dsSetKey - поиск записи.
  • dsCalcFields - состояние установки вычисляемых полей.
  • dsFilter - режим фильтрации записей.
  • dsNewValue - режим обновления свойства TField.NewValue.
  • dsOldValue - режим обновления свойства TField.OldValue.
  • dsCurValue - режим обновления свойства TField.CurValue.
  • dsBlockRead - состояние чтения блока записей.
  • dsInternalCalc - обновление полей, у которых свойство FieldKind соответствует значению fkInternalCalc.

Методы

Append - Метод добавляет новую запись в конец набора данных. При этом набор данных автоматически переходит в режим редактирования.

AppendRecord (const Values: array of const) - Метод добавляет новую запись в конец набора данных, и заполняет поля этой записи значениями из массива, переданного в метод как параметр.

Cancel - Отменяет все изменения набора данных, если они еще не сохранены методом Post или переходом на другую запись.

ClearFields - Метод очищает все поля текущей записи.

Close - Закрывает набор данных. Метод является альтернативой присваивания False свойству Active набора данных.

Delete - Метод удаляет текущую запись. Следует заметить, что во многих форматах данных удаляемая запись лишь помечается, как удаленная, и скрывается от пользователя. Физически же такая запись из файла не удаляется. В этом случае обычно время от времени приходится "паковать" таблицы, избавляясь от таких записей.

Edit - Метод переводит набор данных в состояние редактирования. Если этого не сделать, изменение записи будет невозможным.

FieldByName - Еще один способ получить значение поля или изменить его, указывая имя поля. При этом можно использовать явное преобразование данных в нужный тип, например, AsInteger, AsString и т.п. Пример:

Table1. FieldByName ('QUANTITY').AsInteger := StrToInt(Edit1.Text);

FindFirst , FindLast , FindNext и FindPrior - Методы пытаются установить курсор соответственно, на первую, на последнюю, на следующую и на предыдущую запись. В случае успеха методы возвращают True. Переход к другой записи приводит к автоматическому сохранению изменений, если изменения были.

First , Last , Next и Prior - просто устанавливают указатель соответственно на первую, последнюю, следующую и предыдущую запись. Переход к другой записи приводит к автоматическому сохранению изменений, если изменения были.

FreeBookmark - Метод освобождает память, связанную с закладкой Bookmark. Обычно вместо вызова этого метода достаточно присвоить закладке пустую строку (см. лекцию 30 курса "Введение в программирование на Delphi").

GotoBookmark - Метод обеспечивает переход на закладку Bookmark, переданную в качестве параметра.

Insert - Метод вставляет новую запись в указанную в параметре позицию набора данных. При этом набор данных автоматически переходит в режим редактирования.

InsertRecord (const Values: array of const) - Метод вставляет новую запись в набор данных, и заполняет поля этой записи значениями из массива, переданного в метод как параметр. Пример:

Customer. InsertRecord ([CustNoEdit.Text, CoNameEdit.Text, 
                                       AddrEdit.Text, Null, Null, Null, Null, 
                                       Null, Null, DiscountEdit.Text]);

Обратите внимание, что в некоторые поля были вставлены значения Null, то есть, ничего. То же самое происходит, когда пользователь при редактировании записи вносит значения не во все поля.

IsEmpty - Метод возвращает True, если в наборе данных нет записей. Применяется для проверки - не пуста ли таблица?

Locate - Метод ищет запись в наборе данных (см. предыдущую лекцию).

Lookup - Метод ищет запись в наборе данных (см. предыдущую лекцию). В отличие от Locate не переводит указатель на найденную запись, а лишь возвращает значения ее полей.

Open - Метод открывает набор данных. То же самое происходит, если свойству Active набора данных присвоить значение True.

Post - Метод сохраняет сделанные изменения в наборе данных.

Refresh - Метод заново перечитывает таблицу и обновляет набор данных. Имеет смысл использовать в приложениях, где несколько пользователей работают с одной базой данных.

События

After … - События, возникающие после вызова соответствующего метода:

AfterCancel - Событие возникает после отмены изменений в текущей записи.

AfterClose - Событие возникает после закрытия набора данных.

AfterDelete - Событие возникает после удаления текущей записи.

AfterEdit - Событие возникает после перехода набора данных в режим редактирования.

AfterInsert - Событие возникает после вставки новой записи.

AfterOpen - Событие возникает после открытия набора данных.

AfterPost - Событие возникает после вызова метода Post.

AfterScroll - Событие возникает после перехода на другую запись.

Before … - События, возникающие перед вызовом соответствующего метода:

BeforeCancel - Событие возникает перед отменой изменений в текущей записи.

BeforeClose - Событие возникает перед закрытием набора данных.

BeforeDelete - Событие возникает перед удалением текущей записи.

BeforeEdit - Событие возникает перед переходом набора данных в режим редактирования.

BeforeInsert - Событие возникает перед вставкой новой записи.

BeforeOpen - Событие возникает перед открытием набора данных.

BeforePost - Событие возникает перед вызовом метода Post.

BeforeScroll - Событие возникает перед переходом на другую запись.

OnCalcFields - Событие возникает при необходимости переопределения вычисляемых полей. Такое событие возникает всякий раз, когда программа должна сформировать значения для вычисляемых полей. Событие возникает также при открытии набора данных, и при любом его изменении. Если алгоритм вычислений достаточно сложен, база данных большая, а пользователь интенсивно с ней работает, событие OnCalcFields может значительно замедлить работу с базой данных. В этом случае следует отключать это событие. Для этого достаточно присвоить значение False свойству AutoCalcFields текущего набора данных.

OnFilterRecord - Событие возникает при включении фильтрации записей.

OnNewRecord - Событие возникает при вызове методов Append или Insert.

Блокировка таблиц в архитектуре файл-сервер

При работе в архитектуре файл-сервер с единой сетевой базой данных работают несколько клиентских приложений. При этом нередко возникает ситуация, когда один пользователь вносит изменения в базу данных. В этот момент, во избежание потери или порчи данных, следует запретить внесение изменений другими пользователями.

Такая блокировка достигается методом LockTable (). При этом значение свойства LockType этого набора данных определяет вид запрета. Значение ltReadLock запрещает чтение, а ltWriteLock - запись в набор данных. Можно запретить и чтение, и запись, но для этого следует вызвать метод LockTable () дважды. Блокировка таблиц методом LockTable () справедлива для таблиц Paradox или dBase, если вы используете механизм BDE. Когда изменения внесены, и необходимость блокировки пропадает, можно снять блокировку методом UnlockTable (), указав в параметре тип снимаемого запрета ( ltWriteLock, ltReadLock ).

Свойство LockType набора данных ADO имеет тип TADOLockType:

type TADOLockType = (ltUnspecified, ltReadOnly, ltPessimistic, ltOptimistic, ltBatchOptimistic);

Это свойство позволяет определить тип блокировки при открытии набора данных. Как видно из описания типа, свойство может иметь следующие значения:

ltUnspecified - тип блокировки не определен.

ltReadOnly - блокировка записи, читать данные можно.

ltPessimistic - пессимистическая блокировка. Свойство указывает, что если вы редактируете запись, то другие пользователи не смогут редактировать ее, пока вы не сохраните изменения.

ltOptimistic - оптимистическая блокировка. Блокировка подразумевает, что возникновение конфликта маловероятно. В связи с этим любой пользователь в любое время может редактировать любую запись. Проверка на наличие конфликтов производится только в момент сохранения изменений.

ltBatchOptimistic - свойство устанавливает блокировку на пакет записей, а не на отдельную запись. При этом все обновления, сделанные пользователем, не записываются сразу, а накапливаются в оперативной памяти. Позже они сохраняются одним пакетом. Такой подход увеличивает производительность приложения, но также увеличивается риск возникновения конфликтов.

Курсоры в наборах данных ADO

Наборы данных ADO имеют два специфичных свойства, неразрывно связанные друг с другом: CursorLocation и CursorType. Курсоры оказывают большое влияние на то, каким образом извлекаются данные из таблиц, каким образом вы можете перемещаться по ним и т.д. Фактически, курсор - это механизм перемещения по записям набора данных. От того, какой курсор используется в многопользовательской среде, зависит способ перемещения по записям: только вперед или в обе стороны. Будете ли вы видеть изменения, сделанные другими пользователями, также зависит от типа применяемого курсора.

CursorLocation (положение курсора)

Это свойство определяет, каким образом извлекаются и модифицируются данные. Значений только два:

clUseClient - курсор на стороне клиента.

clUseServer - курсор на стороне сервера.

Клиентский курсор обслуживается механизмом ADO Cursor Engine. В момент открытия набора данных все данные перекачиваются с сервера на клиентский компьютер. После этого данные хранятся в оперативной памяти. Перемещения по данным и их модификация происходит значительно быстрее, кроме того, клиентский курсор обладает более широкими возможностями.

Серверный курсор обслуживается операционной системой. Благодаря тому, что курсор находится на стороне сервера, приложению нет смысла перекачивать все данные разом, это повышает скорость работы с БД. Серверные курсоры больше подходят для обслуживания больших наборов данных. Следует заметить, что если вы работаете с локальной базой данных (например, Access ), то серверный курсор будет обслуживаться программой, обслуживающей эту базу данных.

CursorType (тип курсора)

Имеется пять типов курсора:

  • Unspecified - не указанный. В Delphi такой тип не используется, он присутствует только потому, что имеется в ADO.
  • Forward-only (только вперед). Этот тип курсоров обеспечивает самую высокую производительность, однако он позволяет перемещаться по записям только в одном направлении - от начала к концу, что делает его малопригодным для создания пользовательского интерфейса. Однако он хорошо подходит для программных операций, таких как перебор записей, формирование отчета и т.п.
  • Static (статический) - пользователь имеет возможность перемещаться в обоих направлениях, однако изменения записей, выполненные другими пользователями, не видны таким курсором.
  • Keyset (набор ключей). При открытии набора данных с сервера читается полный список всех ключей. Этот набор ключей хранится на стороне клиента. Если приложение нуждается в данных, провайдер OLE DB читает строки таблицы. Однако после открытия набора данных в этот набор нельзя добавлять новые ключи, или удалять имеющиеся. То есть, если другой пользователь добавил новую запись, текущий клиент ее не увидит. Однако он увидит изменения существующих записей, сделанные другими пользователями.
  • Dynamic (динамический). Самый мощный тип курсора, но при этом и самый ресурсоемкий. Он позволяет видеть все изменения, все добавления или удаления, сделанные другими пользователями, но при этом больше других замедляет работу с БД.
< Лекция 3 || Лекция 4 || Лекция 5 >
Евгений Медведев
Евгений Медведев

В лекции №2 вставляю модуль данных. При попытке заменить name на  fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? 

Анна Зеленина
Анна Зеленина

При вводе типов успешно сохраняется только 1я строчка. При попытке ввести второй тип вылезает сообщение об ошибке "project mymenu.exe raised exception class EOleException with message 'Microsoft Драйвер ODBC Paradox В операции должен использоваться обновляемый запрос'.