Основные понятия и определения баз данных. Реляционная модель данных. Язык SQL
Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
1. Реляционная модель данных. Язык SQL
Основные понятия и определения баз данных
База данных – организованная совокупность данных, длительное время
хранимая в ЭВМ.
Распределенная база данных – база данных, составные части которой
хранятся на разных узлах сети ЭВМ.
Система управления базами данных (СУБД) – программное средство
для построения и использования БД. Основное назначение СУБД –
поддержка
определенной
модели
данных.
Другие
функции
СУБД:
обеспечение секретности, поддержание целостности, параллельный доступ и
распределенная обработка, восстановление при отказах и разрушениях.
Технология «клиент-сервер» - частный случай распределенных систем,
при
котором общий процесс решения
задачи
разбивается
на два
взаимодействующих процесса: процесс клиент и процесс сервер. Каждый из
процессов может выполняться на отдельном компьютере.
Модель данных – правила организации структурированных данных.
Распространенными являются реляционная, сетевая и иерархическая модели
данных. Принято различать внешние и внутренние модели данных.
Внешняя модель – это модель пользователя, описывающая данные в
абстрактных терминах, независящих от способов хранения данных в
физической памяти.
Внутренняя модель – модель разработчика, описывает хранение данных в
физической памяти.
Иногда
используется
трехуровневая
модель
данных,
включающая
представление, концептуальную базу данных, физическую базу данных.
Перечисленные
уровни
являются
видением
БД
соответственно
пользователем, администратором, разработчиками. Трем уровням иерархии
БД отвечают три типа описаний: подсхема, схема, схема хранения.
Для описания базы данных используются языки описания данных (ЯОД),
для
непосредственной
работы
с
данными
используются
языки
манипулирования данными (ЯМД) или языки запросов. ЯОД и ЯМД
связаны с конкретными моделями данных.
Содержание (наполнение) БД в конкретный момент времени называется
экземпляром или состоянием БД. Описание структуры, характеристик
хранения и использования данных называется метаданными, словарем
данных, каталогом БД.
Реляционная модель данных
Основание реляционной модели – математическое понятие отношения,
подмножества декартова произведения доменов. Домен – множество
однотипных значений.
Пример.
D1 = {a,b}, D2 = {u,v}.
D1 D2 = {, , , }.
R = {, }
D1 D2 .
D1, D2 - два домена, D1
D2 - декартово произведение доменов, R -
отношение.
Элемент отношения называется кортежем, является последовательностью
компонентов. На практике принято табличное представление отношений, в
котором строки таблицы представляют кортежи, а столбцы – атрибуты
отношения.
R
D1
a
b
D2
u
v
кортеж
атрибут
Схемой отношения называется набор его атрибутов, схемой БД – набор
схем отношений БД.
В реляционной модели каждое отношение должно иметь ключ – набор
атрибутов, однозначно идентифицирующих кортежи отношения. Ключи
бывают первичные (основные), возможные (альтернативные) и внешние.
Внешние ключи используются для связи разных отношений.
Язык SQL
Язык структурированных запросов SQL позволяет выполнять операции
над
отношениями
и
отдельными
кортежами,
может
использоваться
автономно и в приложениях. Результат выполнения SQL-запроса –
множество записей, удовлетворяющих условию запроса. Для позаписной
обработки результата используются курсоры (указатели текущей записи).
SQL – основа реляционного доступа к данным, используемого в
распределенных информационных системах.
Имеются следующие группы операторов SQL:
Операторы определения данных (DDL);
Операторы манипулирования данными (DML);
Управление транзакциями, администрирование, программный SQL.
Операторы DDL
CREATE TABLE имя_таблицы
(
{
имя_столбца
тип
[ограничения_столбца]
},..
[,ограничения_таблицы] );
Оператор создает пустую таблицу с именем «имя_таблицы», содержащую
перечисленные
столбцы
«ограничения_столбца/таблицы»
указанных
задает
ограничения
значения или комбинации значений столбцов.
Пример.
CREATE TABLE Покупатели
(Фамилия CHAR (20) NOT NULL,
Адрес CHAR (20) NOT NULL,
Баланс MONEY NOT NULL,
типов.
на
Параметр
допустимые
PRIMARY KEY (Фамилия));
ALTER TABLE имя_таблицы
(
{
{
ADD|MODIFY|DROP
}
имя_столбца
[тип]
[ограничения_столбца]},.. );
Оператор изменяет указанную таблицу. Ключевые слова означают: ADD –
добавить столбец, MODIFY – изменить столбец, DROP – удалить столбец.
Пример. ALTER TABLE Покупатели (ADD Телефон CHAR (7));
DROP TABLE имя_ таблицы;
Оператор удаляет таблицу из БД.
CREATE [UNIQUE] INDEX имя_индекса ON имя_таблицы
({имя_столбца [ASC|DESC] },..);
Создает индекс для указанной таблицы. Перечень имен столбцов
определяет ключ индекса. Ключевые слова: UNIQUE – уникальный индекс
(значения ключа не повторяются), ASC – сортировка по возрастанию
значений атрибута, DESC – по убыванию значений атрибута.
Пример. CREATE UNIQUE INDEX Инд_покупатели ON Покупатели
(Фамилия);
DROP INDEX имя_индекса;
Удаляет индекс из БД.
CREATE VIEW имя_представления [ (список_столбцов) ] AS операторSELECT;
Представление – логическая таблица, представляющая результат SQLзапроса.
Может
(представление).
Пример.
рассматриваться
как
видение
БД
пользователем
CREATE VIEW Мои_покупатели (ФИО) AS
SELECT Фамилия FROM Покупатели WHERE Адрес = ”Казань”;
ALTER VIEW – изменение представления.
DROP VIEW – удаление представления.
CREATE DATABASE
‘путь\файл.gdb’ USER ‘имя_пользователя’
PASSWORD ‘пароль’;
В СУБД InterBase оператор создает новую пустую БД как файл с
расширением .gdb. Первоначально доступ к БД имеют только ее создатель и
системный администратор.
CREATE DOMAIN имя_домена тип [DEFAULT знач_по_умолчанию]
[ограничения];
Создает новое имя для расширенной спецификации одного из
стандартных типов данных SQL.
Пример. CREATE DOMAIN FAMILY CHAR (20) DEFAULT ‘FFFFF’
NOT NULL;
Операторы DML
UPDATE имя_таблицы
SET { имя_столбца = {выражение | NULL }},..
[WHERE условие ];
Обновляет таблицу, присваивая новые значения указанным столбцам в
кортежах, удовлетворяющих условию.
Пример.
UPDATE Покупатели
SET Баланс = Баланс+100
WHERE Баланс < 0;
Увеличивает баланс на 100 ед. для покупателей с отрицательным
балансом.
INSERT INTO имя_таблицы
(1)
[( список_столбцов )] VALUES ( список_значений );
INSERT INTO имя_таблицы
(2)
[( список_столбцов )] предложение_SELECT;
Оператор (1) вставляет в таблицу новую запись, поля которой имеют
указанные значения.
Оператор (2) добавляет к таблице множество записей, выбранных
оператором SELECT.
Пример.
INSERT INTO Покупатели VALUES (‘Петров’, ‘Маяковского’, 100.00);
Вставляет в таблицу запись с атрибутами покупателя Петрова.
DELETE FROM имя_таблицы
[WHERE условие ];
Удаляет из таблицы все удовлетворяющие условию записи.
*Практические задания к теме
Корпоративные ИС
хранения
и
- информационные системы для распределенного
совместного
использования
данных
структурными
подразделениями предприятий. Корпоративные ИС строятся на технической
базе компьютерных сетей с использованием технологии клиент-сервер.
Серверная часть ИС включает одну или несколько БД и СУБД, клиентская
часть – приложения и средства связи с сервером.
Корпоративные ИС
используют реляционный способ доступа к данным: клиент посылает серверу
SQL-запрос
и
получает
от
него
результат
–
множество
записей,
удовлетворяющих условию запроса. Реляционный способ доступа к
удаленным данным поддерживается многими промышленными СУБД, в том
числе, и сервером InterBase.
Запуск и соединение с сервером
В
лабораторных
работах
используется локальный вариант
сервера. Запуск сервера может
производиться
как
автоматически, так и вручную,
командой
Program/InterBase/InterBase
Server Manager. Если сервер не
запущен, то в окне команды
выдается
сообщение
«The
InterBase Server is currently Stopped», в противном случае – сообщение «The
InterBase Server is currently Running». Для запуска сервера нужно нажать на
кнопку «Start».
Другой способ запуска сервера – запуск из утилиты IBConsole (вызывается
Program/InterBase/IBConsole).
Утилита
конфигурирование сервера, создавать
позволяет
БД и
также
производить
администрировать ими,
создавать и выполнять запросы на языке SQL. Окно программы содержит
дерево известных ей серверов и БД, рабочее окно для выполнения действий.
Для запуска и соединения с сервером нужно выполнить команду
Server/Login или дважды щелкнуть на значке Local Server в дереве объектов
в левой части окна программы. Команда сообщит о состоянии сервера и
потребует указать имя пользователя и пароль. Следует ввести имя SYSDBA и
пароль masterkey (имя и пароль администратора БД).
Создание базы данных. Таблицы
Создадим учебную базу данных «Расписание занятий», включающую три
таблицы:
Группы (Номер_группы, Факультет, Курс),
Преподаватели
(Идентификатор_преп,
Фамилия,
Имя,
Отчество,
Факультет, Должность, Возраст),
Расписание (Номер_группы, День_недели, номер_пары, Дисциплина,
Идентификатор_преп, Аудитория).
В схемах таблиц выделены ключевые атрибуты.
Создайте каталог d:\ib\. Запустите утилиту IBConsole и выполните
команду Database/Create, Введите значения следующих полей:
Alias – псевдоним БД: bdrasp;
Files – полное имя БД и ее размер: d:\ib\bdrasp.gdb, 300;
Page Size – размер страницы: 4096;
Default character set – набор символов по умолчанию: WIN1251;
SQL Dialect: 3.
Нажмите
Создана
пустая
OK.
БД.
Структуру ее метаданных
(схему)
если
можно
увидеть,
выделить
строку
bdrasp в списке БД в окне
IBConsole
и
выполнить
команду
View
metadata.Добавим к схеме
таблицу Gruppy. Для этого
выполним команду Tools/
Interactive
SQL,
загружающую
программу
построения интерактивных
запросов
SQL.
Окно
программы содержит две области: верхняя – область запросов, нижняя –
область результатов.
Установите режим Auto Commit. Для этого: выберите пункт Edit/Options,
установите поле AutoCommit DDL = true, нажмите кнопку Apply. В режиме
AutoCommit каждый запрос (транзакция) автоматически подтверждает
сделанные им обновления. Аналогичный результат имеет место, если
выполнить оператор COMMIT. Включение или выключение режима
AutoCommit DDL указывается в строке статуса программы ISQL.
Запросы можно набирать по одному в области запросов и выполнять
(Query/Execute). Но лучше воспользоваться сценарием – файлом с текстом
одного или нескольких SQL-запросов. Сценарий можно создать с помощью
программы БЛОКНОТ.
Сценарий создания таблицы Gruppy:
CREATE TABLE Gruppy
(nomer_gr CHAR (4) NOT NULL,
fak CHAR (20) NOT NULL,
kurs CHAR (1) NOT NULL,
PRIMARY KEY ( nomer_gr))
Сценарии сохраняются в файлах с расширением .sql. Для загрузки и
выполнения сценария надо выполнить команды Query/Load script
Query/Execute.
После
этого
следует
просмотреть
и
диагностические
сообщения и исправить сценарий, если при выполнении были обнаружены
ошибки.
Таким же образом подготовьте и выполните сценарии создания таблиц
Prepod и Rasp.
CREATE TABLE Prepod
(ident_pr INTEGER NOT NULL,
family CHAR (20) NOT NULL,
name CHAR (10) NOT NULL,
father_name CHAR (15) NOT NULL,
fak CHAR (20) NOT NULL,
job CHAR (20) NOT NULL,
age INTEGER NOT NULL,
PRIMARY KEY (ident_pr));
CREATE TABLE Rasp
(nomer_gr CHAR (4) NOT NULL,
dayn CHAR (3) NOT NULL,
para CHAR (1) NOT NULL,
disc CHAR (20) NOT NULL,
ident_pr INTEGER NOT NULL,
aud CHAR (3) NOT NULL,
PRIMARY KEY ( nomer_gr,dayn,para))
Если все запросы выполнены успешно, то созданная БД содержит три
таблицы: Gruppy, Prepod и Rasp, имена которых можно увидеть в правой
части окна IBConsole при условии,
что в левой части выделена строка
DataBases/bdrasp/Tables. С помощью команды
Database/View metadata
можно просмотреть сценарии создания таблиц.
Для соединения с уже существующей БД нужно дважды щелкнуть по
имени базы в левой части окна или выполнить команду Database/Connect.
Индексы. Добавление в таблицу новых записей
Для ускорения операций с таблицами используются индексы. Поэтому
добавим к схеме БД описания двух индексов для таблиц Prepod и Rasp:
CREATE INDEX ind_prep ON Prepod (family),
CREATE INDEX ind_rasp ON Rasp (ident_pr).
Ключ индекса ind_prep таблицы Prepod содержит поле family, а индекса
ind_rasp таблицы Rasp – поле ident_pr.
Запросы набираются в ISQL и выполняются по одному или включаются в
состав сценариев. Индексы для первичных ключей создаются автоматически.
Теперь БД готова для использования.
Для ввода в таблицу новых записей используется оператор SQL INSERT
INTO, имеющий следующий синтаксис:
INSERT INTO имя_таблицы (список колонок) VALUES (список
значений).
Для работы с символами кириллицы установите набор символов WIN1251
(используйте Edit/Options). Наберите в области запросов программы ISQL
запрос
INSERT INTO Gruppy
(nomer_gr, fak, kurs) VALUES (‘И211’,
’Информационный’, ’2’) и выполните его.
Чтобы убедится, что запись действительно попала в таблицу можно
выполнить запрос
SELECT * FROM Gruppy.
Если все было сделано
правильно, то в окне результатов появится только что введенная запись.
Для подтверждения сделанных изменений нужно выполнить оператор
Transactions/Commit. Если этого не сделать, то изменения не попадут в БД.
Отменить изменения можно оператором Transactions/Rollback.
Таким же образом добавьте к БД еще несколько групп и просмотрите
полученные результаты. Сформируйте и выполните файлы сценариев для
добавления во все таблицы по 2-3 записи.
Вводить новые записи и редактировать существующие можно и в
интерактивном режиме, без использования SQL-запросов. Для этого в окне
IBConsole нужно щелкнуть на строке Tables в дереве объектов, выбрать и
дважды щелкнуть на нужной таблице в правой части окна, и выбрать вкладку
Data окна Properties. Добавьте таким способом во все таблицы
по 6-7
записей.
Закройте
программу
(Console/Exit).
ISQL
(File/Close)
и
программу
IBConsole
2. Оператор SELECT
Центральным оператором языка SQL является оператор SELECT.
Синтаксис оператора:
SELECT [ALL | DISTINCT] {список_данных|*}
FROM список_таблиц
[WHERE условие_выборки]
[GROUP BY поля_группировки]
[HAVING условия_групп]
[ORDER BY ключ_сортировки];
Оператор производит выборку и вычисления над данными одной или
нескольких таблиц. Результатом является таблица, в которой разрешены
(ALL) или запрещены (DISTINCT) повторяющиеся строки. Список данных
определяет столбцы результирующей таблицы.
Предложение FROM задает исходные таблицы, предложение WHERE –
условие выборки кортежей, GROUP BY определяет поля группирования
результирующих кортежей, HAVING задает условия включения групп
кортежей в результат, ORDER BY определяет упорядоченность строк
результата.
В условиях запросов могут использоваться следующие предикаты:
Сравнение, кратное сравнение;
BETWEEN A AND B – проверка на попадание в диапазон;
IN (NOT IN) (множество) – принадлежность элемента множеству;
LIKE (NOT LIKE) (шаблон) – сравнение с шаблоном;
IS NULL (IS NOT NULL) – сравнение с неопределенным значением;
EXISTS (NOT EXISTS ) – проверка множества на непустоту;
AND, OR, NOT – логические операции.
В связи с наличием неопределенных (NULL) значений имеются варианты
языка с трехзначной логикой, истинностными значениями которой являются
true
(истина),
false
(ложь),
unknown
(неизвестно).
Сравнение
неопределенным значением (NULL) дает логическое значение unknown.
с
Правила вычисления логических операций:
AND
t
u
f
t
t
u
f
u
u
u
f
f
f
f
f
OR
t
u
f
t u f
t t t
t u u
t u f
NOT
t
f
u
u
f
t
Агрегатные функции
Вычисляют обобщенные групповые значения, требуют группирования
кортежей результата. Агрегатные функции: COUNT - число непустых
значений столбца или число кортежей в группе, SUM - сумма элементов
столбца, AVG - среднее по столбцу, MIN - минимальное в столбце, MAX максимальное в столбце.
Пример. Определить число поставщиков каждого поставляемого товара.
SELECT Товар, COUNT (*)
FROM Поставщики
GROUP BY Товар;
Вложенные запросы
SELECT …
FROM …
WHERE … {IN|EXISTS|ALL|ANY}
(SELECT … FROM … WHERE …)
Запрос может быть частью условия другого запроса. Внутренний запрос
порождает некоторое значение, которое проверяется в предложении WHERE
или HAVING внешнего запроса. В условии используются предикаты IN,
EXISTS, ALL (все), ANY (некоторые) и сравнение скаляров.
Примеры.
Найти поставщиков заказанных товаров.
SELECT Название, Товар
FROM Поставщики
WHERE EXISTS
(SELECT Товар
FROM Заказы
WHERE Товар=Поставщики.Товар);
Определить адреса покупателей, каждый заказ которых не меньше 20
единиц.
SELECT Фамилия, Адрес
FROM Покупатели
WHERE 20 <= ALL
(SELECT Количество
FROM Заказы
WHERE Фамилия=Покупатель.Фамилия);
Коррелированные и некоррелированные подзапросы
Внешние
и
внутренние
запросы
(подзапросы)
могут
быть
как
коррелированны между собой, так и не коррелированны. Корреляция имеет
место, если внутренний запрос получает из внешнего некоторое значение,
которое используется в условии внутреннего запроса.
Пример. Найти поставщиков заказанных товаров.
SELECT Название, Товар
FROM Поставщики
WHERE EXISTS
(SELECT Товар
FROM Заказы
WHERE Товар=Поставщики.Товар);
Из
внешнего
запроса
во
внутренний
передается
Поставщики.Товар. В результате этого внутренний запрос
столько раз, сколько было передано значений.
Другая реализация этого же запроса:
SELECT Название, Товар
параметр
выполняется
FROM Поставщики
WHERE Товар IN
(SELECT DISTINCT Товар
FROM Заказы);
В последнем случае внутренний запрос не зависит от внешнего и поэтому
будет выполнен только один раз. Замена коррелированного подзапроса на
некоррелированный является оптимизацией запроса.
Внутренние и внешние соединения
Оператор «SELECT A, B, … FROM R1, R2 WHERE условие» формирует
множество кортежей с атрибутами A, B, … путем селекции декартова
произведения R1 R2 по заданному условию. Такую операцию принято
называть внутренним (INNER) условным соединением. На практике также
используется внутреннее естественное
JOIN), внешнее
соединение (NATURAL INNER
естественное соединение (NATURAL OUTER JOIN),
перекрестное соединение (CROSS JOIN).
Внешнее соединение используется в тех случаях, когда в результат
требуется включить все кортежи отношения R1, а вместо кортежей
отношения R2, не удовлетворяющих условию, включить неопределенные
значения. Или наоборот.
Внутреннее естественное соединение – это аналог операции естественного
соединения реляционной алгебры.
Перекрестное соединение – это декартово произведение.
Синтаксис соединений:
FROM R1 NATURAL INNER JOIN R2;
FROM R1 NATURAL {FULL|LEFT|RIGHT} [OUTER] JOIN R2;
FROM R1 CROSS JOIN R2;
Вариант LEFT означает, что в результат включаются все кортежи отношения
R1, RIGHT – все кортежи отношения R2, FULL – все кортежи обоих
отношений.
Программный SQL
Имеются следующие способы применения SQL в программах:
Модульный SQL – операторы собраны в один модуль;
Встроенный SQL – операторы включены в текст программы;
Интерфейс API – операторы передаются СУБД во время выполнения с
помощью специальных функций;
Компонентный интерфейс – операторы задаются значениями свойств
компонентов приложения.
Различают статический и динамический SQL. Статический – операторы
задаются
до
выполнения
приложения,
динамический
–
операторы
формируются во время выполнения приложения.
Для позаписной обработки результатов запросов в программах SQL
используются курсоры – указатели текущего положения в наборе данных.
В Delphi для задания операторов SQL можно использовать компонент
Query, свойство SQL которого содержит текст запроса. Набор данных
(логическая таблица) формируется при открытии компонента (используется
метод Open или присваивание Active:=true). Если запрос не должен
возвращать результирующее множество, то используется метод ExecSQL.
Статический SQL-запрос может иметь параметры, значения которых
задаются во время выполнения приложения. Параметры запроса сохраняются
в свойстве Params компонента Query (указывается имя и тип параметра).
Массив Params формируется с помощью редактора параметров на этапе
проектирования приложения.
Пример динамического запроса.
…
Query1.Close;
Query1.SQL.Clear;
Quer1.SQL.Add(‘SELECT * FROM TableName WHERE A>B’);
Query1.Open;
…
Пример статического запроса с параметром.
Текст запроса: SELECT * FROM TableName WHERE A>:param;
Программа:
…
Query1.Close;
Query1.ParamByName(‘param’).AsInteger:= StrToInt(Edit1.Text);
Query1.Open;
…
Обычно текст SQL-запроса проверяется и выполняется при каждом
открытии набора данных Query. Если текст запроса при выполнении не
изменяется, то его можно предварительно подготовить и в дальнейшем
использовать уже подготовленный вариант. Подготовка
вызываться
при
создании
формы,
свойство
(Prepare) может
Prepared
указывает
на
подготовленность запроса.
*Практическик задания к теме
Работа с базами данных в Delphi. Программа BDE Administrator
Delphi имеет несколько механизмов доступа к данным. Наиболее
распространенным механизмом доступа является BDE (процессор баз
данных Борланд), позволяющий обращаться как к локальным, так и к
глобальным БД, поддерживаемых различными СУБД. Кроме BDE, для
доступа к БД в Delphi можно использовать механизмы ADO, DBExpress,
InterBaseExpress и др. Будем ориентироваться на доступ через BDE.
BDE
выполняет
подключения
функции
настройки
драйверов, кеширования
связи
пользователя
с
БД,
данных, управления памятью,
генерации SQL-запросов, преобразования типов данных и др. Для получения
доступа к той или иной БД пользователю нужно указать только ее имя (файл
БД) или псевдоним – все остальное делает BDE. Обычно для связи
используется псевдоним, так как в этом случае можно изменять физическое
расположение БД и СУБД, не изменяя само приложение.
Для создания псевдонима БД используется программа BDE Administrator,
которую можно вызвать командой Пуск/Программы/Borland Delphi 7/BDE
Administrator.
Ранее в программе IBConsole был создан псевдоним bdrasp, создадим
теперь новый псевдоним программой BDE Administrator. Для этого
выполняются действия:
Выбрать Object/New.
В выпадающем списке драйверов выберите INTRBASE, нажмите OK. В
окне псевдонимов замените псевдоним по умолчанию (INTRBASE1) на
нужное имя (Raspisanie).
Настройте параметры в правой части окна:
LANGDRIVER – языковый драйвер. Значение «Pdox ANSI Cyrillic».
SERVERNAME – файл базы данных. Значение «d:\ib\bdrasp.gdb».
USERNAME – имя пользователя. Значение «SYSDBA».
Сохраните настройки командой Object/Apply.
Закройте BDE Administrator командой Object/Exit.
Компоненты доступа, визуализации и управления данными
Для доступа, визуализации и управления данными приложение использует
компоненты-наборы данных DataSet, визуальные компоненты DBGrid,
DBEdit и др., компоненты-источники данных DataSource. Наборы данных
непосредственно связаны с постоянными или временными объектами БД,
такими как таблицы, запросы, хранимые процедуры и др. Визуальные
компоненты позволяют просматривать данные и управлять ими. Компоненты
источники служат для связи визуальных компонентов с наборами данных.
Схема взаимодействия компонентов:
БД
Набор
данных
Источник
данных
Визуальные
компоненты
данных
Рассмотренные компоненты размещены на страницах DataAccess, BDE и
DataControls палитры компонентов Delphi.
Построим простое приложение. Поместите на форму компоненты
DataSource, Query и DBGrid и настройте их связи следующим образом.
Компонент DataSource1. Установите DataSet=Query1.
Компонент Query1. Установите DataBaseName=Raspisanie,
RequestLive=true, SQL=’select * from Gruppy’.
Компонент DBGrid1. Установите DataSource=DataSource1.
Сделанные
настройки
связывают
компоненты
в
соответствии
с
приведенной выше схемой, при этом компоненту Query1 сопоставляется
запрос ‘select * from Gruppy’ на чтение всех записей таблицы Gruppy.
Если теперь установить Query1.Active=true, то можно получить доступ к
записям набора данных Query1. Значение Active=true указывает на активное
состояние набора данных (набор
открыт), значение Active=false – на
неактивное состояние набора данных (набор закрыт). Для открытия и
закрытия набора данных можно также использовать методы Open и Close.
В процессе открытия набора данных BDE потребует ввести пароль для
доступа к данным. После ввода правильного пароля компонент DBGrid1
будет отображать данные таблицы Gruppy. Так реализуется доступ к данным
в режиме проектирования приложения.
Рассмотрим реализацию доступа в режиме выполнения приложения.
Добавьте к форме две кнопки Button1 и Button2. Назовите кнопку Button1
«открыть», а кнопку Button2 «выход».
Напишите обработчики события OnClick для кнопок.
procedure TForm1.Button1Click (Sender:Tobject);
begin
Query1.Active:=true;
// открыть набор данных
Button1.Enabled:=false;
// сделать кнопку неактивной
end;
procedure TForm1.Button2Click(Sender:Tobject);
begin
if Query1.Active then Query1.Close; // если н. д. открыт, то закрыть
Application.Terminate;
// завершить приложение
end;
Выполните приложение.
Обратите внимание, что в заголовках колонок компонента DBGrid1
используются имена физических полей таблицы Gruppy. Часто это бывает
нежелательно. Для переименования колонок DBGrid, изменения их порядка,
пропуска части колонок используется редактор колонок, вызов которого
производится из контекстного меню DBGrid (пункт Columns Editor).
В окне редактора с помощью кнопок добавления и удаления колонок
формируется список колонок компонента. Выделив строку списка, с
помощью инспектора объектов можно отредактировать ее свойства.
Отредактируйте следующие свойства колонок DBGrid1:
FieldName. Укажите имя связанного поля таблицы.
Title.Caption. Укажите заголовок колонки.
Title.Font. Укажите шрифт заголовка.
Сохраните проект. Выполните приложение.
Навигация в наборе данных
Для позаписной обработки набора данных в приложении используется
навигационный способ доступа, основанный на понятии курсора. Курсор –
указатель текущей записи набора данных.
Навигация в наборе данных использует следующие методы перемещения
курсора:
First – на 1-ю запись,
Last – на последнюю запись,
Prior – на предыдущую запись,
Next – на следующую запись,
MoveBy – на заданное число записей.
Свойства BOF и EOF набора данных указывают, находится ли курсор в
начале набора (BOF=true) или в его конце (EOF=true).
Реализуем навигацию в наборе данных.
Добавьте к форме компоненты Button3 и Button4. Установите свойство
Caption этих компонентов равными соответственно значениям «следующая»
и «предыдущая». Свойство Enabled обоих компонентов установите в false.
Создайте обработчик события OnClick для кнопок.
procedure TForm1.Button1Click (Sender:Tobject);
begin
Query1.Active:=true;
// открыть набор данных
Button1.Enabled:=false;
// сделать кнопку неактивной
Position;
// проверить позицию
end;
procedure TForm1.Button2Click (Sender:Tobject);
begin
if Query1.Active then Query1.Close; // если н. д. открыт, то закрыть
Application.Terminate;
// завершить приложение
end;
procedure TForm1.Button3Click(Sender:Tobject);
begin
Query1.Next;
// к следующей записи
Position;
// проверить позицию
end;
procedure TForm1.Button4Click(Sender:Tobject);
begin
Query1.Prior;
// к предыдущей записи
Position;
// проверить позицию
end;
// проверить позицию
procedure TForm1.Position;
begin
if Query1.EOF then Button3.Enabled:=false;
else Button3.Enabled:=true;
if Query1.BOF then Button4.Enabled:=false;
else Button4.Enabled:=true;
end;
Сохраните проект. Выполните приложение.
Доступ к значениям полей
Набор данных является таблицей, состоящей из строк (записей) и столбцов
(атрибутов или полей). Компонент DataSet содержит массив Fields,
представляющий поля набора данных (объекты типа TField). Свойство
FieldCount указывает число полей набора.
К объекту полю можно обратится по порядковому номеру поля:
Query1.Fields[2] – обращение к 3-му полю;
Query1.Fields[0] – обращение к 1-му полю.
Следует иметь в виду, что обращение к объекту полю есть обращение к
объекту типа TField, а не к данным БД. Для получения значения данных БД
можно
использовать
AsBoolean,
свойство
AsDateTime,
Value
AsFloat,
или
AsInteger,
свойства-модификаторы:
AsString,
AsVariant,
возвращающие значения соответствующих типов. Например, обращение
Query1.Fields[2].AsInteger возвращает целое число, находящееся в третьем
поле текущей записи. Обращение
Query1.Fields[2].Value возвращает
значение, которое хранится в записи набора данных. Если значение в поле не
может быть преобразовано в указанный тип, то возникает исключительная
ситуация.
К полю можно обратится по его имени, используя функцию FieldByName:
Query1.FieldByName(‘имя поля’).AsString – значение поля ‘имя поля’ в
текстовом виде.
Наконец, к полю можно обратится и так: Query1[‘имя поля’].
Некоторые свойства объекта TField:
DisplayName – имя поля, используемое в сообщениях;
FieldKind – вид поля;
DataType – тип данных поля;
FieldNo – порядковый номер поля (начинается с 1);
CanModify – признак возможности редактирования.
Задание. Начните новый проект. Разместите на форме компоненты и дайте
им подходящие названия (рисунок). Свяжите компонент Query1 с одной из
таблиц БД и введите в свойство SQL запрос на чтение всех записей таблицы.
Работа приложения: при нажатии кнопки Button1 приложение считывает из
компонента Edit1 имя одного из полей набора данных Query1 и помещает
значения поля из
всех записей набора в список ListBox1. Ввод
неправильного имени поля должен сопровождаться выдачей подходящего
диагностического сообщения. Напишите обработчики событий кнопок.
Сохраните проект. Выполните приложение.
Изменение набора данных
Наборы данных, в том числе и Query, имеют следующие методы
изменения данных:
Append – добавление записи,
Insert – вставка записи,
Delete – удаление записи,
Edit – редактирование,
Post – сохранение изменений в БД,
Cancel – отмена изменений.
Набор Query по умолчанию является нередактируемым. Для того чтобы
данные можно было редактировать, необходимо выполнение условий:
запрос относится к одной таблице БД,
в запросе не используется квалификатор DISTINCT, агрегатные
функции, предложения GROUR BY и HAVING,
запрос не содержит подзапросов.
Кроме этого, необходимо установить у компонента Query свойство
RequestLive=true («живой» набор). Реальная возможность модификации
набора указывается в свойстве CanModify, которое доступно только для
чтения.
Компонент DataSet работает с данными в буферной области (кеше). Для
перенесения изменений в БД нужно использовать метод Post, для отмены
изменений –
метод
Cancel. Визуальные компоненты, допускающие
редактирование данных, вызывают необходимые методы автоматически,
программное редактирование данных требует явного использования методов
Edit, Post, Cancel и др.
Переделайте проект навигации в наборе данных. Добавьте на форму
компонент Edit1 и кнопки Button5, Button6. Свяжите компонент Query1 с
таблицей Prepod, его свойство SQL установите равным ‘SELECT * FROM
Prepod’, а свойство RequestLive установите в true. Назовите кнопку Button5
«редактировать», Button6 - «удалить».
Измените метод Position так, чтобы он выводил фамилию текущего
преподавателя в компонент Edit1. Удалите из обработчиков Button3Click и
Button4Click вызов Position.
Включите в программу обработчик Query1AfterScroll:
procedure TForm1.Query1AfterScroll (Sender: Tobject);
begin Position; end;
Обработчик будет вызываться после каждого изменения курсора набора
данных.
Добавьте процедуру редактирования поля текущей записи (обработчик
события OnClick кнопки Button5) и процедуру удаления текущей записи
(обработчик Button6Click):
procedure TForm1. Button5Click(Sender: Tobject);
begin
Query1.Edit;
Query1[‘family’]:=Edit1.Text;
Query1.Post;
end;
procedure TForm1. Button6Click(Sender: Tobject);
begin
Query1.Delete;
end;
Для предотвращения нежелательного удаления записей добавьте в
программу обработчик Query1BeforeDelete, вызываемый при каждой
попытке удаления записи:
procedure TForm1.Query1BeforeDelete (Sender: Tobject);
begin
if not (MessageDlg(‘Удалить запись?’, mtError, [ mbYes, mbNo], 0) = mrYes)
then Abort;
end;
Установите в компоненте DBGrid1 свойство Options.dgConfirmDelete =
false (отмена запроса на удаление).
Сохраните проект. Запустите приложение и проверьте его работу.
3. Оптимизация запросов
Оптимизация запроса – выбор эффективной процедуры реализации
запроса. Процесс оптимизации затрагивает как планирование реализации, так
и преобразование самого запроса, дающее тот же самый результат, но с
меньшими издержками. Термин «оптимизация» не следует понимать
буквально: обычно имеется в виду просто выбор хорошей реализации, а не
решение строгой математической задачи оптимизации.
Оптимизация
может
производиться
вручную
или
автоматически.
Автоматическая оптимизация обладает рядом достоинств:
СУБД имеет больше информации, чем пользователь;
Учитывается текущее состояние БД;
Рассматривается больше вариантов;
Используются лучшие стратегии.
Пример.
Рассмотрим два эквивалентных варианта запроса:
1.
2. (
R1.A>R1.B(R1
A>B(R1)
R2).
R2 .
Пусть мощность R1 – n кортежей, мощность R2 – m кортежей. Тогда для
выполнения запроса 1 потребуется прочитать 2nm кортежей, а для запроса 2
(полагая мощность селекции в среднем равной n/2) только nm/2 кортежей.
Запрос 2 выполняется в четыре раза быстрее, чем запрос 1.
Схема оптимизации
Четыре стадии оптимизации:
преобразование запроса во внутреннюю форму,
преобразование в каноническую форму,
выбор потенциальных процедур реализации,
генерация планов вычислений и выбор наилучшего плана.
Преобразование во внутреннюю форму
Внутреннее представление запроса базируется на реляционной алгебре
или исчислении. Алгебраическое выражение кодируется в форме дерева
запроса.
Пример.
SELECT Покупатели.Фамилия
FROM Покупатели NATURAL INNER JOIN Заказы
WHERE Товар = «спички»;
Внутреннее представление запроса:
Фамилия
(
Товар=»спички»
(Покупатели ▷◁ Заказы)).
Представление в виде дерева:
Фамилия
Товар=спички
▷◁
Покупатели
Заказы
Преобразование в каноническую форму
Выполняются
гарантированно
хорошие
операции
оптимизации,
независимые от реальных условий. Эквивалентные запросы приводятся к
одинаковой канонической форме с помощью правил эквивалентных
преобразований.
Выбор потенциальных процедур реализации
Запрос в канонической форме рассматривается как серия низкоуровневых
операций (соединение, селекция, проекция …), частично зависящих друг от
друга. Для каждой операции имеется набор процедур реализации,
учитывающих условия операции (наличие индекса, выборка по ключу …). С
каждой процедурой связана стоимостная формула.
Генерация планов вычислений запросов
Конструируются планы вычисления запроса и производится выбор
лучшего плана. Каждый план является некоторой комбинацией процедур,
реализующих
операции
запроса.
Число
генерируемых
планов
по
возможности ограничивают, а их исчерпывающий перебор заменяют
использованием эвристических алгоритмов.
Эквивалентные преобразования запросов
В качестве примера эквивалентных преобразований приведем несколько
преобразований операций выборки и проекции:
F1( F2(R))
F1 F2(R),
A(
AB(R))
A(R),
F(
A(R))
A(
F(R)).
Общим правилом является как можно более раннее проведение выборки,
так как она сокращает размеры промежуточных результатов. В формулах
преобразований
широко
используются
свойства
коммутативности,
ассоциативности, дистрибутивности и др. реляционных операций и свойства
логических операций. Возможно использование семантической оптимизации,
учитывающей ограничения целостности БД.
Статистические данные о БД и ее использовании часто позволяют найти
лучшие планы реализации запросов. Примеры статистик: мощность таблиц,
число различных значений столбца, количество уровней индекса и др.
Способы реализации реляционных операторов
Реляционные операции проекции, селекции, соединения и агрегации с
точки зрения реализации имеют некоторое сходство: в каждом из этих
случаев имеет место группирование кортежей в соответствии со значениями
некоторых атрибутов. Для проекции такая группировка позволяет исключить
дублирующие кортежи, для соединения – найти кортежи, для агрегации –
вычислить групповое значение.
Методы группировки: прямой, по индексу, по хеш-таблице, слияние.
Прямой метод
Рассматривается реализация операции соединения. Анализируются все
возможные сочетания кортежей отношений R и S. Отношение R включает
кортежи R[1], R[2],…R[m], а отношение S – кортежи S[1], S[2],… S[n].
Общий атрибут – C.
Схема метода:
for i:=1 to m do
for j:=1 to n do
if R[i].C=S[j].C then
Добавить к результату кортеж ;
Стоимость метода.
Чтение: m n операций.
Запись результата:
Соединение 1:M. В большинстве случаев n или m операций.
Соединение M:M. Пусть dCR – количество разных значений атрибута C
отношения R, dCS – аналогичное количество для отношения S. Пусть
значения распределены равномерно. Тогда для кортежа из R существует n/dCS
кортежей S со значением R.C=S.C и мощность результата равна mn/dCS.
Рассуждая аналогично со стороны отношения S, получим оценку мощности
nm/dCR. Используется меньшая из оценок.
Количество операций чтения страниц.
Пусть на странице помещается PR и PS кортежей
отношений R и S
соответственно. Тогда число чтений страниц составит m/PR+mn/PS или
n/PS+mn/PR. Это наихудшие результаты.
Использование индекса
Пусть для атрибута C отношения S существует индекс X. Это позволяет
сразу переходить от кортежа отношения R к связанному кортежу отношения
S. Число чтений кортежей будет равно мощности результата. Количество
операций
чтения
страниц
составит
m/PR+mn/dCS
при
наихудшем
предположении, что каждое чтение кортежа из S требует обращения к
отдельной странице.
Схема метода:
for i:=1 to m do
//k – число вхождений R[I].C в индекс
for j:=1 to k do
if R[i].C=S[j].C then
Добавить к результату кортеж ;
Если кортежи отношения S хранятся в порядке значений атрибута C, то
количество чтений страниц составит m/PR+(mn/dCS)/PS. Чтением индекса
пренебрегаем.
Использование хеширования
Метод аналогичен использованию индекса.
Схема:
for i:=1 to m do
begin
k:= hash(R[i].C);
for j:=1 to h do
//h – число кортежей S попавших в k-ю строку хеш-
таблицы
if R[i].C=S[j].C then
Добавить к результату кортеж ;
end;
Слияние.
Предполагается, что кортежи R и S хранятся в последовательности
значений атрибута C. В этом случае соединение может быть выполнено за
один проход по данным. Число чтений страниц составит m/PR+n/PS. Отсюда
следует важность физической кластеризации логически связанных данных.
Если такой кластеризации нет, то целесообразно провести предварительную
сортировку отношений.
Поддержка оптимизации в SQL
Большинство серверов БД (SQL-серверы), включая и СУБД InterBase,
сообщают пользователям планы выполнения запросов и разрешают задавать
пользовательские планы. План сервера отображается в окне результатов
программы ISQL на вкладке PLAN. Планы пользователей задаются в
операторе SELECT:
SELECT … FROM … WHERE … PLAN (план выполнения запроса).
План выполнения запроса = [{JOIN|[SORT] MERGE}] ({Таблица|План},..).
Таблица = {Имя таблицы|Псевдоним таблицы} {NATURAL|INDEX
(список индексов)| ORDER Список индексов}.
Здесь NATURAL – последовательный доступ к данным; INDEX – индекснопоследовательный доступ;
ORDER –
сортировка таблицы;
JOIN –
объединение таблиц. Если объединение не поддерживается индексами,
следует указать MERGE (слияние) или SORT MERGE.
Пример запроса с рекомендацией использовать для сортировки таблицы
индекс.
SELECT Фамилия
FROM Покупатели
ORDER BY Фамилия
PLAN (Покупатели ORDER индекс_фамилии_покупателей);
4. Параллельная обработка данных
Основные понятия параллельной обработки
Транзакция – процесс выполнения последовательности операторов,
переводящий БД из одного целостного состояния в другое. Транзакция
характеризуется
4-мя
свойствами:
атомарность,
согласованность,
изолированность, долговечность.
Атомарность – транзакция должна быть выполнена целиком или не
выполнена вовсе.
Согласованность – транзакция переводит БД из одного целостного
состояния в другое.
Изолированность – можно считать, что конкурирующие транзакции
обрабатываются физически последовательно, изолированно друг от друга.
Долговечность – результаты успешной транзакции не могут быть
потеряны.
Транзакция может завершиться успешно или неуспешно. В первом случае
транзакция фиксируется, во втором БД возвращается в исходное состояние.
Успешность или неуспешность транзакции определяется двумя SQLоператорами: COMMIT и ROLLBACK.
Транзакция может завершиться:
оператором COMMIT – успех;
оператором ROLLBACK – неудача, откат транзакции;
успешным завершением программы (неявный COMMIT);
ошибочным завершением программы (неявный ROLLBACK).
Транзакция запускается SQL-оператором SET TRANSACTION. В языке
Delphi запуск, подтверждение или отмена транзакции может производиться
одноименными методами компонента Database.
Пример.
Database1.StartTransaction;
try
…
Query1.Edit;
…
Database1.Commit;
except
Database1.Rollback;
end;
Проблемы параллельного выполнения транзакций
Ничем не ограниченный параллелизм может приводить к следующим
проблемам:
Пропавшие изменения. Ситуация возникает при одновременном
изменении
записи
несколькими
сделанные
транзакцией,
могут
транзакциями.
быть
испорчены
Изменения,
другими
транзакциями.
Промежуточные
данные
(грязные
данные).
Временные
изменения, сделанные одной транзакцией, ошибочно становятся
доступными другим транзакциям.
Несогласованные данные (неповторяющееся чтение). Повторное
чтение транзакцией одной и той же записи может давать разные
результаты.
Строки-фантомы. Два одинаковых запроса к БД в одной
транзакции может приводить к разным результатам.
Названные проблемы преодолеваются с помощью специальных правил
выполнения транзакций.
Блокировки, расписания, протоколы
Любой ресурс БД может быть взят во владение транзакцией – блокирован.
Блокирование
может
быть
разделяемым
(несколько
транзакций
одновременно имеют доступ к ресурсу) и монопольным (только одна
транзакция может использовать ресурс). Каждая транзакция в конце работы
должна разблокировать все заблокированные ею ресурсы.
Расписание транзакций – порядок, в котором выполняются отдельные
шаги транзакций.
Сериализация расписаний. Расписание считается последовательным,
если все шаги каждой транзакции выполняются последовательно. Расписание
называется сериализуемым, если его результат эквивалентен результату
некоторого
последовательного
совокупности
параллельных
расписания.
транзакций
Корректное
обязательно
расписание
должно
быть
сериализуемым.
Протокол
параллельных
–
правила
выполнения
транзакций
транзакций.
преодолеваются
с
Многие
помощью
проблемы
подходящих
протоколов.
Тупик. Состояние системы параллельных транзакций, когда каждая из них
пытается заблокировать ресурс, уже заблокированный другой транзакцией
системы, называется тупиком. Тупик означает бесконечное ожидание всех
транзакций системы. Для борьбы с тупиками используются специальные
методы.
Журнализация транзакций и восстановление базы данных
Для обеспечения надежного хранения данных в БД используются журналы
транзакций, позволяющие восстанавливать согласованные состояния БД
после любых аппаратных и программных сбоев.
Принципы восстановления:
Зафиксированные
транзакции
должны
быть
сохранены
в
отсутствовать
в
восстановленном состоянии БД;
Незафиксированные
транзакции
должны
восстановленнном состоянии БД.
Восстановление БД может производиться в следующих случаях:
Индивидуальный
откат
транзакции
(ROLLBACK,
аварийное
завершение, откат при тупике);
Мягкий сбой;
Жесткий сбой.
При
индивидуальном
откате
транзакции
устраняются
последствия
операторов модификации БД. Восстановление при мягком сбое использует
журнал
транзакций,
хранящийся
на
диске.
Жесткий
сбой
требует
использования архивных копий БД и неповрежденных журналов транзакций.
Журнал транзакций можно представлять в виде последовательного файла,
в котором фиксируются все изменения БД.
Способы
сохранения
целостности
БД
при
использовании
параллельных транзакций
Решение проблем параллельных транзакций достигается с помощью
следующих правил выполнения транзакций:
Пользователи не должны видеть несогласованные и промежуточные
данные;
Расписание параллельных транзакций должно быть сериализуемым.
Для реализации этих правил используются блокировки. Различают
разделяемые (Shared) и эксклюзивные (eXclusive) блокировки. В SQL
оператор блокирования имеет вид
LOCK TABLE имя_таблицы IN {SHARED|EXCLUSIVE}
MODE.
Сериализация
транзакций
достигается
использованием
двухфазного
протокола блокирования ресурсов: первая фаза транзакции – накопление
блокировок, вторая – разблокирование всех захваченных ресурсов.
Уровни изолированности пользователей
В тех случаях, когда приложению важны не точные данные, а скорость
выполнения запросов, требование сериализации можно ослабить. Для этого
вводится понятие уровня изолированности пользователя.
Имеются следующие уровни изолированности:
SERIALIZABLE – полная изоляция.
REPEATABLE READ (повторяющееся чтение). Транзакция не имеет
доступа как к промежуточным, так и к окончательным результатам
других транзакций. Возможны строки фантомы.
READ COMMITED (подтвержденное чтение). Транзакция не имеет
доступа к промежуточным результатам других транзакций. Возможны
несогласованные данные и строки фантомы.
READ
UNCOMMITED
(грязное
чтение).
Транзакция
видит
промежуточные и несогласованные данные и строки призраки.
Предотвращаются пропавшие изменения.
Уровни
изолированности
задаются
в
SQL
оператором
SET
TRANSACTION:
SET TRANSACTION …
ISOLATION LEVEL [SERIALIZABLE |REPEATABLE READ |READ
COMMITED
|READ UNCOMMITED] [READ WRITE |READ ONLY]
…
Гранулированные синхронизационные захваты
Объекты блокирования могут быть разного уровня: база данных, файл,
отношение, страница, кортеж, поле. Чем крупнее объект, тем меньше
блокировок потребуется программе, тем меньше накладные расходы. Однако
одновременно возрастает вероятность конфликта транзакций, уменьшается
степень их параллельности. Для достижения разумного компромисса между
требованиями минимизации расходов,
уменьшения
конфликтности и
увеличения параллельности был предложен механизм гранулированных
синхронизационных захватов. В соответствии с ним объект может быть
захвачен в режимах S, X, IS, IX, SIX. При этом используется специальный
протокол: перед захватом объекта в режиме S или X соответствующий
объект более высокого уровня должен быть захвачен в режиме IS, IX или
SIX.
Режим IS (Intended for Shared Lock) по отношению к составному объекту
O означает намерение захватить некоторый входящий в O объект в S-режиме.
Режим IX (Intended for eXclusive Lock) по отношению к составному
объекту O означает намерение захватить некоторый входящий в O объект в
X-режиме.
Режим SIX – совместный захват объекта O с намерением впоследствии
захватить входящий в него объект в монопольном режиме.
Предикатные синхронизационные захваты
Предыдущий метод не решает проблему фантомов. Эта проблема решается
методом предикатных синхронизационных захватов.
Суть метода. Рассматривается захват двумя транзакциями одного
отношения. Каждая транзакция содержит условие, определяющее множество
обрабатываемых кортежей. Если множества кортежей транзакций не
пересекаются, то транзакции можно выполнять параллельно.
Реализация механизма транзакций в SQL и Delphi
Различают явные и неявные транзакции. Неявные запускаются и
завершаются автоматически, явными управляет приложение. В Delphi для
управления явными транзакциями используется компонент Database и его
методы StartTransaction, Commit, RollBack. Для неявных транзакций
можно задать порядок взаимодействия соперничающих запросов. В СУБД
InterBase для этого используется параметр SQLPASSTHRU MODE
псевдонима БД или драйвера, принимающий следующие значения:
SHARED AUTOCOMMIT – запускается неявная транзакция, которая
автоматически подтверждается. Разные транзакции могут использовать
общее соединение с БД.
SHARED NO AUTOCOMMIT – запускается неявная транзакция, но
автоматического подтверждения не происходит; можно использовать
общее соединение.
NOT SHARED – транзакции должны использовать разные соединения
с БД и подтверждаться оператором COMMIT.
Оператор задания явной транзакции в языке SQL записывается
следующим образом:
SET TRANSACTION
[READ WRITE |READ ONLY]
[WAIT |NO WAIT]
[ISOLATION LEVEL …]
[RESERVING список_таблиц
[FOR [SHARED |PROTECTED] [READ |WRITE]]];
Операнды:
WAIT – при конфликте ожидается завершение другой транзакции;
NO WAIT – при конфликте данная транзакция завершается;
RESERVING – резервирование таблиц для транзакции в режимах:
PROTECTED READ –защищенное чтение;
PROTECTED WRITE – защищенная запись;
SHARED READ – разделяемое чтение;
SHARED WRITE – разделяемая запись.
5. Распределенная обработка данных
Принято различать распределенные системы и системы с удаленным
доступом к данным. В системах с удаленным доступом пользователь видит
соединения между узлами, в распределенной системе соединения скрыты от
пользователя (фундаментальный принцип распределенной системы).
Другие принципы распределенных систем:
Локальная автономия узлов;
Независимость от центрального узла;
Непрерывное функционирование;
Независимость от расположения;
Независимость от фрагментации;
Независимость от репликации;
Обработка распределенных запросов;
Управление распределенными транзакциями;
Независимость от аппаратного обеспечения;
Независимость от операционной системы;
Независимость от сети;
Независимость от СУБД.
Расшифровка принципов.
Локальная автономия – операциями узла управляет сам узел.
Независимость от центрального узла – все узлы рассматриваются как
равные; зависимость от центрального узла снижает надежность системы.
Непрерывное
функционирование
–
система
сохраняет
работоспособность даже в случае выхода из строя отдельных узлов.
Независимость от расположения (прозрачность) – пользователь не знает,
на каких узлах хранятся его данные.
Независимость от фрагментации – пользователь не видит фрагментацию
данных.
Независимость от репликации – пользователь не знает, с какой копией
данных он работает.
Обработка
распределенных
запросов
–
остро
стоит
проблема
оптимизации выполнения запросов.
Управление распределенными транзакциями – решаются задачи
сохранения целостности и управления параллелизмом. Целостность данных
обеспечивается протоколом двухфазной фиксации транзакций, параллельное
выполнение транзакций управляется блокированиями ресурсов.
Независимость от аппаратуры, операционной системы, сети и СУБД
избавляет пользователя от необходимости знать соответствующие объекты,
позволяет целиком сконцентрироваться на предметной области задачи.
Модели «клиент-сервер»
Модели «клиент-сервер» - частный случай систем с удаленным доступом.
Процесс решения задачи разделяется на два взаимодействующих процесса:
клиента и сервера. Клиент запрашивает услуги, сервер обеспечивает их
выполнение.
Сервер
одновременно
может
обслуживать
несколько
клиентских процессов.
Функции обработки данных могут по-разному распределяться между
клиентом и сервером. Принято следующее деление функций стандартного
интерактивного приложения:
ввод и отображение данных (Presentation Logic),
обработка данных (Business Logic),
управление информационными ресурсами (Database Manager System).
Презентационная
логика
обслуживает
графический
интерфейс
пользователя. Бизнес-логика определяет основные алгоритмы решения задач
приложения. Управление информационными ресурсами – это СУБД.
Возможно следующее распределение функций между клиентом и
сервером:
Логика
Бизнес- Управление
представления логика
данными
Распределенное
клиент,
сервер
сервер
представление
сервер
Удаленное
клиент
сервер
сервер
представление
Распределенная
клиент
клиент,
сервер
обработка
сервер
Удаленное
клиент
клиент
сервер
управление
Распределенное
клиент
клиент
клиент,
управление
сервер
Двухуровневые модели
Модель удаленного доступа к данным
SQL
логика
представления
бизнес-логика
управление
данными
(СУБД)
клиент
сервер
БД
Модель поддерживается большинством существующих СУБД, которые
предоставляют все необходимые для этого средства. Недостатки модели:
дублирование бизнес-логики однотипными приложениями и пассивность
сервера, работа которого ограничена выполнением запросов.
Модель сервера БД
Вызов
процедур
логика
представления
клиент
бизнес-логика
(хранимые процедуры, триггеры)
СУБД
сервер
БД
Основу модели составляет механизм хранимых процедур, производящих
обработку данных по
требованию клиента. Триггеры
хранимых
автоматически
процедур,
запускаемых
- разновидность
при
наступлении
некоторых событий. С их помощью поддерживается целостность БД.
Основной недостаток модели – перегрузка сервера, которому приходится
заниматься как обработкой, так и управлением данными.
Трехуровневая модель распределения функций (модель сервера
приложений, AS-модель)
Представление
Управление
данными
Обработка
сервер
приложений
клиент
сервер
БД
Каждая из трех групп функций реализуется на отдельном компьютере.
Центральное звено AS-моделей – сервер приложений, состоящий из ряда
служб, выполняющих запросы клиентов. Перед выполнением запросы
помещаются в общую очередь и обслуживаются в соответствии с некоторой
дисциплиной. Достоинство AS-модели – гибкость и универсальность,
недостаток – большие затраты на организацию взаимодействия компонентов.
Реализация распределенной обработки данных
Монитор транзакций
SQL
Прикладная
программа
ATMI
Двухзвенные
и
клиент-серверные
Менеджер
ресурсов
Менеджер
транзакций
XA
многозвенные
модели
порождают
распределенные
транзакции,
использующие
вычислительные и информационные ресурсы сразу нескольких компьютеров.
Корректное
выполнение
распределенных
транзакций
обеспечивается
монитором обработки транзакций (TPM), управляющим информационновычислительными ресурсами в распределенной среде. TPM позволяет
выполнять масштабирование системы, поддерживает корректную работу
приложений, повышает производительность обработки данных.
Функционирование TPM описывается моделью монитора транзакций
X/Open DTP. Модель состоит из трех объектов: прикладной программы,
менеджера ресурсов (RM) и менеджера (монитора) транзакций (TM). RM
выполняет функции сервера ресурсов некоторого вида. Прикладная
программа взаимодействует с RM с помощью набора специальных функций
или SQL. Интерфейс ATMI (Application Transaction Monitor Interface)
позволяет
вызывать
функции
Менеджерами ресурсов обычно
из
TPM
языка
программирования.
выступают серверы БД или СУБД. При
обработке распределенных транзакций TM и RM следуют протоколу
двухфазной фиксации транзакций и стандарту X/Open XA.
Управление распределенными данными
Основные проблемы распределенных систем – сохранение целостности
распределенных данных и совместный доступ к общим ресурсам. Доступ к
общим
данным
Целостность
управляется
обеспечивается
механизмом
специальными
блокирования
технологиями
ресурсов.
управления
распределенными данными. Распространены две технологии: распределенная
БД и тиражирование данных.
Распределенная БД состоит из нескольких фрагментов, размещенных на
разных узлах сети и управляемых разными СУБД. С точки зрения
пользователя РБД воспринимается как одна локальная БД. Информация о
нахождении
частей
РБД
хранится
в
глобальном
словаре
данных.
Корректность модификации РБД обеспечивается протоколом двухфазной
фиксации транзакций. На первом этапе в узлах сети производятся изменения
(обратимые)
и
менеджеру
транзакций
посылаются
соответствующие
уведомления. На втором этапе менеджер транзакций, получив уведомления о
правильности операций, выдает всем узлам команду фиксации изменений. С
этого момента транзакция считается завершенной.
Достоинством протокола является соответствие состояния БД всем
зафиксированным изменениям. Недостаток – повышенные требования к
производительности и надежности каналов связи.
Тиражирование данных предполагает дублирование данных в узлах сети.
Данные обрабатываются как обычные локальные. Управление данными
осуществляет репликатор. Допускается неполное совпадение копий в течение
некоторых промежутков времени. Достоинства тиражирования: большая
скорость обработки, меньший трафик сети, надежность механизма доступа к
данным. Недостаток – возможное расхождение копий.
Поддержка распределенной обработки в SQL и Delphi
Приложение одновременно может быть подключено к нескольким БД,
причем активным является только одно текущее подключение. Для
управления подключениями к удаленным БД в SQL используются операторы
CONNECT, DISCONNECT, SET CONNECTION.
В СУБД InterBase оператор
CONNECT DATABASE «имя_файла_БД» USER «имя_пользователя»
PASSWORD «пароль»
подключает пользователя к БД. Предыдущее подключение становится
неактивным.
Отключение приложения от текущей БД в InterBase производится
оператором DISCONNECT.
Оператор SQL SET CONNECTION переключает приложение на другое
подключение.
В Delphi для управления подключениями используются компоненты
Database и Session. Компонент Database позволяет настраивать параметры
соединения с БД, явно управлять транзакциями. Основные свойства
компонента:
SessionName – имя компонента сеанса;
AliasName – псевдоним БД;
DatabaseName – имя базы данных в приложении;
Params – параметры соединения;
Connected – признак соединения.
Значения свойств можно устанавливать с помощью редактора параметров
соединения. Установить или разорвать соединение можно изменением
свойства Connected или методами Open и Close.
Компонент Session – текущий сеанс работы с БД, управляет всеми
соединениями со всеми БД. Компонент Database связывается с компонентом
Session через свойство SessionName.
Схема установления соединения:
1. С помощью утилиты BDE Administrator создать псевдоним БД;
2. Разместить на форме компоненты Database1 и Query1;
3. Установить значения свойств AliasName, DatabaseName компонента
Database1 и значение свойства DatabaseName компонента Query1;
4. Соединение устанавливается открытием набора данных Query1 или
установкой Database1.Connected=true.
Приложение может одновременно работать с несколькими БД, используя
несколько компонентов Database.
6. Хранимые процедуры, генераторы, триггеры
Хранимые процедуры
Хранимые процедуры являются подпрограммами, постоянно хранящимися
на сервере и запускаемыми на выполнение из приложений клиента.
Использование хранимых процедур ускоряет обработку удаленных данных,
уменьшает трафик сети.
Хранимая процедура создается оператором CREATE PROCEDURE:
CREATE PROCEDURE имя_процедуры [(входные_параметры)]
[RETURNS (выходные_параметры)] AS тело_процедуры;
Тело процедуры может содержать описания локальных переменных и блок
операторов, подобных операторам языков SQL и Pascal. Тексты с
описаниями процедур удобно хранить в отдельных файлах сценариев (script),
которые создаются с помощью любого текстового редактора.
Пример сценария процедуры StProc1, вычисляющей среднее значение
столбца Col1таблицы Tab1:
SET TERM !! ;
CREATE PROCEDURE StProc1
RETURNS (opAvgCol1 float)
AS
BEGIN
SELECT AVG(Col1) FROM Tab1 INTO :opAvgCol1;
END!!
SET TERM ; !!
Здесь предложение SET TERM, используемое только в сценариях, служит
для задания ограничителя операторов. Предложение SET TERM !! ;
устанавливает в качестве ограничителя символы «!!», а последний оператор
возвращает исходный ограничитель «;». Это делается для того, чтобы
транслятор процедур выполнил оператор CREATE PROCEDURE и не
выполнял операторы тела процедуры, которые должны выполняться при
вызове процедуры, а не при ее создании. Оператор выбора строк SELECT
AVG(Col1) FROM Tab1 INTO :opAvgCol1 возвращает результат запроса
(среднее значение столбца) в выходной параметр opAvgCol1, которому в
операторах SQL тела процедуры должен предшествовать префикс «:».
Хранимая процедура удаляется оператором DROP PROCEDURE.
Для вызова хранимой процедуры из других процедур, приложений и
утилит можно использовать оператор
EXECUTE PROCEDURE имя_процедуры [(входные_аргументы)]
[RETUNING_VALUES (выходные_аргументы)]
или оператор SELECT.
В языке хранимых процедур различают два вида оператора выбора строк:
1. оператор SELECT …FROM …WHERE …INTO… - оператор выбора
одной строки, возвращающий первую найденную строку;
2. оператор FOR SELECT …FROM …WHERE … INTO …DO … оператор выбора нескольких строк, выполняющий для каждой
выбранной строки оператор после слова DO.
Пример сценария процедуры с оператором выбора нескольких строк:
SET TERM !! ;
CREATE PROCEDURE StProc2
RETURNS (opAvgCol1 float)
AS
DECLARE VARIABLE n INTEGER;
DECLARE VARIABLE m INTEGER;
DECLARE VARIABLE i INTEGER;
BEGIN
N=0; m=0; i=0;
FOR SELECT Col1 FROM Tab1 INTO n DO
BEGIN m=m+n; i=i+1; END
IF (i<>0) THEN opAvgCol1=m/i; ELSE opAvgCol1=0;
END!!
SET TERM; !!
Если в операторе выбора нескольких строк после слова DO стоит слово
SUSPEND (приостановка), то для каждой выбранной записи в приложение
будут передаваться значения выходных параметров.
Различают хранимые процедуры выбора и действия. Процедура действия
возвращает в качестве результата одну строку, процедура выбора – несколько
строк (набор данных).
Вызов хранимой процедуры выбора
Хранимая процедура выбора запускается на выполнение оператором
SELECT * FROM имя_процедуры (параметры). Результатом ее работы
является набор данных, состоящий из нескольких строк значений выходных
параметров. Если процедуру выбора запустить оператором EXECUTE
PROCEDURE или использовать для ее запуска компонент StoredProc, то
возвращается только одна первая строка набора (используется при отладке
процедур).
В приложении для запуска хранимой процедуры выбора используется
компонент Query, при этом текст запроса находится в свойстве SQL и может
содержать параметры, например: SELECT * FROM StProc (:par1,:par2).
Параметры определяются с помощью редактора параметров: задаются
свойства DataType, ParamType, Value каждого параметра из массива Params.
Для обращения к параметрам из приложений можно использовать метод
ParamByName.
Пример.
SET TERM !! ;
CREATE PROCEDURE StProc3(ipCol2)
RETURNS (opCol1)
AS
BEGIN
FOR SELECT Col1
FROM Tab1
WHERE Col2=:ipCol2
INTO :opCol1
DO SUSPEND;
END!!
SET TERM ; !!
Процедура StProc3 выдает значения тех строк столбца Col1 таблицы Tab1,
в которых столбец Col2 имеет значение ipCol2. Если поместить в свойство
SQL компонента Query запрос «SELECT * FROM StProc3(:ipCol2)», задать
значения параметров в свойстве Params и открыть набор данных, то Query
будет содержать результат выполнения хранимой процедуры, который
можно отобразить в сетке DBGrid и обработать методами компонента Query.
Вызов хранимой процедуры действия
Для вызова процедуры действия в SQL используется оператор EXECUTE
PROCEDURE
имя_процедуры
[(список_входных_параметров)].
В
приложениях Delphi можно использовать компонент StoredProc (задаются
значения
свойств
DatabaseName,
StoredProcName,
Params).
Значения
параметров задаются так же, как и в SQL-запросе. Запустить хранимую
процедуру в приложении можно методами Prepare и ExecProc.
Пример. Запуск хранимой процедуры действия stProc, возвращающей одно
значение выходного параметра opPar.
Procedure TForm1.Button1Click();
begin
StoredProc1.StoredProcName:=‟stProc‟;
StoredProc1.Prepare;
StoredProc1.ExecProc;
Edit1.Text:=FloatToStr(StoredProc1.ParamByName(„opPar‟).Value);
End;
Генераторы и триггеры
Триггер – это хранимая процедура, которая находится на сервере и
запускается автоматически при модификации БД. Триггер нельзя вызвать из
приложения клиента, передать ему параметры и получить от него
результаты. По характеру действий триггер похож на обработчики событий
типа BeforeEdit, AfterEdit и др. Триггеры используются для программной
реализации ограничений целостности (бизнес-правил).
Триггер создается оператором
CREATE TRIGGER имя_триггера FOR имя_таблицы
[ACTIVE|INACTIVE] {BEFORE|AFTER} {UPDATE|INSERT|DELETE}
[POSITION число]
AS тело_триггера.
Параметры оператора:
ACTIVE, INACTIVE – активность (пассивность) триггера;
BEFORE, AFTER – триггер вызывается до (после) модификации БД;
UPDATE, INSERT, DELETE – вид модификации БД;
POSITION – приоритет для конкурирующих триггеров.
Триггер удаляется оператором DROP TRIGGER имя_триггера.
Язык программирования триггеров аналогичен языку хранимых процедур.
К именам полей таблицы в теле триггера можно обращаться с приставками
OLD или NEW.
Генератор в СУБД InterBase используется для обеспечения уникальности
значений ключевых атрибутов. Генератор создается оператором CREATE
GENERATOR
имя.
Начальное значение
генератора устанавливается
командой SET GENERATOR имя TO начальное_значение. Обращение к
генератору выполняется функцией GEN_ID(имя, шаг), которая возвращает
увеличенное на шаг значение генератора. Функция используется в операторе
INSERT и в триггерах.
Пример. Реализация ссылочной целостности с помощью триггеров.
Имеются две связанные таблицы – Table1 и Table2. Таблица Table1 –
главная, Table2 – подчиненная. Связь таблиц производится по полю Field1.
CREATE GENERATOR GenTable1;
SET GENERATOR GenTable1 TO 1;
SET TERM !! ;
CREATE TRIGGER Tr1Table1 FOR Table1
ACTIVE
BEFORE INSERT
AS
BEGIN
NEW.Field1=GEN_ID(GenTable1, 1);
END!!
CREATE TRIGGER Tr2Table1 FOR Table1
ACTIVE
AFTER DELETE
AS
BEGIN
DELETE FROM Table2 WHERE Table1.Field1=Table2.Field1;
END!!
SET TERM ; !!
Триггер Tr1Table1 обеспечивает уникальные значения поля связи Field1
для таблицы Table1, триггер Tr2Table1 удаляет записи таблицы Table2,
связанные с удаленной записью таблицы Table1.
*Практические задания к теме
Хранимые процедуры
Хранимые
процедуры
–
подпрограммы, хранимые на
сервере и
вызываемые из приложений клиента. Использование хранимых процедур
ускоряет обработку удаленных данных, уменьшает трафик сети.
Хранимая процедура создается оператором
CREATE PROCEDURE Имя_процедуры [(список_входных_параметров)]
RETURNS [(список_выходных_параметров)]
AS тело_процедуры
Тело процедуры может содержать описания локальных переменных и блок
операторов, подобных операторам языков SQL и Pascal.
Запустите IBConsole, подключитесь к локальному серверу (двойной
щелчок на ветви “Local Server”, далее укажите имя
SYSDBA и пароль
masterkey). Вызовите ISQL и подключитесь к базе данных bdrasp (Database |
Connect As …, укажите имя SYSDBA, пароль masterkey, ClientDialect=2,
CharacterSet=WIN1251).
С помощью программы БЛОКНОТ наберите текст сценария:
SET TERM !! ;
CREATE PROCEDURE pPrepod
RETURNS (opAvgAge float)
AS
BEGIN
SELECT AVG(age)
FROM Prepod
INTO :opAvgAge;
END!!
SET TERM ; !!
Сохраните текст сценария в файле с расширением .sql.
Предложение SET TERM изменяет разделитель операторов (;
!!), что
позволяет программе ISQL начать выполнение сценария с оператора
создания процедуры CREATE. Символы «:» в тексте процедуры выделяют
вхождения параметров. Данная процедура вычисляет средний возраст
преподавателей
Загрузите сценарий в ISQL и выполните
создана.
его. Хранимая процедура
Удалить хранимую процедуру можно оператором DROP PROCEDURE
имя_процедуры.
Хранимую процедуру можно вызывать из других хранимых процедур,
приложений и программы ISQL. В ISQL для вызова хранимой процедуры
используется оператор
EXECUTE PROCEDURE имя_процедуры [(список_входных_параметров)]
[RETURNS_VALUES (список_выходных_параметров)].
Наберите в окне запросов ISQL EXECUTE PROCEDURE pPrepod.
В области результатов должно появится следующее сообщение:
OpAvgAge
_________
_________
значение
Оператор SELECT FROM WHERE INTO – оператор выбора одной строки
–
возвращает в качестве результата первую найденную строку,
удовлетворяющую условию.
Оператор FOR SELECT FROM WHERE DO оператор – оператор выбора
нескольких записей. Для каждой выбранной записи выполняется оператор
после слова DO.
Наберите текст сценария:
SET TERM !! ;
CREATE PROCEDURE pPrepod1
RETURNS (opAvgAge float)
AS
DECLARE VARIABLE n INTEGER;
DECLARE VARIABLE m INTEGER;
DECLARE VARIABLE i INTEGER;
BEGIN
N=0; m=0; I=0;
FOR SELECT age FROM Prepod WHERE job=‟доцент‟ INTO n DO
BEGIN m=m+n; I=I+1; END
IF (I<>0) THEN opAvgAge= m/I; ELSE opAvgAge =–1;
END!!
SET TERM ; !!
Загрузите
и
выполните
сценарий.
Выполнив
PROCEDURE pPrepod1, получите в области
запрос
EXECUTE
результата ISQL средний
возраст преподавателей доцентов.
Если после слова DO стоит SUSPEND, то для каждой выбранной записи в
приложение будут передаваться значения выходных параметров.
Принято различать хранимые процедуры действия и выбора. Хранимые
процедуры действия возвращают в качестве результата одну строку,
хранимые процедуры выбора – несколько строк (набор данных).
Вызов хранимой процедуры выбора
Хранимая процедура выбора запускается на выполнение оператором
SELECT * FROM имя_процедуры (параметры). Результатом ее работы
является набор данных, состоящий из нескольких строк значений выходных
параметров процедуры.
Если процедуру выбора запустить оператором EXEC PROCEDURE или
использовать для запуска компонент StoredProc, то возвращается только
первая строка набора. Такая форма запуска обычно используется при отладке
процедур. В приложениях для запуска процедуры выбора
используется
компонент Query, при этом текст запроса (находится в свойстве SQL) может
содержать параметры, например, SELECT * FROM pProc(:par1,:par2).
Параметры определяются с помощью редактора параметров инспектора
объектов: устанавливаются свойства Params, DataType, ParamType, Value.
Для обращения к параметру можно использовать метод ParamByName.
Наберите и сохраните текст сценария.
SET TERM !! ;
CREATE PROCEDURE pPrepod2(ipJob CHAR (20))
RETURNS (opFamily CHAR (20))
AS
BEGIN
FOR SELECT family
FROM Prepod
WHERE job=:ipJob
INTO :opFamily
DO SUSPEND;
END!!
SET TERM ; !!
Загрузите и выполните сценарий.
Начните новый проект. Поместите на форму компоненты Query1,
DataSource1 и DBGrid1, свяжите их между собой, свяжите Query1 с базой
данных. С помощью инспектора объектов определите параметр ipJob и
задайте его значение. Сохраните и выполните проект. В таблице DBGrid1
должны появится фамилии преподавателей с указанной должностью
Вызов хранимой процедуры действия
Для вызова процедуры действия в среде IBConsole используется оператор
EXECUTE PROCEDURE имя_процедуры [(список_входных параметров)].
В приложениях используется компонент StoredProc.
При настройке
компонента нужно задать значения свойств:
DatabaseName – имя БД,
StoredProcName – имя хранимой процедуры,
Params – массив параметров.
Значения параметров задаются так же, как и значения параметров SQL
запроса.
Для выполнения хранимой процедуры в приложении необходимо
последовательно выполнить методы Prepare и ExecProc, при необходимости
можно переустановить значения входных параметров.
Начните новый проект. Поместите на форму компоненты StoredProc1,
Edit1 – результат процедуры, Button1 – запуск процедуры, Button2 – очистка
результата.
Введите обработчик OnClick кнопки Button1:
Procedure TForm1.Button1Click(…);
Begin
StoredProc1.StoredProcName:=‟pPrepod‟;
StoredProc1.Prepare;
StoredProc1.ExecProc;
Edit1.Text:=FloatToStr(StoredProc1.ParamByName(„opAvgAge‟).Value);
End;
Сохраните и выполните проект.
Генераторы и триггеры
Триггер – процедура, которая находится на сервере и вызывается
автоматически при модификации записей БД. Триггер нельзя вызвать из
приложения клиента, передать ему параметры и получить от него
результаты. По характеру действия триггер похож на обработчики событий
типа BeforEdit, AfterEdit и др. Триггеры используются для программной
реализации бизнес-правил (ограничений целостности).
Триггер создается оператором
CREATE TRIGGER имя_триггера FOR имя_табицы
[ACTIVE | INACTIVE] {BEFOR | AFTER} {UPDATE | INSERT | DELETE}
[POSITION число] AS тело_триггера
Триггер удаляется оператором DROP TRIGGER имя_триггера.
Язык программирования триггеров аналогичен языку хранимых процедур.
В теле триггера к полям таблицы можно обращаться с приставкой OLD
(старое значение) или NEW (новое значение).
Генераторы
Для обеспечения уникальности значений ключевых атрибутов в InterBase
используются генераторы. Генератор создается оператором
CREATE
GENERATOR имя. Начальное значение генератора задается командой SET
GENERATOR имя TO нач_значение.
Обращение к генератору выполняется функцией
GEN_ID(имя, шаг),
которая возвращает увеличенное на «шаг» значение генератора. Такое
обращение можно использовать в операторе INSERT или триггере.
Обратимся к базе данных Raspisanie. Видно, что она состоит из связанных
таблиц: таблица Rasp (подчиненная) содержит поля
nomer_gr и ident_pr,
которые должны совпадать с ключевыми полями записей таблиц (главных)
Grupy и Prepod, представляющих группу и преподавателя
с заданным
номером группы и идентификатором преподавателя. При удалении записей
главных таблиц или изменении их потенциальных ключей связанные записи
подчиненных таблиц должны подвергаться соответствующим изменениям –
это требование ссылочной целостности.
Реализуем обеспечение ссылочной целостности БД Raspisanie с помощью
хранимых процедур. Наберите текст сценария.
CREATE GENERATOR GenPrepod;
SET GENERATOR GenPrepod TO макс_знач ident_pr в_табл Prepod;
SET TERM !! ;
CREATE TRIGGER TrPrep1 FOR Prepod;
ACTIVE
BEFOR INSERT
AS
BEGIN
NEW.ident_pr=GEN_ID(GenPrepod,1);
END !!
CREATE TRIGGER TrPrep2 FOR Prepod
ACTIVE
AFTER DELETE
AS
BEGIN
DELETE FROM Rasp WHERE Prepod.ident_pr=Rasp.ident_pr;
END!!
CREATE TRIGGER TrGrup FOR Gruppy
ACTIVE
AFTER DELETE
AS
BEGIN
DELETE FROM Rasp WHERE Gruppy.nomer_gr=Rasp.nomer_gr;
END!!
SET TERM : !!
Загрузите и выполните сценарий. Запустите проект «изменение набора
данных» и удалите несколько записей преподавателей. Убедитесь, что
связанные записи таблицы Rasp также удалены из БД (содержимое таблиц
можно просмотреть с помощью IBConsole).
7. Механизмы распределенной обработки в Delphi
Кеширование изменений
Кеширование изменений заключается в том, что на компьютере клиенте в
кеше (буфере) создается локальная копия данных, в которой и производятся
все изменения. В дальнейшем сделанные изменения можно утвердить,
переслав их в базу данных, или отказаться от них. В отличие от механизма
транзакций кеширование передает в БД все изменения сразу, одним пакетом,
что значительно снижает нагрузку на сеть.
Для кеширования изменений используются компоненты Database, Table,
Query
и
UpdateSQL.
Основное
назначение
компонента
UpdateSQL
заключается в выполнении SQL-запросов на обновление связанного с ним
набора данных Query. Компонент хранит запросы на обновление, вставку и
удаление записей в свойствах ModifySQL, InsertSQL, DeleteSQL. Запросы
можно вводить вручную или использовать редактор свойств компонента,
способный автоматически генерировать тексты запросов для заданных
параметров запроса. Сгенерированные запросы можно редактировать.
Для перенесения изменений из кеша в БД используются методы
ApplyUpdates и CommitUpdates компонента Query.
Пример транзакции переноса изменений.
Используемые компоненты: Database1, Query1, DataSource1, DBGrid1,
UpdateSQL1.
Значения свойств:
Query1.UpdateObject=UpdateSQL1;
Query1.CashedUpdates=true;
Query1.RequestLive=true;
UpdateSQL1.InsertSQL=”INSERT INTO
таблица (поле1, поле2,…)
VALUES (:поле1, :поле2,…);”
UpdateSQL1.UpdateSQL=”UPDATE таблица SET
поле1=:поле1,
поле2=:поле2,
…
WHERE поле=:поле;”
UpdateSQL1.DeleteSQL=”DELETE
FROM
таблицаWHERE
поле=:old_поле;”
Здесь :поле, :поле1,… - параметры, представляющие значения одноименных
полей текущей записи в кеше; old – значение поля до модификации.
Транзакция:
Database1.StartTransaction;
try
Query1.ApplyUpdates;
Database1.Commit;
except
Database1.Rollback;
Raise;
end;
Query1.CommitUpdates;
Механизм событий сервера
Механизм событий используется сервером InterBase для посылки
сообщений клиентским приложениям. С этой целью на сервере создается
триггер или хранимая процедура, а в приложении регистрируется сообщение.
Сообщение посылается оператором POST_EVENT “имя_события”. Триггер
посылает сообщения автоматически при возникновении событий, хранимая
процедура должна запускаться сервером или приложением.
Для регистрации сообщений в приложении используется компонент
IBEventAlerter, связанный с компонентом Database.
Свойство Events
определяет список событий, на которые реагирует приложения. Список
событий можно редактировать как на этапе проектирования, так и во время
выполнения приложения. Регистрация события выполняется методом
RegisterEvents, отмена регистрации – методом UnRegisterEvents. Обработка
события выполняется обработчиком OnEventAlert.
Пример.
Посылка сообщения (триггер).
CREATE TRIGGER имя FOR таблица
ACTIVE
AFTER INSERT
AS
BEGIN
POST_EVENT “имя_события”;
END
Приложение. Регистрация события.
procedure TForm1.FormCreate();
begin
IBEventAlerter1.Events.Clear;
IBEventAlerter1.Events.Add(имя_события);
IBEventAlerter1.Events.RegisterEvents;
end;
Обработка события.
procedure
TForm1.IBEventAlerter1EventAlert(Sender;
EventCount;
Var CancelAlerts);
begin
if EventName=”имя_события” then
begin … end;
end;
*Практические задания к теме
Транзакции и кешированные изменения
EventName;
Транзакция – последовательность операций, переводящая БД из одного
целостного состояния в другое. Транзакция обладает свойством атомарности:
либо успешно выполняются все операции транзакции (успешная транзакция),
либо, в случае ошибки, не выполняется ни одна операция (неуспешная
транзакция).
Транзакции бывают явные и
неявные. Неявная
запускается
при
модификации набора данных операторами Edit, Insert и др., подтверждается
методом Post, аннулируется методом Cancel. Явная транзакция управляется
программистом. Для реализации явных транзакций используются методы
StartTransaction, Commit и Rollback компонента DataBase.
Типичная схема управления транзакциями:
Database1.StartTransaction;
Try
//пробный блок
Dataset1.Edit;
//режим модификации
…
Dataset1.Post;
//подтверждаем изменения
Database1.Commit;
//подтверждаем транзакцию
Except
//обработка исключений
messageDlg( ..подходящее сообщение ..);
Database1.Rollback;
//аннулируем транзакцию
End;
Кеширование изменений заключается в том, что на компьютере клиента в
кеше (буфере) создается локальная копия данных, и все изменения
выполняются в этой копии. Сделанные изменения можно утвердить,
перенеся их в базу данных, или отказаться от них. В отличие от механизма
транзакций кешированные изменения передаются все сразу, одним пакетом,
что значительно снижает нагрузку на сеть. Для кеширования изменений
используются компоненты Database, Table, Query и UpdateSQL.
Основное назначение компонента UpdateSQL заключается в выполнении
запросов на обновление связанного с ним набора данных Query. Компонент
хранит три разных запроса на редактирование, вставку и удаление записей.
Запросы хранятся в свойствах ModifySQL, InsertSQL, DeleteSQL.
Запросы можно вводить вручную или использовать редактор свойств
компонента UpdateSQL, способный автоматически генерировать тексты
запросов для заданных параметров. Сгенерированные запросы можно
отредактировать.
Для перенесения изменений из кеша в БД используются методы
ApplyUpdates и CommitUpdates компонента Query.
Начните новый проект. Поместите на форму компоненты Query1,
DataSource1,
DBGrid1,
DBNavigator
и
кнопку
Button1
(«внести
изменения»). Установите свойство DatabaseName компонента Database1 в
“Raspisanie”. Свяжите, как и ранее, компоненты Query1, DataSource1,
DBGrid и DBNavigator. Свяжите компонент Query1 с таблицей Gruppy.
Установите
свойство
UpdateObject
компонента
Query1
равным
UpdateSQL1, а свойства CashedUpdates=true, RequestLive=true.
Задайте запросы компонента UpdateSQL:
Для InsertSQL:
INSERT INTO Gruppy(nomer_gr, fak, kurs)
VALUES (:nomer_gr,:fak,:kurs);
Для UpdateSQL:
UPDATE Gruppy SET
Nomer_gr=:nomer_gr,
Fak=:fak,
Kurs=:kurs
WHERE nomer_gr=:nomer_gr;
Для DeleteSQL:
DELETE FROM Gruppy WHERE nomer_gr=:old_nomer_gr;
Здесь :nomer_gr, :fak и т.д. – параметры, представляющие значения
одноименных полей текущей записи в кеше, префикс old представляет старое
значение поля.
Напишите обработчик для кнопки Button1.
procedure Tform1.Button1.Click (…);
begin
Database1.StartTransaction;
try
Query1.ApplyUpdates;
Database1.Commit;
except
Database1.Rollback;
Raise;
end;
Query1.CommitUpdates;
end;
Запустите приложение, и с помощью DBGrid1 введите в БД несколько
новых записей, удалите и обновите часть старых. Кнопкой Button1
перенесите
изменения из кеша в БД. Закройте приложение и повторно
запустите его – сделанные при первом запуске изменения должны
отобразиться в БД.
Технология DDE
DDE (Dynamic Data Exchange – динамический обмен данными) – один из
ранних способов взаимодействия приложений в ОС Windows – позволяет
программам клиентам и серверам обмениваться данными (текстом). Многие
приложения корпорации Microsoft поддерживают этот протокол, могут
выполнять функции сервера DDE.
В Delphi имеются 4 компонента DDE:
DDEClientConv – связь клиента с сервером DDE,
DDEClientItem – объект обмена с сервером,
DDEServerConv – сервер DDE,
DDEServerItem – объект обмена с клиентом.
Свойства компонента DDEClientConv:
DDEService – серверное приложение,
DDETopic – имя серверного объекта обмена.
Методы DDEClient Conv:
PokeData(Item, Data): Boolean – вставить данные в объект обмена,
RequestData(Item): Pchar – получить данные.
Компоненты DDEClientConv и DDEClientItem позволяют приложениюклиенту обмениваться данными с сервером DDE. Информация о поддержке
DDE конкретными программами Microsoft можно найти в соответствующей
эксплуатационной документации. Существует простой способ проверки
наличия DDE у ряда программ Microsoft с помощью буфера обмена на этапе
проектирования приложения. Например, для того чтобы установить, является
ли программа Excel DDE-сервером, следует скопировать содержимое ячейки
Excel в буфер и запустить в инспекторе объектов Delphi редактор свойств
DDEService или DDETopic. Если данные были скопированы из сервера DDE,
то будет активна кнопка Paste Link. После щелчка на этой кнопке в поля
DDEService и DDETopic будут внесены соответствующие значения. Щелчок
на кнопке OK и связь установлена.
Задание.
Написать
приложение,
DDEClientConv, Edit и
форма
которого
содержит
элементы
кнопки «Послать» и «Получить». «Послать»
пересылает данные из Edit в Excel, «Получить» - принимает данные из Excel
в Edit.
Посылка данных:
StrPCopy(Источник, „текст‟);
DDEClientConv1.PokeData(„RnCm‟, Источник);
где RnCm – ячейка Excel с координатами n,m; Источник – переменная типа
array [ …] of char.
Получение данных:
Получатель:=DDEClientConv1.RequestData(„RnCm‟);
где Получатель – переменная типа PChar.
Технология OLE
Технология OLE (Object Linking and Embedding – связывание и внедрение
объектов) позволяет связывать или внедрять в приложение объекты
программ Microsoft. Внедряемый или связываемый объект называется
контейнером OLE (компонент OLEContainer). Таким способом можно
вставлять в приложение рисунки, диаграммы, музыку, видеоклипы, слайды,
документы Word и многое другое.
Контекстное
меню
компонента
OLEContainer
содержит
команду
InsertObject, помещающую объект на форму приложения. Необходимо
указать тип объекта и установить переключатель новый/из файла. Далее с
добавленным объектом
можно работать, используя соответствующее
средство Windows.
Технология OLE развивает возможности DDE, позволяя обмениваться не
только данными, но и объектами, управлять приложениями Windows.
Задание.
Помесите на форму компонент OLEContainer и включите в приложение
электронную таблицу, текст Word, рисунок, формулу и другие объекты по
выбору. Запустите приложение и поработайте с добавленными объектами.
Динамические библиотеки
Одним из простейших способов взаимодействия программ является
использование DLL (Dynamically Linked Library), которые подключаются к
приложению динамически после его запуска. Использование DLL экономит
оперативную память, упрощает построение проектов.
Для
построения
библиотеки
нужно
выполнить
команду
File/New/Other/DLL Wizard, которая создает пустую заготовку библиотеки.
В код библиотеки вставляется описание требуемых процедур и функций, а в
его конец
добавляется список экспорта (ключевое слово exports). При
необходимости к библиотеке можно добавить
форму (File/New/Form) и
разместить на ней требуемые компоненты.
При работе с библиотечными формами в приложении следует помнить,
что последние должны создаваться динамически, т.к. Delphi не обеспечивает
их автоматического построения. В интерфейсной части модуля приложения
следует описать все импортируемые функции.
Задание.
Построить
приложение
и
поддерживающее
его
DLL.
На
форме
приложения размещены метка и кнопка. На форме DLL – элемент
редактирования и кнопка. При нажатии кнопки приложения вызывается DLL
и принимает текст в элемент редактирования своей формы. Последующее
нажатие кнопки DLL передает текст в приложение. Приложение помещает
полученный текст в метку.
Порядок работы:
Создать пустую библиотеку.
Включить в библиотеку исходные коды процедуры загрузки формы и
обработчика кнопки.
Добавить в конец библиотеки список экспорта.
Добавить к текущей группе проектов новый проект.
Написать обработчик нажатия кнопки приложения.
Добавить в интерфейсную часть модуля приложения описания
импортируемых
функций:
описание
функции;
external
‟файл
библиотеки‟;
Выполнить приложение.
Потоки
Поток управления – это процесс. Любая программа Windows реализуется
как совокупность параллельных потоков, работающих в одном адресном
пространстве
и
использующих
ее
ресурсы.
Явное
использование
программистами потоков способствует ускорению выполнения программы.
Поток
в
Delphi
представляется
компонентом
Thread,
имеющим
необходимые свойства и методы управления потоками. Автоматически
устанавливаемое свойство Terminated указывает состояние потока. Метод
Execute задает логику работы потока, метод Resume начинает или
возобновляет
выполнение
потока,
метод
Synchronize
обеспечивает
корректность выполнения параллельных потоков.
Разработаем многопоточную программу, форма которой содержит два
компонента PaintBox, заполняемых двумя параллельными потоками.
Порядок работы:
1. Создать новое приложение.
2. Поместить на форму два PaintBox и кнопку запуска потоков.
3. Добавить в проект класс-поток (File/New/Other/Thread Object).
4. Указать имя класса (TMyThread).
5. Добавить в описание класса переменную Flag: Boolean.
6. Переопределить метод Execute:
procedure TMyThread.Execute;
begin
while not Terminated do
if Flag then Synchronize(Form1.Paint1);
else Synchronize(Form1.Paint2);
end;
Переменная Flag определяет PaintBox, который заполняется в данный
момент.
Процедуры
Paint1
и
Paint2
осуществляют
рисование
в
соответствующих областях. Для корректного использования графических
ресурсов применяется синхронизация процедур.
7. В класс TForm1 добавить потоковые переменные T1 и T2.
8. Написать обработчик кнопки для TForm1:
…
T1:=TMyThread.Create(true);
T1.Flag:= true;
T2:=TMyThread.Create(true);
T2.Flag:= false;
T1.Resume;
T2.Resume;
…
9. Написать процедуры рисования для TForm1:
procedure TForm1.Paint1;
begin
// рисование в PaintBox1
end;
procedure TForm1.Paint2;
begin
// рисование в PaintBox2
end;
10. Связать модули главной формы и потока: раздел interface Unit1
ссылается на Unit2, раздел implementation Unit2 ссылается на Unit1.
8. Технология COM
ОС Windows – многозадачная операционная система, в которой
одновременно могут выполняться несколько взаимодействующих программ,
некоторые из которых являются клиентами, а другие – серверами.
Рассмотрим несколько технологий взаимодействия приложений в Windows.
Модель COM (Component Object Model) – независимая от языка
программирования базирующаяся на объектах спецификация.
Модель
определяет способ построения и доступ к компонентным объектам.
Компонентный
объект
является
экземпляром
некоторого
класса
и
поддерживает ряд интерфейсов, которые используются клиентами для
доступа к службам объекта. Каждый интерфейс является набором методов
объекта. Клиент не имеет непосредственного доступа к данным объекта, для
этого используются методы.
В технологии различают два типа программ: клиенты и серверы. Сервер
COM является исполняемым файлом или динамической библиотекой,
содержащей один или несколько объектов COM. Имеется три типа серверов:
внутренние
серверы
(in-process)
–
динамические
библиотеки,
подключаемые к приложению-клиенту и работающие с ним в одном
адресном пространстве;
локальные серверы (внешние) – отдельные приложения, работающие на
одном компьютере с клиентом;
удаленные серверы (remote) – приложения, работающие на удаленном
компьютере.
Клиент COM – приложение (или DLL), использующее объект COM.
Клиенту обычно неизвестно место расположения сервера.
Обращение к
серверу производится по имени объекта COM. Поиск и запуск подходящего
сервера выполняет ОС Windows.
Схема доступа к объекту COM:
1. Клиент запрашивает компонентный объект;
2. ОС выполняет поиск сервера для объекта, запускает его и возвращает
клиенту указатель на запрошенный интерфейс.
Информация о расположении сервера находится в реестре Windows.
Интерфейс COM
Интерфейсы COM имеют два имени: строковое имя, начинающееся с
буквы I, и глобальный уникальный идентификатор (GUID). Строковые имена
интерфейсов разных объектов могут совпадать, уникальные никогда не
совпадают. GUID для объекта называется идентификатором класса (CLSID),
GUID для интерфейса – идентификатором интерфейса (IID).
GUID – 16-байтовая величина, автоматически генерируемая при создании
COM-объекта
или
интерфейса.
Уникальность
GUID
обеспечивается
использованием при его создании показаний таймера и сетевого адреса
компьютера (или другой уникальной величины).
Интерфейс IUnknown
Это базовый интерфейс всех объектов COM. Методы интерфейса:
QueryInterface, AddRef, Release. Метод QueryInterface возвращает указатель
на интерфейс объекта, идентификатор IID которого передается в параметре
метода. Если запрошенный интерфейс не поддерживается объектом, то
возвращается NULL. Имея указатель на один интерфейс объекта, клиент
может получить указатели на другие интерфейсы. Эта схема позволяет
добавлять
новые
интерфейсы,
не
влияя
на
работу
приложений,
использующих старые интерфейсы. Технология COM запрещает изменять
существующие интерфейсы.
Методы AddRef и Release. Объекты COM могут использоваться
несколькими клиентами одновременно, поэтому завершение использования и
уничтожение объекта возлагается на сам объект. Для этого используется
механизм подсчета ссылок на объект, который и поддерживается методами
AddRef и Release. Выдавая указатель на один из своих интерфейсов, объект
увеличивает счетчик ссылок на 1. Если клиент передает указатель
интерфейса другому клиенту, то второй клиент должен выполнить метод
AddRef (добавить ссылку). Работа клиентов с интерфейсом должна
завершаться методом Release (счетчик ссылок уменьшается на 1).
Объект уничтожает сам себя, когда счетчик ссылок становится равным 0.
Таким
образом,
правильность
подсчета
ссылок
обеспечивается
программистом. Если клиент не использует или неправильно использует
методы, то объект может зависнуть или преждевременно уничтожится.
Библиотека COM
Библиотека COM содержит функции базовых служб объектов и клиентов,
предоставляет пользователям средства запуска серверов объектов. Доступ к
службам библиотеки осуществляется через вызовы функций, имена которых
начинаются с префикса Co (например, CoCreateInstance).
Фабрика класса
Если клиенту нужен только один COM-объект, то можно использовать
функцию CoCreateInstance, если требуется несколько объектов одного класса,
то следует использовать фабрику класса (class factory) – объект, способный
создавать экземпляры других объектов. В отличие от обычных объектов,
фабрика класса поддерживает интерфейс IClassFactory, в котором имеются
два метода: CreateInstance (создает новый объект) и LockServer (оставляет
сервер в памяти после создания объекта).
Для получения доступа к фабрике класса используется функция
библиотеки COM
CoGetClassObject. Функции передается идентификатор
CLSID класса объъектов, которые будут создаваться фабрикой и IID
интерфейса IClassFactory. Функция возвращает указатель на интерфейс
IClassFactory, после чего методом CreateInstance интерфейса IClassFactory
создается объект COM.
Создание объектов COM в Delphi
Объект COM и объект Delphi практически совпадают. Интерфейс COM
напоминает объект Delphi, у которого отсутствуют свойства и имеются лишь
виртуальные методы. Некоторая проблема создания COM-объектов в Delphi
связана с отсутствием множественного наследования. Для решения этой
проблемы используется следующий подход. Объект COM создается на
основе обычного класса Object Pascal, который имеет имя TComObject и
является непосредственным потомком класса TObject. Свойства и методы
объекта COM описываются так, как это принято в Object Pascal.
Одновременно создается еще один класс, содержащий описания всех
интерфейсов объекта COM. Этот класс называется компонентным классом
(CoClass)
и
ему
дается
имя
объекта
COM
с
приставкой
Co
(MyObject CoMyObject). В результате, класс, наследник TComObject,
содержит код объекта, а компонентный класс – описание интерфейсов (в
соответствии с моделью COM).
Объявление и описание компонентного класса содержится в библиотеке
типов, которая всегда создается при построении COM-объекта. Для создания
объектов COM с использованием библиотеки типов применяется класс
TTypedComObject.
Описание интерфейса
Пример описания.
IUnknown=interface
[‘{00000000-0000-0000-0000-000000000053}’]
function QueryInterface(const IID:TGuid; out:Obj):integer; stdcall;
function _AddRef:integer; stdcall;
function _Release:integer; stdcall;
end;
Код описания генерируется автоматически с помощью библиотеки типов.
Создание внутреннего сервера COM
Внутренний сервер – DLL, содержащая по крайней мере один объект
COM. Пустая библиотека создается командой
File/New/ActiveX/ActiveX
Library.
Для добавления объекта используется мастер COM Object Wizard: File/
New/ ActiveX/ COM Object.
Задаются параметры объекта:
Имя класса COM (ClassName);
Способ создания экземпляров COM (Instancing):
Internal – объект используется внутри процесса клиента;
Single Instance – один сервер для всех клиентов, отдельный
объект для каждого клиента;
Multiple Instance – у каждого клиента свой сервер.
Способ взаимодействия сервера и клиентов (Threading Model):
Single – последовательное обслуживание;
Apartment – вызов объекта выполняется в потоке, в котором
создан и
сам объект; поддерживается одновременная работа
нескольких объектов;
Free – объект может обслуживать произвольное число клиентов
одновременно;
Both – комбинация Apartment и Free.
Установим значения:
ClassName=TestCom;
Instancing=Multiple Instance;
Threading Model=Single;
Including Type Library= true.
После установки необходимых значений мастер создает заготовку модуля
объекта TestCom и открывает редактор библиотеки типов.
Модуль:
unit TestCom;
interface
uses Windows, ActiveX, Classes, ComObj, TestComServer_TLB, StdVcl;
type
TTestCom= class(TTypedComObject, ITestCom)
protected
{ITestCom methods}
end;
implementation
uses ComServ;
initialization
TTypedComObjectFactory.Create(ComServer,
TTestCom,
Class_TestCom,
ciMultyInstance, tmSingle);
end.
Для построения библиотеки типов в Delphi принято использовать Object
Pascal (в других системах язык IDL). Код библиотеки генерируется
автоматически, для изменений используется редактор. Первоначально
библиотека типов содержит описание только одного интерфейса (ITestCom) и
одного класса (CoTestCom). В дальнейшем с помощью редактора в
библиотеку добавляются новые интерфейсы и методы.
Новые интерфейсы добавляются командой New Interface, новые методы –
командой New Method. При задании метода указывается его имя, тип
возвращаемого значения, передаваемые параметры. Разрешены только
скалярные типы параметров. Для передачи массива используется вариантный
тип. Далее следует привязать новые интерфейсы к объекту COM (команда
Insert Interface) и перенести изменения в код библиотеки и объект COM
(команда Refresh).
Пишется код для каждого нового метода интерфейса. Некоторая
особенность программирования связана с использованием вариантных
массивов. Для создания массивов используются функции:
Function
VarArrayCreate(const
Bounds:
array
of
Integer;
VarType:
Integer):Variant – выделяет область памяти и возвращает указатель на нее;
Function VarArrayOf(const Values: array of Variant): Variant – возвращает
область памяти и инициализирует ее заданными значениями.
Функция VarArrayLowBound(const A: Variant; Dim: Integer): Integer
возвращает минимальный индекс измерения с номером Dim массива A;
функция
VarArrayHighBound(const
A:
Variant;
Dim:
Integer):
Integer
возвращает максимальный индекс измерения Dim массива A.
После задания кода методов выполняется компиляция Dll и регистрация
сервера. Регистрация в среде Delphi: Run/Register ActiveX Server.
Разработка клиентского приложения для внутреннего сервера.
Приложение, использующее объект COM, называется клиентом COMобъекта. Оно является обычным приложением Delphi. Для взаимодействия
приложения с объектом в раздел uses модуля приложения включается
библиотека типов (TestComServer_TLB). Для вызова методов объекта
объявляются переменные указатели на соответствующие интерфейсы.
TForm1=class (TForm)
…
private
IntVar1:ItestCom1;
IntVar2:ItestCom2;
…
end;
Для создания объекта COM используется метод Create компонентного
класса объекта (CoClass), который возвращает указатель на главный
интерфейс.
Для
получения
указателей
других
интерфейсов
использовать метод QueryInterface основного интерфейса.
procedure TForm1.FormShow (Sender:Tobject);
begin
IntVar1:=CoTestCom.Create;
InVar1.QueryInterface(ITestCom2,IntVar2);
…
end;
следует
Метод интерфейса вызывается обычным способом: IntVar1.метод.
*Практические задания к теме
Создание компонентов COM
Одним из способов реализации взаимодействия приложений в ОС
Windows является технология COM – основанная на объектах, независимая
от
языка
программирования
спецификация,
определяющая
способ
построения компонентных объектов и предоставления доступа к ним.
Компонентный объект является экземпляром некоторого класса и содержит
ряд интерфейсов, которые используются клиентами для доступа к службам
объекта. Интерфейс содержит
объявления
доступных пользователю
методов без указания их реализации.
Основные элементы модели COM: сервер COM, объект COM, клиент
COM, интерфейс COM, библиотека типов COM, фабрика классов COM.
Сервер COM – исполняемый файл или динамическая библиотека,
содержащая один или несколько объектов COM.
Клиент COM – приложение или DLL, использующее объект COM.
Объект COM – объект типа TComObject, методы которого доступны
только через его интерфейсы. Интерфейсы объекта в Delphi описываются
отдельно в связанном с объектом компонентном классе (CoClass).
Библиотека типов COM – файл с расширением .tlb, содержащий
описания компонентных классов (CoClass) объектов.
Фабрика
классов
–
объект
COM
с
интерфейсом
IClassFactory.
Применяется для создания объектов COM.
Система программирования Delphi поддерживает технологию COM,
позволяет разрабатывать программы серверы и клиенты COM.
Задание.
Разработать программы клиент и сервер COM. Внутренний сервер COM
(DLL) с именем MyComServer содержит два интерфейса: IMyCom и
IMyCom1.
Методы интерфейса IMyCom:
Function min(A:oleVariant):Integer – наибольшее,
Function max(A:oleVariant):Integer – наименьшее.
Методы интерфейса IMyCom1:
Function avg(A:oleVariant):Single – среднее,
Function std(A:oleVariant):Single – среднеквадратичное отклонение.
Клиент – приложение, форма которого содержит компонент ListBox, два
компонента Label и две кнопки. В компоненте Список указываются
несколько целых чисел, одна кнопка служит для вычисления min/max списка
целых, другая – для статистических вычислений. Результаты вычислений
помещаются в компоненты Метка.
Последовательность построения внутреннего сервера:
Создание DLL.
Создание объекта COM.
Создание интерфейсов объекта COM.
Задание кода методов интерфейса.
1. Создание DLL.
Начните новый проект командой
генерации библиотечного файла:
File/New/Other/ActiveX/ActiveX Library.
Файл создан.
2. Создание объекта COM.
Запустите программу Мастер COM-объектов: File/ New/ Other/ ActiveX/
COM Object. Задайте параметры Мастера:
ClassMame - имя класса COM (значение MyCom);
Instancing – способ создания экземпляров COM (значение Multiple instance
– у каждого клиента свой сервер);
Threading model – способ взаимодействия сервера и клиентов (значение
Single – последовательное обслуживание).
Установите флаг Include Type Library, сбросьте флаг Mark interface
OleAutomation.
Создается модуль объекта MyCom, открывается редактор библиотеки
типов.
3. Создание интерфейсов COM-объекта.
Интерфейсы объекта описываются в библиотеке типов. Первоначально
библиотека содержит описание одного класса (в нашем случае CoMyCom) и
одного интерфейса – IMyCom. Для добавления новых интерфейсов
используется редактор.
Добавление интерфейса:
Выполнить команду New Interface редактора.
Ввести имя интерфейса.
Установить Parent Interface = IUnknown.
Снять флажки страницы Flags.
Задание методов интерфейса:
Выбрать интерфейс.
Выполнить команду New Method.
Задать параметры метода (имя метода, тип возвращаемого значения,
имена и типы входных параметров).
Параметры могут быть только скалярного типа. Для передачи массива
следует использовать тип Variant.
Новые интерфейсы и методы следует привязать к COM-объекту. Для этого
в окне редактора выбирается объект и на вкладке Implements командой
контекстного меню Insert Interface добавляется нужный интерфейс.
Командой Refresh сделанные изменения переносятся в библиотеку типов и
модуль объекта.
4. Задание кода методов интерфейса.
В модуле объекта пишется код для каждого метода новых интерфейсов.
Особенностью кода является использование для передачи параметров
вариантных массивов. Для этого используются следующие функции:
function
VarArrayCreate(const
Bounds:
array
of
integer;
VarType:Integer):Variant – выделяет область памяти и возвращает указатель
на нее;
function VarArrayOf(const Values:array of Variant):Variant – выделяет
область памяти, инициализирует ее указанными значениями и возвращает
указатель области;
function VarArrayLowBound(const A:Variant; Dim:Integer):Integer –
минимальное значение индекса измерения Dim массива A;
function VarArrayHighBound(const A:Variant; Dim:Integer):Integer –
максимальное значение индекса измерения Dim массива A.
После задания методов DLL компилируется, и производится регистрация
сервера: Run/Register ActiveX Server. Сервер создан.
Разработка приложения-клиента
Клиент – обычное приложение Delphi. Для вызова методов объекта в
классе формы объявляются переменные – указатели интерфейсов: variable:
interfacename. Вызов метода интерфейса: variable.method. Для создания
COM-объекта можно использовать метод Create компонентного класса
объекта,
который
возвращает
variable:=CoMyCom.Create.
используется
метод
Для
указатель
доступа
QueryInterface
на
к
главный
другим
основного
интерфейс:
интерфейсам
интерфейса:
variable.QueryInterface(interfacename2,variable2) – variable2 принимает
ссылку на interface2.
9. Технологии OLE и ActiveX
Автоматизация OLE
Автоматизация OLE является усовершенствованием технологии COM,
позволяющим
одним
приложениям
использовать
функции
других
приложений. Автоматизация – механизм обмена информацией между
приложениями в ОС Windows, обеспечивающий их взаимодействие. Объект
автоматизации принципиально не отличается от объекта COM, основное
отличие от COM – использование для доступа к объектам специальных
интерфейсов диспетчеризации (dispinterface), упрощающих обращение к
объекту.
Основные элементы технологии: сервер автоматизации, контроллер
автоматизации, библиотека типов, интерфейс IDispatch.
Сервер автоматизации – исполняемый модуль, включающий несколько
объектов
автоматизации.
выполняющиеся
в
Различают
адресном
внутренние
пространстве
клиента,
серверы
и
(DLL),
внешние
–
самостоятельные приложения. Внутренние серверы имеют высокую скорость
обмена, внешние более надежны.
Контроллер автоматизации – клиентское приложение, управляющее
объектом автоматизации.
Библиотека типов. Типовая информация хранится в файлах .tlb и .olb и
включает:
Описания интерфейсов, включая интерфейс диспетчеризации;
Описания классов компонентных объектов;
Ссылки на другие библиотеки.
Интерфейс IDispatch – интерфейс COM, производный от
IUnknown.
Основное отличие от COM – вызов методов объектов через специальный
метод
Invoke,
с
которым
связывается
дополнительный
интерфейс,
указывающий доступные для него методы. Каждому методу интерфейса
сопоставляется диспетчерский идентификатор (dispid), служащий для вызова
методов через Invoke.
Создание сервера автоматизации в Delphi подобно построению сервера
COM, но имеет ряд особенностей. Объект автоматизации создается на основе
класса TAutoObject – потомка класса TTypedCOMObject.
Построение внешнего сервера автоматизации в Delphi
Приложение-сервер
является
обычным
приложением,
включающим
объекты автоматизации. В сервер включается новый объект автоматизации:
File/ New/ ActiveX/ Automation Object. Запускается мастер объекта
автоматизации, задаются параметры:
CoClassName – имя класса объекта автоматизации;
Instancing – способ создания объекта (аналог COM);
Threading Model – работа с потоками (аналог COM);
Generate Event Support code – поддержка обработки событий.
Создается объект и открывается окно редактора библиотеки типов с
описаниями
интерфейсов
объекта
и
интерфейсов
диспетчеризации.
Интерфейсы и методы объекта создаются с помощью редактора. Создание
методов имеет ряд особенностей: результат, возвращаемый функцией, может
иметь только тип HRESULT, поэтому для возврата результата требуется
использовать параметр вызова процедуры. Работая в редакторе, следует
указать для параметра-результата атрибут out и добавить символ «*» к имени
типа параметра. После задания методов и описания параметров выполняется
команда Refresh, и изменения переносятся в библиотеку типов. Объект
автоматизации создан. Внешний сервер не регистрируется.
Построение клиента автоматизации
Клиент автоматизации – обычное приложение, использующее объекты
автоматизации. Для создания экземпляра объекта и получения указателя на
интерфейс
используется
функция
CreateOleObject
(
const
имя_сервера.имя_объекта:string ): IDispatch. Для работы с объектами
автоматизации используются переменные типа OleVariant.
Var
s:OleVariant;
…
s:=CreateOleObject(„сервер.объект‟);
…
s.Method1(Param1,Param2);
…
Этот способ работы использует вариант позднего связывания методов, не
позволяющий проверять корректность вызовов во время компиляции. Для
раннего связывания в клиенте используется библиотека типов и правила
работы с обычными COM-объектами.
Элементы управления ActiveX
Терминология и история
Первоначально элементы ActiveX назывались элементами OLE или OCX.
Позднее OCX были приспособлены к использованию в Internet и
переименованы в ActiveX. С точки зрения COM элементы ActiveX –
внутренние серверы, поддерживающие технологию Automation. В настоящее
время под ActiveX понимаются все технологии на основе COM (OLE).
ActiveX и компонентное программирование
Элемент
ActiveX
–
сервер,
поддерживающий
автоматизацию,
реализованный в виде динамической библиотеки, исполняющийся в
адресном
пространстве
приложения,
допускающий
визуальное
редактирование.
Компонентное программирование – программирование на основе
компонентов – готовых частей приложения. ActiveX реализует идею
компонентного программирования – в виде элемента ActiveX можно
реализовать что угодно – от кнопки до текстового редактора.
Достоинства компонентного программирования:
постепенное наращивание системы;
упрощается отладка, так как компоненты отлаживаются отдельно;
систему легче адаптировать;
компоненты допускают повторное использование;
компоненты доступны через сеть;
могут быть написаны на разных языках программирования;
упрощается модернизация системы.
ActiveX – стандарт компонентного подхода для разработки приложений
Windows. ActiveX доступна почти во всех современных средствах
разработки.
Недостатки технологии:
полноценная поддержка ActiveX имеется только в Windows;
компоненты не имеют механизма наследования и не реализуют
полиморфизм.
Использование ActiveX в Delphi
Страница ActiveX палитры компонентов содержит готовые компоненты
ActiveX. Другие компоненты ActiveX можно позаимствовать
в Internet.
Подключение
командой
к
Component/Import
Delphi
нового
ActiveX
компонента
Control,
выполняется
которая
открывает
список
зарегистрированных компонентов. Для добавления нового компонента
необходимо
его
зарегистрировать:
команда
Add,
выбрать
файл
с
компонентом, команда Install. После этого автоматически генерируется
библиотека типов, производится компиляция, и элемент ActiveX добавляется
в палитру компонентов на странице ActiveX. Работа с элементами ActiveX
ничем не отличается от работы с компонентами VCL.
Создание собственных элементов ActiveX
Элементы ActiveX в Delphi создаются на основе компонентов VCL или
форм. Построение ActiveX на основе компонентов осуществляется особенно
просто.
Рассмотрим
этот
способ
построения
ActiveX
на
примере
преобразования потомков класса TWinControl.
Команда File/New/Other/ActiveX/ActiveX Control
ActiveX. Устанавливаются
запускает мастера
параметры мастера: имя класса VCL, имя
создаваемого элемента, имя файла модуля, имя файла проекта, вариант
работы сервера с потоками. Автоматически генерируются файлы: файл
проекта, библиотека типов, модуль реализации. Проект компилируется.
Создание активных форм ActiveForm.
В элемент ActiveX можно преобразовать целую форму, содержащую как
визуальные, так и невизуальные компоненты, в том числе и компоненты
доступа к данным. Особенностью активных форм является недоступность
для приложений свойств, методов и событий
компонентов формы. Если
доступ все-таки необходим, то следует добавить в класс формы свойства и
методы,
позволяющие
управлять
компонентами.
Рассмотрим пример
построения активной формы, отображающей информацию таблицы БД.
С помощью мастера активных форм (Active Form) создается файл проекта,
модуль реализации, библиотека типов, форма. На форму помещаются
компоненты TADOTable, TDataSource и TDBGrid и связываются между
собой и с таблицей БД.
С
помощью
редактора
библиотеки
типов
задаются
свойства,
обеспечивающие открытие и закрытие БД и передачу информации в
приложение. Для этого к главному интерфейсу (IMyActiveForm) добавляются
свойства MyActive, Data и устанавливается их вид (Read/Write или Read
Only) и тип.
После обновления проекта (Refresh Implementation) задаются реализации
методов.
function TMyActiveForm.Get_MyActive:WordBool;
begin result:=ADOTable1.Active; end;
procedure TMyActiveForm.Set__MyActive(Value:WordBool);
begin ADOTable1.Active:=Value; end;
function TMyActiveForm.Get__Data:WideString;
begin result:=ADOTable1.FieldByName(„----„).AsString; end;
Для того чтобы обеспечить приложению возможность реагировать на
изменение положения курсора в таблице БД нужно задать обработчик
события After Scroll компонента ADOTable1. Обработчик создается
добавлением метода (OnScroll) к интерфейсу IMyActiveFormEvents
с
последующей привязкой его к событию After Scroll. Подробности привязки
приведены в практических заданиях.
Проект компилируется и регистрируется в
палитре компонентов.
Приложения могут взаимодействовать с компонентом, используя свойства
MyActive, Data и обработчик события OnScroll.
*Практические задания к теме
Автоматизация OLE
Автоматизация OLE – усовершенствованный вариант технологии COM,
использующий
для
доступа
к
объектам
специальные
интерфейсы
диспетчеризации (dispinterface), упрощающие работу с объектами.
Основные элементы технологии:
Сервер автоматизации. Приложение (внешний сервер) или динамическая
библиотека
(внутренний
сервер),
включающие
несколько
объектов
автоматизации.
Контроллер
автоматизации.
Приложение
клиента,
управляющее
объектом автоматизации.
Библиотека типов. Файлы с расширениями .tlb или .olb, хранящие
типовую
информацию:
описания
интерфейсов,
описания
классов
компонентных объектов, ссылки на другие библиотеки.
Интерфейс IDispatch. Отличается от COM-интерфейсов вызовом методов.
Для вызова используется специальный метод Invoke, параметром которого
является диспетчерский идентификатор вызываемого метода.
Построение сервера автоматизации в целом аналогично созданию сервера
COM. Объект автоматизации создается на основе класса TAutoObject,
производного от TTypedComObject.
Задание.
Разработать внешний сервер и контроллер автоматизации, реализующие
вычисления предыдущего задания (min, max, avr, std).
Последовательность действий.
1. Создать сервер автоматизации:
File/New Application.
2. Включить в сервер объект автоматизации:
File/New/Other/ActiveX/Automation Object.
Автоматически запускается мастер автоматизации. Задаются параметры:
CoClassName (имя класса объекта автоматизации), Instancing (способ
создания экземпляра объекта), Threading Model (работа с потоками).
Объект создается, и открывается редактор библиотеки типов.
3. Создание интерфейса и методов объекта автоматизации.
Интерфейсы и методы объекта автоматизации создаются с помощью
редактора библиотеки типов. Так как методы в автоматизации – процедуры,
для возврата результатов используются параметры вызова методов: к имени
типа параметра добавляется символ «*» (вызов по ссылке), в столбце modifier
задается «out».
После создания методов и описания их параметров, сделанные изменения
переносятся в библиотеку типов (команда Refresh). В модуле реализации
следует задать код методов.
Объект
автоматизации
создан.
Проект
сервера
компилируется.
Регистрировать внешний сервер не нужно.
4. Построение клиента автоматизации.
Начните новый проект. Включите в
приложение переменную типа
OleVariant, представляющую объект автоматизации. Для создания объекта
используется функция CreateOleObject, возвращающая ссылку на интерфейс
диспетчеризации. Единственным параметром функции является строка
символов
вида
«имя_сервера.имя_объекта»
(в
нашем
случае
«имя_проекта_сервера. имя_класса_объекта»). Методы объекта вызываются
принятым в ООП способом.
Элементы управления ActiveX
Элементы ActiveX – модификация управляющих элементов OLE (COM),
приспособленная к использованию в Internet. Фактически, элемент ActiveX
является внутренним сервером автоматизации, допускающим визуальное
редактирование.
Технология
ActiveX
поддерживает
компонентное
программирование.
Палитра компонентов Delphi
содержит большое количество готовых
компонентов ActiveX, которые используются так же, как и компоненты VCL.
Много
элементов
ActiveX
можно
позаимствовать
из
Internet.
Для
подключения нового готового компонента ActiveX к палитре компонентов
нужно выполнить команду Component/Import ActiveX Control и произвести
регистрацию компонента: нажать кнопку Add, выбрать файл с компонентом
и нажать кнопку Install. После этого автоматически генерируется библиотека
типов, производится компиляция пакета и элемент добавляется к палитре
компонентов на странице ActiveX.
Новые элементы ActiveX могут быть созданы на основе существующих
элементов VCL или на основе форм. Рассмотрим второй способ – построение
активных форм.
Преобразуемая
форма
может
содержать
как
визуальные,
так
и
невизуальные компоненты. Свойства, методы и события компонентов формы
напрямую в приложении недоступны. При необходимости такого доступа в
класс формы добавляются свойства и методы, позволяющие управлять
компонентами формы.
Задание. Построить активную форму для ввода информации из таблицы
базы данных.
Последовательность действий.
1. File/New/Other/ActiveX/Active Form.
2. Задать имя компонента ActiveForm (“MyActiveForm”).
3. Автоматически создается проект, содержащий файл проекта, модуль
реализации, библиотеку типов, форму.
4. Поместить на форму компоненты TADOTable, TDataSource, TDBGrid.
Связать компоненты между собой и с одной из существующих таблиц
InterBase.
5. Задать свойства, обеспечивающие открытие и закрытие таблицы из
приложения. Для этого переключаемся в редактор библиотеки типов,
выбираем интерфейс IMyActiveForm, выбираем вариант Read/Write кнопки
New Property, задаем имя свойства (MyActive). Добавленное свойство
отобразится в списке как пара свойств – одно для чтения, другое для записи.
Тип каждого свойства установите равным VARIANT_BOOL.
6. Выполнить команду Refresh Implementation. В файл проекта
автоматически
вносятся
изменения:
к
интерфейсу
IMyActiveForm
добавляется новое свойство и методы чтения/записи, в модуль реализации
добавляются заготовки методов.
Реализация методов:
function TMyActiveForm.Get_MyActive:WordBool;
begin result:=ADOTable1.Active; end;
procedure TMyActiveForm.Set_MyActive(Value:WordBool);
begin ADOTable1.Active:=Value; end;
7. Задать свойство (Data) для передачи информации из БД в приложение. В
списке New Property выбрать вариант ReadOnly, тип свойства установить в
BSTR.
8. Выполнить команду Refresh Implementation. Код реализации метода:
function TMyActiveForm.Get_Data:WideString;
begin result:=ADOTable1.FieldByName(„…‟).AsString; end;
9. Добавить в приложение реакцию на скроллинг таблицы. Для этого
задается
обработчик
события
AfterScroll
компонента
ADOTable1:
активизировать окно редактора библиотеки типов, выбрать интерфейс
IMyActiveFormEvents,
добавить
метод
OnScroll,
выполнить
Refresh
Implementation.
Вручную в библиотеке типов производятся дополнительные модификации
в классе TMyActiveForm: изменить тип FOnScroll на TDatasetNotifyEvent, тип
OnScroll на TDatasetNotifyEvent, в раздел Uses добавить модуль Db.
10. Добавить в файл реализации в класс формы заголовок
procedure ScrollEvent(DataSet:TDataSet);
11. Добавить в реализацию метода TMyActiveForm.Initialize оператор
ADOTable1.AfterScroll:=ScrollEvent;
12. Включить в файл реализации код метода ScrollEvent:
procedure TMyActiveForm.ScrollEvent(DataSet:TDataSet);
begin if FEvents<>nil then FEvents.OnScroll; end;
Откомпилировать, зарегистрировать и установить в палитру компонент
MyActiveForm. Разработать подходящее тестовое приложение для проверки
работоспособности компонента.
10. Технологии ADO и CORBA
В Delphi наряду с традиционными средствами доступа к данным BDE и
ODBC можно применять технологию ADO (ActiveX Data Objects),
основанную на возможностях COM (OLE DB). Технология ADO широко
используется, т.к. интерфейсы OLE DB есть в каждой ОС фирмы Microsoft. В
палитре компонентов Delphi имеется страница ADO.
Технология ADO обеспечивает
ADO-приложение
универсальный
доступ
к
источникам данных из приложений
ADO
БД. Для этого используется набор
интерфейсов на основе COM и
OLE DB
спецификации OLE DB.
ADO и OLE DB поддерживают
Хранилище данных
единый
способ
доступа
к
источникам данных разного типа.
Например,
БД
Файлы
Электронные
таблицы
приложение
может
применять одинаковые операции к
данным, хранящимся на сервере
SQL, в электронной таблице, файлах и т.д. Направленный источнику SQLзапрос будет выполнен в любом случае. Это обеспечивается ADO и OLE DB.
Объекты OLE DB являются объектами COM, выполняющими как
стандартные функции обработки данных, так и специальные функции
конкретных источников. Любой источник данных в ADO называется
хранилищем данных, с которым при помощи провайдера взаимодействует
приложение.
Минимальный
соединение,
набор
данных,
набор
компонентов
команду.
включает
Приложение
объект
обращается
не
непосредственно к источнику данных, а к объекту OLE DB, который умеет
представлять данные источника в виде таблицы БД или результата SQLзапроса.
Технология ADO
позволяет сделать набор объектов и интерфейсов
открытым и расширяемым. Требуемые объекты и поддерживающие их
провайдеры могут быть созданы для любого хранилища без внесения
изменений в исходную структуру. Появляется возможность работы с
нетрадиционными данными: графическими, геоинформационными и др. OLE
DB различает следующие типы объектов:
Перечислители (Enumerator) – выполняют поиск источников или
других перечислителей. Используются провайдерами ADO.
Источники данных (Data Source Object) – хранилище данных.
Сессия (Session) – совокупность объектов, обращающихся к одному
хранилищу данных.
Транзакция (Transaction) – механизм выполнения транзакции.
Команда (Command) – содержит текст команды.
Набор строк
(Row Set) – совокупность строк данных, результат
выполнения команды.
Объект ошибка (Error) – информация об исключительной ситуации.
Провайдеры ADO
Провайдеры выполняют с помощью ADO соединение приложения с
хранилищем данных. Для каждого типа источника существует свой
провайдер ADO. Провайдер знает местоположение источника и его
содержание, умеет обращаться к данным с запросами и получать результаты.
Список
провайдеров
TADOConnection.
При
указывается
инсталляции
при
соединении
ADO
в
компоненте
указываются
следующие
провайдеры:
Microsoft Jet OLE DB Provider – соединение с Access;
Microsoft OLE DB Provider for Oracle – соединение с Oracle;
Microsoft OLE DB Provider for SQL Server – соединение с MS SQL
Server;
………….
Файлы и интернет ресурсы, служба каталогов, http-файлы, ODBC и др.
Реализация ADO в Delphi
Компоненты ADO размещены на одноименной странице. Интерфейсы
описаны в файлах OleDB.pas и ADODB.pas библиотеки Vcl. Компоненты
ADO:
TADOConnection реализует возможности перечислителя, источника и
сессии.
TADOCommand содержит текстовые команды ADO.
TADOTable, TADOQuery, TADOStoredProc – наборы данных.
Способы использования компонентов незначительно отличаются от
применения стандартных компонентов доступа к данным.
Соединение с хранилищем данных
Для подключения к хранилищу можно использовать стандартный способ
ADO или стандартный способ Delphi. В первом случае используется
свойство ConnectionString компонента доступа для прямого обращения к
хранилищу.
Во
TADOConnection,
втором
применяется
обеспечивающий
специальный
управление
компонент
подключениями
и
использование данных несколькими компонентами одновременно.
Формат
‘Remote
ConnectionString:
Server=ServerName;
Provider=ProviderName’. Можно задать путь к удаленному провайдеру:
‘Remote
Provider=ProviderName’
и
параметры
провайдера:
‘User
Name=User_Name; Password=Password’. Каждый компонент самостоятельно
задает свойство ConnectionString и открывает собственное соединение.
Целесообразно использовать компонент TADOConnection, открывающий
одно соединение для всех компонентов доступа. Компоненты ссылаются на
TADOConnection в свойстве Connection. TADOConnection позволяет:
Обращаться к хранилищу через одно соединение;
Задавать провайдер соединения;
Выполнять команды ADO;
Управлять транзакциями;
Использовать обработчики событий.
Компонент TADOConnection
Для управления соединением используются свойства:
ConnectionString – задает источник данных и провайдер. Для настройки
можно использовать редактор.
Connected – используется для открытия и закрытия соединения. Можно
использовать присваивание и методы Open и Close.
Mode – режим, указывает доступные операции (Read, Write, …).
Событие OnConnectComplete позволяет после открытия соединения
выполнить собственный код (обработчик события).
Доступ к наборам данных и командам ADO обеспечивается свойствами:
DataSets[] – список наборов данных;
DataSetCount – число наборов данных;
CursorLocation – тип курсора (clUseClient – локальный курсор на
стороне клиента, clUseServer – курсор на стороне сервера);
Commands[] – команды, работающие с хранилищем через данное
соединение;
CommandCount – счетчик команд.
Пример.
procedure
TForm1.ADOConnectionConnectComplete(Connection;
EventStatus);
Var
begin
if EventStatus=esOk then
for i:=0 to ADOConnection.CommandCount-1 do
try
if ADOConnection.Commands[I].CommandText<>’’ then
ADOConnection.Commands[I].Execute;
except
Error;
On E: Exception do …
end;
end;
Метод
Execute
можно
переопределить
и
задавать
команды
в
параметрической форме. После выполнения команды вызывается метод
обработчик события OnExecuteComplete.
Для
управления
CommitTrans,
транзакциями
и
RollbackTrans
используются
события
методы
BeginTrans,
OnBeginTransComplete,
OnCommitTransComplete. Уровень изоляции транзакции устанавливается
свойством IsolationLevel.
Наборы данных ADO
Наборы
данных
TADOQuery,
ADO
TADOTable,
представляются
классами
TADODataSet,
Базовый
TADOStoredProc.
класс
–
TCustomADODataSet.
Класс TCustomADODataSet содержит механизм доступа к хранилищу
через ADO. Перед обновлением набора данных необходимо установить тип
блокировки для редактирования записей. Для этого используется свойство
LockType, принимающее значения: ltUnspecified – блокировка задается
источником данных;
ltReadOnly – только чтение; ltPessimistic – запись
блокируется на все время редактирования; ltOptimistic – запись блокируется
только
на
время
сохранения
изменений
в
хранилище
данных;
ltBatchOptimistic – для редактирования используется метод UpdateBatch.
Текущее состояние набора данных указывается свойством RecordsetState.
Свойство RecordSet – набор записей ADO.
После обновления набора данных вызывается обработчик события
OnFetchComplete. Для асинхронного режима используется обработчик
OnFetchProgress.
Курсор набора данных
Размещение курсора задается свойством CursorLocation. Серверный курсор
используется
при
нецелесообразно
обеспечивает
работе
с
пересылать
передачу
большими
клиенту
набора
наборами
целиком.
данных
данных,
которые
Клиентский
клиенту,
курсор
целесообразен
для
небольших наборов данных.
Для клиентского курсора устанавливается свойство MarshalOptions,
управляющее обменом между клиентом и сервером. Если соединение
быстрое, можно использовать moMarshalAll, разрешающее возврат серверу
всех записей набора данных. В противном случае для ускорения работы
следует
использовать
moMarshalModifiedOnly
–
возврат
только
модифицированных записей.
Тип курсора задается свойством CursorType, принимающим следующие
значения:
CtUnspecified – тип не задан;
CtOpenForwardOnly – однонаправленный курсор, используемый для
быстрого прохода по данным;
CtKeySet – двунаправленный локальный курсор, не обеспечивающий
просмотр добавленных и удаленных другими пользователями записей;
CtDynamic – двунаправленный курсор, отображающий все изменения;
CtStatic
–
двунаправленный
курсор,
полностью
игнорирующий
изменения других пользователей.
До и после перемещения курсора в наборе данных можно использовать
обработчики событий OnWillMove и OnMoveComplete.
Локальный буфер
Переданные клиенту записи размещаются в локальном буфере, размер
которого определяется свойством CacheSize. Другие свойства буфера:
RecordSize – размер записи;
BlockReadSize – число записей в блоке;
MaxRecords – максимальное число записей набора данных;
RecordCount – текущее число записей;
OnEndOfRecordSet – обработчик конца набора данных.
Другие свойства набора данных:
RecordStatus – состояние текущей записи;
Filter, Filtered, OnFilterRecord, FilterGroup – фильтрация;
Sort – сортировка;
Command – команда;
CommandType – тип команды.
Компонент TADODataSet
Предназначен для представления набора данных из хранилища данных
ADO. С помощью инспектора объектов можно устанавливать свойства
CommandText, CommandType команд ADO. В запросах SQL допустимы
только операторы DML. В приложениях используется как обычный
компонент доступа к данным.
Компонент TADOTable
Подобен
стандартному
табличному
компоненту.
Обеспечивает
использование в приложениях таблиц БД, подключенных с помощью
провайдеров OLE DB. Команда ADO компонента не редактируется. Свойство
TableDirect задает тип доступа к таблице: прямой или опосредованный SQLзапросом.
Компонент TADOQuery
Обеспечивает
применение
SQL-запросов.
Подобен
стандартному
одноименному компоненту. Свойства: SQL (текст запроса), Parameters,
Active, RowsAffected (число обработанных записей). Если набор данных не
требуется возвращать после обработки, то можно использовать метод
ExecSQL.
Команды ADO
Компонент TADOCommand предназначен для выполнения команд, не
возвращающих
наборы
данных.
Текстовое
представление
команды
содержится в свойстве CommandText, на объект-команду можно сослаться с
помощью свойства CommandObject. Выполнение команды инициируется
методом Execute, для прерывания выполнения используется метод Cancel.
Текущее состояние команды определяется свойством State.
Пример приложения ADO, отображающего таблицы БД и сохраняющего
изменения.
Form1
DBGrid1
DBSource1
ADOTable1
Button1
DBGrid2
DBSource2
ADOTable2
ADOConnection1
procedure TForm1.Button1Click();
begin
ADOConnection1.Close;
ADOConnection1.DefaultDataBase:=’…’;
ADOConnection1.Open;
ADOTable1.UpdateBatch();
ADOTable2.UpdateBatch();
end;
procedure TForm1.ADOConnection1AfterConnect();
begin
for I:=0 to ADOConnection1.DataSetCount-1 do
ADOConnection1.DataSets[I].Open;
end;
procedure TForm1.ADOConnection1BeforeDisconnect();
begin
for I:=0 to ADOConnection1.DataSetCount-1 do
ADOConnection1.DataSets[I].Close;
end;
На
форме
приложения
размещаются
компоненты
ADOConnection,
ADOTable, DBSource, DBGrid, Button. Компоненты надлежащим образом
настраиваются и связываются друг с другом. Кнопка Button1 устанавливает
соединение с указанной базой данных и запускает обновление таблиц.
Обработчики событий OnAfterConnect, OnBeforeDisconnect соответственно
открывают и закрывают задействованные наборы данных.
Технология CORBA
Технология CORBA (Common Object Request Broker Architecture – общая
архитектура брокера объектных запросов) – специальная технология,
позволяющая создавать распределенные приложения, работающие на
нескольких компьютерах и способные выполняться под управлением разных
операционных систем, а не только Windows, как компоненты COM.
Технология
CORBA
организует
совместную
работу
объектов,
предоставляющих другим программам свои интерфейсы.
С помощью технологии создаются серверные объекты CORBA, которые
могут быть запущены на любых компьютерах сети при условии, что в ней
установлен брокер объектных запросов ORB (Object Request Broker). Это
специальная программа, которая отслеживает и синхронизирует работу всех
объектов CORBA, организует процесс обмена сообщениями между ними,
оптимально распределяет загрузку и организует связь клиентов с серверными
объектами. Брокер – коллекция библиотек функций CORBA и набор сетевых
ресурсов, позволяющих организовать распределенную работу программ,
написанных на разных языках программирования. В сети может быть
запущено множество объектов CORBA. Брокер решает, где им лучше
выполняться и какие запросы обслуживать. Брокер анализирует запросы
клиентов,
распределяет
пользователям.
их
по
объектам
и
возвращает
результаты
Delphi позволяет создавать объекты CORBA только для Windows. В других
системах программирования создаются объекты для других платформ.
Брокерские службы разных платформ могут взаимодействовать между собой.
Построение серверного CORBA-модуля в Delphi
Исходные тексты серверного и клиентского приложений CORBA в Delphi
автоматически генерируются из описания интерфейса, заданного на
платформенно-независимом языке IDL. Рассмотрим пример построения
простого сервера, вычисляющего среднее двух чисел.
Описание интерфейса серверного объекта на языке IDL сохраняется в
файле server.idl. Описание интерфейса:
Module server
{interface IMyTest;
interface IMyTest
{long Avr (in long X, in long Y);};
interface MyTestFactory
{IMyTest CreateInstance(in string InstanceName);};
};
Интерфейс IMyTest доступен другим CORBA-объектам, интерфейс
MyTestFactory нужен для автоматического создания объекта при обращении
к интерфейсу IMyTest.
IDL-компилятор вызывается командой File/New/Other/CORBA/CORBA
Server Application. Генерируются модули:
Server_i – модуль реализации интерфейса;
Server_s – модуль реализации шаблона;
Server_c – модуль реализации класса;
Server_impl – функциональность интерфейса.
Задается функциональность:
function TIMyTest.Avr (const X:Integer; const Y:Integer):Integer;
begin Result:=(X+Y)/2; end;
Автоматически
создается
процедура
InitCorba,
выполняющая
инициализацию и связь с CORBA-системой, построение серверного
интерфейса. Процедура вызывается при создании формы сервера.
Текст модуля:
unit Unit1;
interface
uses …Server_c, Server_i, Server_s, Server_impl;
type
TForm1=class(TForm)
procedure FormCreate(…);
protected
MTest:IMyTest;
procedure InitCorba;
public
end;
Var Form1:TForm1;
implementation
procedure TForm1.InitCorba;
begin
CorbaInitialize;
MTest:=TIMyTestSkeleton.Create(‘CORBAMyTest’, TIMyTest.Create):
BOA.ObjIsReady(Mtest as _Object);
end;
procedure TForm1.FormCreate(…);
begin InitCorba; end;
end.
Приложение можно откомпилировать и запустить.
Построение приложения-клиента CORBA
Построение
начинается
File/New/Other/CORBA/CORBA
добавляется
idl-файл
с
с
выполнения
Client
описанием
клиентский CORBA-модуль. В
Application.
интерфейса,
команды
В
приложение
затем
генерируется
класс формы добавляется переменная
vIMyTest:IMyTest, служащая для связи с сервером. Связь устанавливается
методом bind класса TIMyTestHelper.
Текст модуля.
unit Unit2;
interface
uses … Server_c, Server_i, StdCtrls;
type
TForm1=class(TForm)
Button1:TButton;
procedure Button1Click();
procedure FormCreate();
protected
vIMyTest:IMyTest;
end;
var Form1:TForm1;
implementation
procedure TForm1.FormCreate();
begin vIMyTest:=TIMyTestHelper.bind; end;
procedure TForm1.Button1Click0;
var n:integer;
begin n:=vIMyTest.Avr(3,7);
ShowMessage(IntToStr(n));
end; end.
Запуск и использование CORBA-объектов
До запуска сервера должен быть запущен «интеллектуальный агент» Smart
Agent - специальный ресурс брокера, обслуживающий объекты с нужными
интерфейсами.
Агент
запускается
командой
Пуск/Программы/VisiBroker/VisiBroker Smart Agent. С помощью проводника
запускается сервер CORBA (Project1.exe) и две или более копий клиента
Project2.exe. Далее происходит выполнение клиентских программ с вводом
данных и получением результатов. Обычно сервер выполняется на
удаленном компьютере.
*Практические задания к теме
Технология ADO
В Delphi наряду с традиционными средствами доступа к данным BDE и
ODBC широко используется технология ADO (ActiveX Data Objects),
обеспечивающая универсальный доступ к источникам данных разных типов
из приложений БД. ADO основана на технологиях COM и OLE DB.
Целью практического занятия является ознакомление с приѐмами работы
с компонентами доступа к данным ADO. Источником данных будет база
данных MS Access 2000, состоящая из двух таблиц: Отделы (Department) и
Служащие (Employees).
Схема БД:
Departments (IdD (ключевое, счетчик), Appellation (строка (50))),
Employees (IdE (ключевое, счетчик), Department (числовой), Family
(строка (50)), Post (строка (50))).
Таблицы связаны по полям IdD и
Department (таблица Departments –
главная, Employees – подчиненная). Файл базы данных (database.mdb)
сохранить в личной папке.
Подготовка проекта. Начните новый проект.
Создайте модуль данных (File > New > Data
Module) с именем DataModule1. Поместите на форму модуля данных
компонент TADOConnection (страница ADO палитры компонентов) и
свяжите его с базой данных. Связь устанавливается обработчиком OnCreate
модуля данных.
procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
DataBasePath := 'путь к базе данных';
ADOConnection1.ConnectionString :=
'Provider=Microsoft.Jet.OLEDB.4.0;'+
'Data Source='+DataBasePath+'database.mdb;'+
'Persist Security Info=False';
ADOConnection1.LoginPromt := False; // чтобы не спрашивал
пароль
ADOConnection1.Open;
// открываем соединение
end;
Этого достаточно чтобы
программа
нашла
базу
данных, но для работы в
режиме
дизайна
воспользоваться
создания
этого
можно
мастером
соединения.
нужно
кликнуть
на
два
Для
раза
компоненте
ADOConnection
и
в
появившемся окне нажать на
кнопку Build.
Появится
создания
первой
окно
мастера
соединения,
вкладке
необходимо
в
которого
указать
провайдер базы данных MS Access: Microsoft Jet 4.0 OLE DB. А на второй –
путь к базе данных. Имя пользователя и пароль оставить без изменений: имя
пользователя –
Admin,
пароль –
«Пустой пароль». На этом работу с
мастером можно закончить и перейти к работе с главной формой
приложения.
Добавьте имя модуля данных в раздел
необходимо
uses
главной формы. Это операцию
проделать со всеми формами, в которых используется
соединение с базой данных. На форму помещаются следующие компоненты:
DsDepartments:
TDataSource;
DsEmployees: TDataSource;
DstDepartments:
TADODataSet;
DstEmployees: TADODataSet;
DbgDepartments:
TDBGrid;
DbgEmployees: TDBGrid;
Настройка компонентов:
DstDepartments.Connection := DataModule1.ADOConnection1;
DstEmployees.Connection := DataModule1.ADOConnection1;
DstDepartments.CommandString := ‘SELECT * FROM Departments’;
DstEmployees.CommandString := ‘SELECT * FROM Employees’;
DsDepartments.DataSet := DstDepartments;
DsEmployees.DataSet := DstEmployees;
DbgDepartments.DataSource := DsDepartments;
DbgEmployees.DataSource := DsEmployees;
После этого двойным щелчком на компонентах типа TADODataSet вызвать
редактор полей и добавить все поля для DstDepartments и DstEmployees.
Затем двойным щелчком на компонентах TDBGrid вызвать редактор
столбцов и добавить все столбцы. После проделанных действий в таблицах
должны появиться заголовки столбцов, соответствующие названиям полей
таблиц базы данных.
По логике базы данных таблицы отделов и служащих являются
связанными. Для того чтобы в таблице служащих показывались только
сотрудники текущего отдела, необходимо соответствующим образом
настроить компоненты: DstEmployees.DataSource := DsDepartments и в
MasterField компонента DstEmployees указать связку Department -> IdD.
Компоненты формы настроены для отображения информации из базы
данных. Теперь можно приступить к реализации действий по наполнению и
редактированию данных таблиц. Для этого будем использовать компоненты
типа TADOCommand.
Использование TADOCommand.
Компоненты
типа
TADOCommand
используются
для
выполнения
операций, не возвращающих наборы данных ( операции INSERT, UPDATE,
DELETE языка SQL). В работе понадобится удалять и добавлять записи в
таблицы базы данных.
Поместите на форму 4 компонента TADOCommand: CmdInsDepartment,
CmdInsEmployee, CmdDelDepartment, CmdDelEmployee. Установите свойство
Connection каждого равным DataModule1.ADOConnection1. В свойство
CommandText запишите инструкции SQL, реализующие соответствующие
действия. Например, для добавления служащего используется инструкция:
INSERT INTO Employees (Department, Family, Post) VALUES (:Department,
:Family, :Post), в которой имена с префиксом «:» являются параметрами. При
описании параметров нужно указать их тип (для строк WideString).
Пример запуска команды.
procedure TForm1.Button3Click(Sender: TObject);
{Добавление служащего}
var
str : string;
begin
str := 'Фамилия служащего';
if not InputQuery('Добавление ','Введите фамилию
служащего',str) then Exit;
if str='' then Exit;
{В последующих строках инициализируются параметры.
DstDepartmentsIdD.Value – идентификатор выделенного отдела}
CmdInsEmployee.Parameters.ParamByName('Department').Value :=
DstDepartmentsIdD.Value;
CmdInsEmployee.Parameters.ParamByName('Family').Value :=
str;
… ввод должности …
{Выполнение команды}
CmdInsObject.Execute;
{Перезапрос обновлѐнных данных}
DstObjects.Requery();
end;
procedure TForm1.Button4Click(Sender: TObject);
{Удаление служащего}
begin
{Инициализация параметров}
CmdDelEmployee.Parameters[0].Value := DstEmployeeIdE.Value;
// идентификатор
//
выделенного объекта
{Выполнение команды}
CmdDelEmployee.Execute;
{Перезапрос обновлѐнных данных}
DstEmployees.Requery();
end;
Реализуйте команды добавления и удаления для всех таблиц.
Сортировка.
Для сортировки набора данных TADODataSet используется свойство Sort,
которому можно присвоить строку, содержащую имя столбца и направление
сортировки.
Пример реализации сортировки:
procedure TForm1.DbgEmployeesTitleClick(Column: TColumn);
begin
if DstEmployees.Sort=Column.FieldName + ' ASC' then
DstEmployees.Sort := Column.FieldName + ' DESC'
else
DstEmployees.Sort := Column.FieldName + ' ASC';
end;
Реализуйте сортировку таблиц.
Фильтрация.
Для фильтрации набора данных используются свойство Filtered и
процедура OnFilterRecord (DataSet: TDataSet;
var Accept: Boolean). При
изменении значения свойства Filtered с false на true происходит фильтрация
набора данных в соответствии с условиями, обозначенными в процедуре
фильтрации. Назначением процедуры фильтрации является вычисление
выходного параметра Accept, переданного по значению. Если Accept истина,
то строка будет присутствовать в отфильтрованном наборе данных, если нет
– не будет.
Реализуйте фильтрацию таблиц.
Метод Locate.
В классе TADODataSet определѐн метод Locate, который позволяет
перейти к искомой записи в наборе данных. Этот метод удобно использовать,
например, при восстановлении позиции курсора после сортировки. Для этого
необходимо
перед
сортировкой
сохранить
идентификатор
записи
в
локальной переменной, и после выполнения сортировки выполнить Locate.
Пример усовершенствованной процедуры сортировки:
procedure TForm1.DbgEmployeesTitleClick(Column: TColumn);
var
StoredID : integer;
Begin
StoredID := DstEmployees.ColumnByName('IdE').Value;
if DstEmployees.Sort=Column.FieldName + ' ASC' then
DstEmployees.Sort := Column.FieldName + ' DESC'
else
DstEmployees.Sort := Column.FieldName + ' ASC';
DstEmployees.Locate('IdE',StoredID,[]);
end;
Реализуйте усовершенствованную сортировку таблиц.
Технология CORBA
Технология CORBA (Common Object Request Broker Architecture – общая
архитектура
брокера
объектных
запросов)
–
позволяет
создавать
распределенные приложения, работающие на нескольких компьютерах и
способные выполняться под управлением разных операционных систем.
С
помощью
технологии
создаются
серверные
объекты
CORBA,
управляемые брокером объектных запросов ORB (Object Request Broker).
Брокер отслеживает и синхронизирует работу объектов CORBA, организует
процесс обмена сообщениями между ними, распределяет загрузку и
организует связь клиентов с серверными объектами.
Delphi позволяет создавать объекты CORBA только для Windows. В
других
системах
программирования
создаются
объекты
для
других
платформ. Брокерские службы разных платформ могут взаимодействовать
между собой.
Исходные тексты серверного и клиентского приложений CORBA в
Delphi автоматически генерируются из описания интерфейса, задаваемого
на платформенно-независимом языке IDL.
Задание. Разработать приложение CORBA для выполнения простых
арифметических вычислений.
Последовательность действий.
Сервер CORBA
1. В блокноте или другом текстовом редакторе описываются интерфейсы
серверного объекта и сохраняются в файле server.idl.
2. Запускается Delphi, выполняется File\New\Other\Corba\ CORBA Server
Application. Кнопкой Add
добавляем в
приложение файл server.idl.
Выполняем команду Generate и получаем файлы server_s.pas, server_c.pas,
server_i.pas, server_impl.pas.
3. Открываем файл server_impl.pas и реализуем функцию TIMyTest.Avr (
const X : Integer; const Y : Integer): Integer).
function TIMyTest.Avr(const X:Integer; const Y:Integer);
begin
if X.
Объявление может размещаться внутри документа или в DTD. Элементы
могут быть вложены друг в друга.
Примеры объявлений в DTD.
Элемент employee содержит элементы name и post, символы #PCDATA
указывают на анализируемые символьные данные (соответствующие
элементы не должны содержать символ начала тега «<»).
При описании элементов используются следующие метасинтаксические
конструкции:
() – альтернативные элементы или элементы списка;
| - разделение альтернативных элементов;
? – элемент может использоваться ноль или один раз;
, - разделение элементов в списке;
* - элемент может использоваться ноль и более раз;
+ - элемент должен использоваться не менее одного раза.
Пример. - post используется не
менее одного раза.
Атрибуты служат для уточнения характеристик элементов, их вида и
размещения. Атрибуты можно указывать в объявлении элемента или в списке
атрибутов (в DTD используется тег ). Объявление атрибута в
DTD задается так:
.
Тип (назначение) атрибута:
CDATA – символьные данные;
Enumerated – перечисление;
ID – идентификационный номер;
IDREF – ссылка на элемент ID;
IDREFS – ссылки на несколько ID;
ENTITY – имя внешнего информационного объекта;
ENTITIES – ссылка на несколько объектов;
NMTOKEN – имя XML;
NOTATION – обозначение имени в DTD;
NMTOKENS – множество имен.
Пример.
- тег в документе.
Объявление в DTD:
Информационные объекты
Обычно документ состоит из двух частей: пролога и данных. Пролог
содержит объявление XML и описания типа документа DTD. Данные –
размеченный текст. В общем случае документ может содержать данные и
объявления из различных источников: баз данных, сценариев и др., т.е.
документ состоит из пролога и информационных объектов (entity).
В
качестве информационного объекта может выступать файл, записи базы
данных и т.д.
Различают внутренние и внешние информационные объекты. Описание
внутреннего объекта содержится в самом документе. Объявление внешнего
объекта ссылается на контейнер, хранящий его содержание.
Пример.
- объявление внутреннего информационного
объекта.
Ссылка &txt – обращение к объекту внутри документа – заменяется
строкой “текст”.
- объявление внешнего
объекта (PUBLIC, SYSTEM – тип доступа к объекту).
Предопределенные ссылки <, >, ', "e;, & ссылаются
соответственно на символы <, >, „, “, &.
Определение типа документа
Наличие
DTD
документа,
обеспечивает
удобное
задание
возможность
структуры
проверки
корректности
документа,
возможность
использования информационных объектов. DTD включает: тип документа,
элементы документа, атрибуты, информационные объекты, комментарии.
DTD бывают внутренние (находится внутри документа) и внешние (вне
документа). Внешнее DTD может быть системным (SYSTEM) или общим
(PUBLIC).
Системное
DTD
может
использоваться
без
уточняющей
информации, общее требует указания идентификатора документа. Основное
назначение DTD – определение структуры документа.
Пример. Определение документа «книга».
]>
…
…
…
…
…
…
Здесь первая строка – объявление xml-документа, строка “” - конец DTD.
Броузер контролирует правильность документа и сообщает об ошибках. В
случае внешнего DTD используется файл с расширением .dtd, первая строка
которого
–
“”.
В
документ
включается
строка
.
XML-обмен данными
XML позволяет определять структуру документа и типы хранимых в нем
данных, причем описание типа отделено от собственно документа. Это
позволяет приложениям легко обмениваться данными, даже если их
структура отличается в разных приложениях. Для доступа к базам данных
или таблицам Excel можно использовать страницы ASP или сценарии Jscript,
которые будут извлекать данные и помещать их в документ XML.
Документы XML могут использоваться как на стороне сервера, так и на
стороне клиента.
Программа XML Mapper
Преобразователь
XML
Mapper
задает
соответствие
между
XML-
документами и пакетами данных клиентских наборов данных, которые
содержат метаданные XML-документов. Отображение (трансформация)
-
соответствие между элементами XML-документа и полями в пакете данных.
Можно задать отображения следующих видов:
Существующей XML-схемы или документа на клиентский набор данных;
Существующего пакета данных на новую XML-схему;
Существующей XML-схемы на существующий пакет данных.
Отображение можно сохранить в трансформационном файле (файле
соответствия) с расширением .xtr. Обычно трансформационные файлы
создаются
в
паре:
для
прямого
и
обратного
преобразования.
Трансформационные файлы используются компонентами TXMLTransform,
TXMLTransformProvider, TXMLTransformClient для преобразования данных в
приложении.
Окно XML Mapper отображает сам документ, 3 варианта его схем,
соответствие между документом и пакетом данных, метаданные пакета
данных.
14. Разработка веб-приложений
CGI-сценарии
В настоящее время наиболее популярны web-серверы Apache, Internet
Information Server (IIS), Personal Web Server (PWS). Сервер Apache
оптимизирован под операционную систему Unix, на его долю приходится
около 60% всех установленных серверов. Сервер IIS работает под ОС
Windows NT/2000/XP, Personal Web Server – под Windows 98. Все
перечисленные серверы могут работать с CGI-сценариями.
В процессе разработки сценария решаются две задачи: построение webинтерфейса и разработка приложения. Различают два типа приложений:
стандартное консольное, с передачей данных через переменные окружения, и
WinCGI, использующее INI-файл.
CGI-сценарий запускается из формы HTML-страницы кнопкой SUBMIT
или щелчком на гиперссылке. В первом случае адрес сценария указывается
тегом
.
Компоненты для формирования HTML-ответа
Страница Internet палитры компонентов содержит большое число
компонентов формирования HTML-ответов.
Компонент TPageProducer
Обеспечивает генерацию HTML-документа на основе шаблона. Свойства
компонента:
HTMLDoc – код шаблона документа;
HTMLFile – файл с шаблоном.
Метод Content обрабатывает шаблон и выдает HTML-страницу.
Шаблон – обычный документ, содержащий специальные теги: <#name
param1=value1
param2=value2
…>.
обработчиком события OnHTMLTag:
Теги
<#
…>
обрабатываются
TTag=(tgCustom, tgLink, tgImage, tgImageMap, tgObject, tgEmbed);
THTMLTagEvent=proc (Sender; Tag; TagString; TagParams; ReplaceText) of
Object.
Здесь Tag – тип тега, TagString – имя тега, TagParams – параметры,
ReplaceText – возвращаемая строка, замещающая тег.
Пример.
procedure TWebModule1. …Action(…);
begin
…
Response.Content:=PageProducer1.Content;
end;
procedure TWebModule1.PageProducer1HTMLTag(Sender; Tag; TagString;
…);
begin
if TagString=‟…‟ then
ReplaceText:= …;
…
end;
Компоненты для работы с базами данных
Используются компоненты: TDataSetPageProducer, TDataSetTableProducer,
TQueryTableProducer.
TDataSetPageProducer -
аналог TPageProducer. Отличие – свойство
DataSet. При обработке шаблона теги, имена которых совпадают с полями
набора данных, заменяются значениями полей из текущей записи.
TDataSetTableProducer - генератор табличных объектов для Web.
Свойства:
DataSet – набор данных;
Dispatcher – компонент-диспетчер, обрабатывающий HTML-запрос.
Обычно устанавливается автоматически на WebModule, содержащий
DataSetTableProducer;
Caption – заголовок HTML-документа;
Header – текст перед таблицей;
Footer – текст после таблицы;
Columns – поля таблицы;
Пример. Вывод таблицы БД в виде HTML-таблицы.
1. Начать новое Web-приложение.
2. Поместить
на
форму
WebModule
компоненты
ADOTable
и
DataSetTableProducer.
3. Подключить ADOTable к таблице БД.
4. Связать DataSetTableProducer1 с ADOTable1.
5. Задать свойства DataSetTableProducer1.
6. Задать новое действие:
procedure … Action( …);
begin Response.Content:=DataSetTableProducer1.Content; end;
7. В обработчиках OnCreate и OnDestroy компонента WebModule
соответственно открыть и закрыть ADOTable1.
Имеются события, позволяющие вызывать соответствующие обработчики
до генерации HTML-документа, до формирования каждой ячейки, для
форматирования документа.
Разработка web-приложений ASP
Приложение ASP – сервер автоматизации, взаимодействующий с webсервером.
ASP
похоже
на
приложения
CGI,
ISAPI.
Отличие
–
сформированный ASP ответ является фрагментом HTML-кода, который
добавляется к некоторому исходному документу. При этом в одном HTMLдокументе возможно обращение к нескольким разным серверам ASP. Ответы
приложений вставляются в страницу и, таким образом, формируется единый
документ.
Сервер ASP взаимодействует с web-сервером через методы интерфейсов
IRequest и IResponse. Интерфейс IRequest позволяет получить параметры из
запроса
клиента,
интерфейс
IResponse
позволяет
сформировать
результирующий HTML-документ.
ASP-сервер может быть внешним (exe-файл) или внутренним (DLL), т.е.
может работать как CGI-, либо ISAPI-приложение.
Пример внутреннего сервера ASP.
1. Создается библиотека ActiveX.
2. К проекту добавляется объект Active Server Object. Задается имя
класса (FirstASP), способ создания объекта (Instancing), тип работы с
потоками (параметр Threading Model, значение Apartment). Все
перечисленные параметры унаследованы от COM-объектов.
3. Устанавливаются параметры web-приложений: Active Server Type,
Generate test script и др. Для web-сервера IIS (версия 3 и 4)
устанавливается ASP=Pageleveleventsmethods, для IIS (5) – Object
Context.
4. Создается файл реализации интерфейсов, библиотека типов и файл
__.asp – шаблон HTML-документа с VB-сценарием вызова сервера
ASP.
5. Создается метод формирования ответа. Для этого с помощью
редактора библиотеки типов в интерфейс IFirstASP добавляется
метод Content. Производится обновление библиотеки (Refresh).
6. Задается реализация метода. Используется свойство Response класса
TFirstASP, являющееся указателем на интерфейс IResponse.
procedure TFirstASP.Content;
begin
if Assigned(Response) then Response.write(„…‟);
end;
7. Проект
компилируется,
результат
помещается
в
каталог,
предназначенный для расширений сервера (Scripts для PWS).
Производится регистрация (Run/Register ActiveX Server).
8. Редактируется
тестовый
файл
FirstASP.asp.
Окончательный
фрагмент HTML-документа:
<% Set DelphiASPObj=Server.CreateObject(“Project1.FirstASP”)
DelphiASPObj.Content
%>
9. Тест записывается в подходящий каталог и выполняется броузером.
Доступ к параметрам
Используется интерфейс IRequest (свойство Request).
Свойство IRequest включает поля:
ServerVariables – коллекция переменных окружения;
QueryString – коллекция значений элементов управления HTMLформы (метод GET);
Form – коллекция значений элементов управления HTML-формы
(метод POST).
Для работы с коллекциями используется интерфейс IRequestDictionary.
Свойства IRequestDictionary:
property Count: SYSIN read Get_Count – количество элементов;
property Key[VarKey:OleVariant]:OleVariant read Get_Key – имена
элементов;
property Item[VarItem:OleVariant]:OleVariant read Get_Item; default –
значения элементов.
При обращении к Item можно использовать как номер элемента, так и его
имя.
S:=
Request.ServerVariables.Item[„REQUEST_METHOD‟]
–
переменной окружения;
S:=Request.Form.Item[„Name‟] – значение элемента управления.
значение
Пример.
Требуется
изменить
метод
Content
предыдущего
примера.
ASP-
приложение возвращает информацию о методе вызова, именах и значениях
управляющих элементов.
procedure TFirstASP.Content;
Var
begin
if Assigned(Request) then
begin
RM:=Request.ServerVariables.Item[„REQUEST_METHOD‟];
Ret:=‟метод‟+RM+‟
‟; if RM=‟GET‟ then begin Count:=Request.QueryString.Count; Ret:=Ret+‟количество элементов‟+IntToStr(Count)+‟
‟; for i:=1 to Count do begin S1:= Request.QueryString.Key[I]; S2:= Request.QueryString.Item[I]; Ret:=Ret+S1+‟=‟+S2+‟
‟; end; end; if RM=‟POST‟ then begin … end; if Assigned(Response) then Response.Write(Ret); end; end; Далее следует отредактировать asp-шаблон и создать форму для тестирования сервера. … … Работа с БД в ASP ASP-сервер в отличие от ISAPI и CGI не использует компонент TWebModule, что затрудняет доступ к данным. Будем использовать для доступа компонент модуль данных. Общая схема создания ASP-сервера аналогична рассмотренным выше способам построения серверных приложений, отличие – использование модуля данных. Пример. Работа с таблицей БД. Повторяются шаги по построению простого сервера, добавляется модуль данных, переписывается метод Content. 1. Инициализация модуля данных dm.pas: Модуль данных подключается к модулю реализации. В описании класса COM-объекта объявляется поле типа TDataModule1: TFirstASP=class (TASPMTSObject) private FDM: TDataModule1; protected procedure Content: safecall; Задается код инициализации и уничтожения экземпляра модуля данных. Используются методы AfterConstruction и BeforeDestruction. Методы объявляются в описании класса в разделе public с директивой override: procedure AfterConstruction; override; procedure BeforeDestruction; override; Код методов: procedure TFirstASP.AfterConstruction; begin inherited; FDM:=TDataModule1.Create(nil); end; procedure TFirstASP.BeforeDestruction; begin if Assigned(FDM) then FDM.Free; inherited; end; 2. Подключение БД. Компоненты TADOConnection и TADOQuery помещаются в модуль данных. Настраиваются свойства: ADOConnection1.ConnectionString настраивается на требуемую таблицу. ADOQuery1.Connection:=ADOConnection1; ADOQuery1.SQL:=‟select * from таблица where поле like :p1‟. 3. Формирование ответа. Определить метод запроса. Определить значение для параметра p1. Установить значение p1 и выполнить SQL-запрос. Сформировать ответ в виде HTML-кода. Передать ответ web-серверу. Код метода Content: procedure TFirstASP.Content; Var RM,Ret,Name: String; Parameters: IRequestDictionary; Count, Fcount, i, j: Integer; begin if Assigned(Request) then begin RM:= Request.ServerVariables.Item[„REQUEST_METHOD‟]; if RM=‟GET‟ then Parameters:=Request.QueryString; … POST … Name:=Parameters.Item[„EDIT‟]; FDM.ADOQuery1.Close; FDM.ADOQuery1.Parameters.ParamByName(„p1‟).Value:=‟%‟+Name+‟%‟; FDM.ADOQuery1.Open; Count:=FDM.ADOQuery1.RecordCount; FCount:=FDM.ADOQuery1.Fields.Count; if Count>0 then begin FDM.ADOQuery1.First; Ret:=‟‟‟;
Ret:=Ret+‟
‟; if RM=‟GET‟ then begin Count:=Request.QueryString.Count; Ret:=Ret+‟количество элементов‟+IntToStr(Count)+‟
‟; for i:=1 to Count do begin S1:= Request.QueryString.Key[I]; S2:= Request.QueryString.Item[I]; Ret:=Ret+S1+‟=‟+S2+‟
‟; end; end; if RM=‟POST‟ then begin … end; if Assigned(Response) then Response.Write(Ret); end; end; Далее следует отредактировать asp-шаблон и создать форму для тестирования сервера. … … Работа с БД в ASP ASP-сервер в отличие от ISAPI и CGI не использует компонент TWebModule, что затрудняет доступ к данным. Будем использовать для доступа компонент модуль данных. Общая схема создания ASP-сервера аналогична рассмотренным выше способам построения серверных приложений, отличие – использование модуля данных. Пример. Работа с таблицей БД. Повторяются шаги по построению простого сервера, добавляется модуль данных, переписывается метод Content. 1. Инициализация модуля данных dm.pas: Модуль данных подключается к модулю реализации. В описании класса COM-объекта объявляется поле типа TDataModule1: TFirstASP=class (TASPMTSObject) private FDM: TDataModule1; protected procedure Content: safecall; Задается код инициализации и уничтожения экземпляра модуля данных. Используются методы AfterConstruction и BeforeDestruction. Методы объявляются в описании класса в разделе public с директивой override: procedure AfterConstruction; override; procedure BeforeDestruction; override; Код методов: procedure TFirstASP.AfterConstruction; begin inherited; FDM:=TDataModule1.Create(nil); end; procedure TFirstASP.BeforeDestruction; begin if Assigned(FDM) then FDM.Free; inherited; end; 2. Подключение БД. Компоненты TADOConnection и TADOQuery помещаются в модуль данных. Настраиваются свойства: ADOConnection1.ConnectionString настраивается на требуемую таблицу. ADOQuery1.Connection:=ADOConnection1; ADOQuery1.SQL:=‟select * from таблица where поле like :p1‟. 3. Формирование ответа. Определить метод запроса. Определить значение для параметра p1. Установить значение p1 и выполнить SQL-запрос. Сформировать ответ в виде HTML-кода. Передать ответ web-серверу. Код метода Content: procedure TFirstASP.Content; Var RM,Ret,Name: String; Parameters: IRequestDictionary; Count, Fcount, i, j: Integer; begin if Assigned(Request) then begin RM:= Request.ServerVariables.Item[„REQUEST_METHOD‟]; if RM=‟GET‟ then Parameters:=Request.QueryString; … POST … Name:=Parameters.Item[„EDIT‟]; FDM.ADOQuery1.Close; FDM.ADOQuery1.Parameters.ParamByName(„p1‟).Value:=‟%‟+Name+‟%‟; FDM.ADOQuery1.Open; Count:=FDM.ADOQuery1.RecordCount; FCount:=FDM.ADOQuery1.Fields.Count; if Count>0 then begin FDM.ADOQuery1.First; Ret:=‟‟
‟; Ret:=Ret+FDM.ADOQuery1.Fields[j].FieldName; Ret:=Ret+‟ | ‟; end; Ret:=Ret+‟
 ‟; Ret:=Ret+FDM.ADOQuery1.Fields[j].AsString; Ret:=Ret+‟ | ‟; end; Ret:=Ret+‟