Книга
Книга
Валерий Фаронов
DELPHI 2005
РАЗРАБОТКА ПРИЛОЖЕНИЙ ДЛЯ БАЗ ДАННЫХ И ИНТЕРНЕТА
必птгЕТ
Москва • Санкт-Петербург - Нижний Новгород - ВоронежРостов-на-Дону ・ Екатеринбург • Самара • НовосибирскКиев - Харьков ・ Минск
2006
ББК 32.973-018.2
УДК 00443
Ф24
Фаронов В. В.
Ф24 Delphi 2005. Разработка приложен而 для баз данных и Интернета. — СПб.: Питер, 2006.——603 с.: ил.
ISBN 5-469-01191-7
В книге самого известного в нашей стране автора по тематике Delphi на многочисленных примерах показываотся применение системы программирования Delphi 2005 для создания двух наиболее важных типов приложений: для управления базами данных и для работы с Интернетом. Издание посвящено решению указанных задач на платформе .NET Framework с применением технологий ADO.NET и ASP.NET. Книга в основном рассчитана на читателя, имеющего опыт создания приложений Win32 я желающего освоить уникальные возможности платформы .NET Framework.
ББК 32.973-018.2
УДК 004.43
Все права защищены, Никакая часть денной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских праа.
Информация, содержащаяся в данной книге, получен# из источников, рассматриваемых издательством как надежные. Твм не менев( имея в веду возможные человаческиа или технические ошибки, издательство не может гарантировать абсолютную точность и полноту приводимых сведений и не несет ответственности за возможные ошибки, связанные с использованием книга.
ISBN 5-469-01191-7ISBN 5-469-01191-7© ЗАО Издательский дом «Питер>( 2006
ISBN 5-469-01191-7
ISBN 5-469-01191-7
Краткое содержание
От автора16
От издательства18
Часть I. Создание приложений для работы с базами данных
Глава 1. Введение в базы данных20
Глава 2. Технология ADO.NET57
Глааа 3. Технология BDE.NET .. . 117
Глава 4. Технология dbGo.NET211
Глава 5. Технология dbExpress.NET242
Глава 6. Технология IBX.NET268
Глава 7. Хранимые процедуры, триггеры и представления291
Глава 8. Отчеты308
Часть II. Создание приложений для работы с Интернетом
Глава 9. Программирование для Интернета и технология ASP.NET357
Глава 10. Веб-формы и серверные элементы управления 369
Глава 11. Проверка данных398
Глава 12. Работа с базами данных406
Глава 13. Веб-службы436
Глава 14. Создание пользовательских элементов управления447
Глава 15. Защита приложений ASP.NET455
Глава 16. Программирование приложений ASP.NET468
Приложения
Приложение А. Сервер InterBase484
Приложение Б. Краткая справка по языку SQL .. . . 514
Приложение В. Краткая справка по языкам HTML и XML526
Приложение Г. Краткая справка по языку Visual Basic .NET 553
Приложение Д. Использование классов общего назначения платформы .NET Framework559
Алфавитный указатель594
о О334667О1155667899Ю334 Z 222222233333333333 屮 444о О334667О1155667899Ю334 Z 222222233333333333 屮 444
о О334667О1155667899Ю334 Z 222222233333333333 屮 444
о О334667О1155667899Ю334 Z 222222233333333333 屮 444
Содержание
От автора16
От издательства18
Часть I. Создание приложений для работы с базами данных
Глава 1. Введение в базы данных
Типы СУБД
Таблицы БД и связи между ними Первичные ключи и индексы
Создание БД
Демонстрационная БД «книголюб»
Анализ информационных потоков
Проектирование БД
Имена таблиц и полей Механизмы BDE и ODBC Создание таблиц файл-серверных БД
Свойства таблиц Paradox 7
Типы полей
Контроль содержимого палей
Таблица подстановки
Вторичные индексы
Ссылочная целостность
Парольная защита
Выбор языкового драйвера
Создание таблиц клиент-серверных БД Пример простой программы
Разработка главной формы
Создание псевдонима БД
7 9 2 3 4 5 7 889001113567389901356036812599^2 4455 5 5 5 555666666666666677777888899999117 9 2 3 4 5 7 889001113567389901356036812599^2 4455 5 5 5 555666666666666677777888899999117 7 8 8 57 7 8 8 5
7 9 2 3 4 5 7 889001113567389901356036812599^2 4455 5 5 5 55566666666666667777788889999911
7 9 2 3 4 5 7 889001113567389901356036812599^2 4455 5 5 5 55566666666666667777788889999911
7 7 8 8 5
7 7 8 8 5
Связь с данными
Создание объектов-полей ... Создание объектов-столбцов . Обработчик события OnGetText Бизнес-правила
Транзакции
Глава 2. Технология ADO.NET
Классы ADO.NET
Соединенные классы
Разъединенные классы
Провайдеры данных ADO.NET
Провайдеры Microsoft
Провайдер Borland
Простой пример
Конструирование проекта
Настройка набора данных
Прогон программы
Применение объекта Connection
Задание значения свойства Connectionstring Работа с транзакциями Получение метаданных События соединения
Применение объектов Command и DataReader
Использование метода ExecuteNonQuery Выполнение параметрических запросов Получение множества результатов запроса
Класс DataAdapter
Свойства, методы и события класса DataSet — набор данных DataTable — таблица НД
DataColumn — поля таблиц Вычисляемые поля Подстановочные поля
Изменение названия и скрытие полей DataRow — записи
Визуализация данных
DataGrid — сетка данных Использование свойства DataBindings визуальных компонентов
Программный доступ к значениям таблиц
Глава 3. Технология BDE.NET . •
Суть технологии
Поля
Обзор свойств, методов и событий Использование объектов-полей .
23499569955793567713334568990 杜12l45l5l7l 1 3 6 7 7 2 2333334^44555566^66777777У7778888888О 1 1-1112 2111111111111111111111111111111111112 2 2 2 2 2 2 223499569955793567713334568990 杜12l45l5l7l 1 3 6 7 7 2 2333334^44555566^66777777У7778888888О 1 1-1112 2111111111111111111111111111111111112 2 2 2 2 2 2 2
23499569955793567713334568990 杜12l45l5l7l 1 3 6 7 7 2 2
333334^44555566^66777777У7778888888О 1 1-1112 2
111111111111111111111111111111111112 2 2 2 2 2 2 2
23499569955793567713334568990 杜12l45l5l7l 1 3 6 7 7 2 2
333334^44555566^66777777У7778888888О 1 1-1112 2
111111111111111111111111111111111112 2 2 2 2 2 2 2
Проверка правильности введенного в поле значения Формирование текстового представления поля
Обзор полей TxxxField
Компоненты TSession и TDatabase. Транзакции Компонент TSession Компонент TDatabase
Транзакции
Наборы данных
Обзор свойств, методов и событий
Открытие и закрытие набора данных
Программный доступ к записям
Навигация по набору данных
Поиск записей в наборах данных
Фильтрация записей
Блокировка таблиц в многопользовательском режиме
Обзор событий
Таблицы
Обзор свойств и методов
Индексы
Эксклюзивный доступ к таблице
Удаление записей и таблиц
Поиск записей в таблице
Выборка записей
Запросы
Обзор свойств
Обзор методов
Свойство SQL
Методы Open и ExecSQL
Параметрические запросы
Методы Prepare и UnPrepare
Изменяемые запросы
Сортировка в обратном порядке
Визуализация данных
Компонент TDataSource
Компонент TDBGrid
Компоненты для визуализации полей текущей записи
Глава 4. Технология dbGo.NET
Пример простой программы
Установление связи с объектом ADO
Структура строки связи
Формирование строки связи
Особенности использования компонентов dbGo.NET Базовые объекты ADO
Связной компонент TADOConnection223
Работа с транзакциями225
Глава 7. Хранимые прсщедуры, триггеры и представления ...Глава 7. Хранимые прсщедуры, триггеры и представления ...32343940414243外48弘57575759686871717276808181858789899191939394949494959595969797000101 2 2 2 2 2 ^ 22222222 ^ 222222222222 ^ 222222222222233332343940414243外48弘57575759686871717276808181858789899191939394949494959595969797000101 2 2 2 2 2 ^ 22222222 ^ 222222222222 ^ 2222222222222333
Глава 7. Хранимые прсщедуры, триггеры и представления ...
Глава 7. Хранимые прсщедуры, триггеры и представления ...
32343940414243外48弘57575759686871717276808181858789899191939394949494959595969797000101 2 2 2 2 2 ^ 22222222 ^ 222222222222 ^ 2222222222222333
32343940414243外48弘57575759686871717276808181858789899191939394949494959595969797000101 2 2 2 2 2 ^ 22222222 ^ 222222222222 ^ 2222222222222333
компонент TADOCommand
Свойства, методы и события компонентов-наборов Компонент TTKDODataSet
Компонент TADOTable
Компонент TADOQuery
Глава 5. Технология dbExpress.NET
Пример простой программы
Компоненты для реализации технологии
Компонент TSQLConnection
Компонент TSQLDataSet
Компонент TSQLQuery
Компонент TSQLTable
Компонент TSQLMonitor
Компонент TSImpfeDataSet
Глава 6. Технология IBX.NET ..・ Пример простой программы Компоненты для реализации технологии Класс TIBBase Компонент TIBDatabase Компонент TIBTransaction ..., Компонент TIBTable Компонент TIBQuery Компонент TIBDataSet Компонент TIBSQL Компонент TIBDatabaseInfo ... Компонент TIBSQLMonitor .... Компонент TIBExtract
Создание хранимых процедур
Алгоритмический язык процедур и триггеров
Локальные переменные
Операторные скобки
Оператор SELECT
Условный оператор
Операторы FOR и SUSPEND .. Оператор присваивания .... Операторы WHILE и ЕХП ... Оператор EXECUTE PROCEDURE Исключения
Компоненты доступа к хранимым процедурам Компонент TStoredProc
Компонент TADOStoredProc
Компонент TSQLStoredProc
Компонент TIBStoredProc
Создание триггеров302
Реализация бизнес-правил с помощью триггеров302
Изменение и удаление процедур и триггеров306
Представления306
Глава 8. Отчеты308
Основы технологии Crystal Reports308
Пример создания простого отчета308
Дополнительные средства эксперта создания стандартного отчета .315
Экспорт отчета 322
Основы технологии Rave Reports323
Пример создания отчета323
Привязка проекта отчета к приложению331
Визуальная среда Rave Reports Designer332
Составляющие проекта отчета333
Объекты данных336
Импорт в отчет произвольных внешних файлов339
Защита данных 341
Типы отчетов.342
Использование агрегатных функций351
Экспорт отчета в файл 353
Часть II. Создание приложений для работы с Интернетом
Глава 9. Программирование для Интернета и технология ASP.NET 357
Основы сетевого программирования357
Средства357
Некоторые детали протокола HTTP 358
Общая схема обработки запроса клиента 360
Введение в технологию ASP.NET 361
Назначение и архитектура технологии ASP.NET361
Возможности технологии ASP.NET365
Директива Раде 366
Атрибут CodeBehind367
Сценарии368
Глава 10. Веб-формы и серверные элементы управления . . , . 369
Веб-формы369
Серверные элементы управления372
Компоненты категории HTML Elements373
Компоненты категории Web Controls374
Глава 11. Проверка данных 398
Две формы проверки398
Настройка клиентской проверки399
Отключение клиентской проверки399
Элемент RequiredReldValidator
Элемент RangeValidator
Элемент RegularExpressionValidator
Элемент CompareValidator
Элемент Validationsummary
Элемент CustomValidator
Глава 12. Работа с базами данных
Доступ к данным
Компоненты доступа к MS SQL Server
Компоненты доступа к другим источникам данных
Визуализация данных
Простой пример
Стандартные элементы для работы с базами данных
Привязка данных
Элемент Repeater
Элемент DataList
Элемент DataGrid
Элементы категории DB Web
Элемент DBWebDataSource
Элемент DBWebNavigator Элемент DBWebGrid Визуализирующие элементы
Глава 13. Веб-службы
Создание веб-служб
Атрибут [WebService]
Атрибут [WebMethod]
Использование веб-служб Создание прокси-класса Использование прокси-класса
Глава 14. Создание пользовательских элементов управления .
Пример простого пользовательского элемента управления Исследование простого элемента управления Элемент управления для регистрации пользователя
Глава 15. Защита приложений ASP.NET
Способы защиты приложений ASP.NET
Аутентификация Windows
Аутентификация на основе форм
Изменения в файле Web.config
Индивидуальная защита страниц
Создание страницы регистрации
Создание регистрационного удостоверения пользователя
399401402403404405406406406407407407409410412415417428428431432433436436442442443443446447447450451455455456457458458459459463399401402403404405406406406407407407409410412415417428428431432433436436442442443443446447447450451455455456457458458459459463Хранение аутентификационной информации в файле Web.config ....
399401402403404405406406406407407407409410412415417428428431432433436436442442443443446447447450451455455456457458458459459463
399401402403404405406406406407407407409410412415417428428431432433436436442442443443446447447450451455455456457458458459459463
8 88158902 4646464747474748488 88158902 4646464747474748484 4568301124556678335677899001348^^^^^««««^^^«««^мммммммммиия^4 4568301124556678335677899001348^^^^^««««^^^«««^мммммммммиия^
8 88158902 464646474747474848
8 88158902 464646474747474848
4 45683011245566783356778990013
48^^^^^««««^^^«««^мммммммммиия^
4 45683011245566783356778990013
48^^^^^««««^^^«««^мммммммммиия^
Хранение регистрационной информации в XML-файле465
Хранение регистрационной инс|х)рмации в БД466
Аутентификация по паспорту467
Глава 16. Программирование приложении ASP.NET
Объекты и классы приложений ASP.NET
Класс Раде
Класс HttpRequest
Класс HttpResponse
Состояние вида
Поле _ViewState
Управление состоянием на уровне сеанса
Управление состоянием на уровне приложения ...
Приложения
Приложение А. Сервер InterBase ...
Назначение и возможности Некоторые технические характеристики .... Физическая организация базы данных InterBase Типы данных InterBase
Обзор типов данных InterBase Столбцы-массивы Типы DEQMAL и NUMERIC Тип DATE Типы CHAR и VARCHAR Тип BLOB
Денежные столбцы Генераторы
Совместимость типов
Домены Ограничения на значения столбцов Ручное администрирование сервера Программное администрирование сервера ..,
Базовые классы
Компонент TIBConfigService
Компонент TIBBackupService
Компонент TIBRestoreService Компонент TIBValidationService Компонент TIBStatisticalService Компонент TIBLogService Компонент TIBSecurityService Компонент TIBServerProperties Компонент TIBLicensingService Компонент TIBInstall Компонент TIBUnlnstall
Приложение Б. Краткая справка по языку SQL . . . 514
Простая выборка данных514
Выборка из связанных таблиц*515
Сортировка записей517
Сложные критерии отбора 517
Псевдонимы полей, таблиц и комментарии520
Агрегатные функции и группировка записей520
Создание/удаление таблиц и индексов523
Изменение таблиц524
Вставка, удаление и редактирование записей 524
Приложение В. Краткая справка по языкам HTML и XML526
Знакомство с языком HTML526
Система тегов526
Гиперссылки528
Шрифты529
Списки529
Изображения 531
Уточняющие параметры и цвет531
Комментарии 532
Диалоговые средства532
Таблицы535
Фреймы537
Другие возможности539
Знакомство с языком XML540
Причины разработки XML540
Структура XML-документа541
Простой пример544
Шаблон преобразования545
Обработка таблицы547
Сортировка549
Фильтрация551
Концепция объектной модели документа552
Приложение Г. Краткая правка по языку Visual Basic .NET . . . 553
Синтаксис языка553
Типы данных* 554
Объявления переменных554
Массивы554
Преобразования типов555
Выражения и операции556
Операторы присваивания556
Условный оператор557
Оператор выбора557
Оператор For558
Оператор While558
Оператор Do558
Приложение Д. Использование классов общего назначения платформы .NET Framework559
Коллекции559
Интерфейсы пространства имен System.Collection559
Классы пространства имен System.Collection562
Обработка строк572
Преобразование значений других типов в строку и обратно572
Форматирование строк572
Использование методов и свойств строк576
Работа с файловой системой580
Классы для работы с файловой системой581
Запись и чтение файлов .. . 587
Сериализация590
Техника сериализации590
Пример591
Алфавитный указатель .. . . 594
От автора
Появление платформы .NET Framework является, безусловно, самым революционным событием в мире программирования за последние 10 лет. Разработчики корпорации Microsoft, создавшие эту платформу, постарались учесть накопленный опыт программирования самых разных приложений и создали уникальный инструмент, позволяющий значительно облегчить и ускорить их разработку. Пожалуй, наиболее важная составляющая новой платформы — общая система типов (Common System Type, CTS). Входящие в ее состав более 4000 типов и классов составляют «кирпичики» повторно используемого кода, решающие практически любые задачи при создании самых разных приложений.
В сегодняшнем мире, объединенном «паутиной» Интернета, наиболее востребован* ной является задача создания веб-приложений. Разработчики .NET Framework подчеркивают нацеленность данной платформы на решение именно этой задачи. Кроме того, программистам очень часто приходится решать задачу управления данными. В .NET Framework существует множество классов, способных обеспечить доступ к разнообразным данным, представленным в форме файловых таблиц, серверных таблиц, XML-файлов и т. д. Этим двум задачам — созданию приложений для работы с данными и приложений для Интернета — и посвящена книга, которую вы держите в своих руках.
Система программирования Delphi 2005 американской корпорации Borland приспособлена как для создания обычных приложений Win32, так и для использования платформы .NET Framework. Предполагается, что вы знакомы с этой системой (средой и языком программирования) по другим книгам. (В качестве необязательной ссылки сошлюсь на мою книгу《Delphi 2005. Язык, среда, разработка приложений», выпущенную в конце мая 2005 года в издательстве «Питер».) И хотя Delphi 2005 может применяться для создания приложений Win32, в настоящей книге эта возможность не описывается: книга полностью посвящена решению
От автора 17
указанных задач на платформе .NET Framework. Более того, технология ASP.NET, которая рассматривается во второй части книги, может работать только на этой платформе.
В заключение скажу, что сжатые сроки создания книги и сложность рассматриваемых в ней технологий не позволили написать ее в форме доступного учебника — судя по всему, это задача будущего. Книга во многом рассчитана на искушенного читателя, имеющего опыт создания приложений Win32 и желающего освоить уникальные возможности платформы .NET Framework. Буду искренне рад, если она поможет вам в этом.
Москва, 20 августа 2005 г.
От издательства
Ваши замечания, предложения н вопросы отправляйте по адресу электронной почты comp@piter.com (издательство «Питер», компьютерная редакция).
Мы будем рады узнать ваше мнение!
Все исходные тексты, приведенные в книге, вы можете найти по адресу: http:// www.piter.com/download.
Подробную информацию о наших книгах вы найдете на веб-сайте издательства:
http://www.piter.com.
Создание приложений для работы с базами данных
Delphi имеет развитые средства создания систем управления базами данных Речь идет прежде всего о технологии ADO.NET, которая поддерживается в CLR (Common Language Run-time — общеязыковая среда исполнения в тезшологии .NET). Но возможности Delphi не исчерпываются только этой технологией. В предыдущих версиях Delphi созданы различные альтернативные технологии, подчас более эффективные, чем ADO.NET. Эти технологии перенесены в Delphi 2005 н, как и ADO.NET, описываются в главах этой части*
Введение в базы данныхВведение в базы данных
Введение в базы данных
Введение в базы данных
Базами данных (БД) называют электронные хранилища информации, доступ к которым осуществляется с одного или нескольких компьютеров. Обычно БД создается для хранения данных, содержащих сведения о некоторой предметной области, то есть некоторой области человеческой деятельности или области реального мира, и доступа к ним.
Типы СУБД
Системы управления базами данных (СУБД) — это программные средства, предназначенные для создания, наполнения, обновления и удаления баз данных. Различают три основных вида СУБД: промышленные универсального назначения, промышленные специального назначения и разрабатываемые для конкретного заказчика. Специализированные СУБД создаются для управления базами данных конкретного назначения — бухгалтерскими, складскими, банковскими и т. д. Универсальные СУБД не имеют четко очерченных рамок применения, они рассчитаны «на все случаи жизни» н, как следствие, достаточно сложны и требуют от пользователя специальных знаний. Как специализированные, так и универсальные промышленные СУБД относительно дешевы, довольно надежны (отлажены) и готовы к немедленной работе, в то время как заказные СУБД требуют существенных затрат, а их подготовка к работе и отладка занимают значительный период времени (от нескольких месяцев до нескольких лет). Однако, в отличие от промышленных, заказные СУБД в максимальной степени учитывают специфику работы заказчика (того или иного предприятия), их интерфейс обычно интуитивно понятен пользователям и не требует от них специальных знаний.
По своей архитектуре СУБД делятся на одао-, двух- и трехзвенные (рис. 1.1). В однозвенной архитектуре используется единственное звено (клиент), обеспечивающее необходимую логику управления данными и их визуализацию. В двухзвенной
архитектуре значительную часть логики управления данными берет на себя сервер БД, в то время как клиент в основном занят отображением данных в удобном для пользователя виде. В трехзвенных СУБД имеется промежуточное звено — сервер приложений, являющееся посредником между клиентом и сервером БД. Сервер приложений призван полностью избавить клиента от каких бы то ни было забот по управлению данными и обеспечению связи с сервером БД.
Рис. 1.1. Архитектура СУБД: слева — однозвенная; в центре — двухзвенная; справа — трехзвенная
В зависимости от местоположения отдельных частей СУБД различают локальные и сетевые СУБД.
Все части локальной СУБД размещаются на компьютере пользователя базы данных. Чтобы с одной и той же БД одновременно могли работать несколько пользователей, каждый пользовательский компьютер должен иметь свою копию локальной БД. Существенной проблемой СУБД такого типа является синхронизация копий данных, именно поэтому для решения задач, требующих совместной работы нескольких пользователей, локальные СУБД практически не применяются. К сетевым относятся файл-серверные, клиент-серверные и распределенные СУБД. Непременным атрибутом этих систем является сеть, обеспечивающая аппаратную связь компьютеров и делающая возможной корпоративную работу множества пользователей с одними и теми же данными.
В файл-серверных СУБД все данные обычно размещаются в одном или нескольких каталогах достаточно мощной машины, специально выделенной для этих целей и постоянно подключенной к сети. Такой компьютер называется файл-сервером —отсюда название СУБД. Безусловным достоинством СУБД этого типа является относительная простота ее создания и обслуживания — фактически все сводится лишь к развертыванию локальной сети и установке на подключенных к ней компьютерах сетевых операционных систем. По счастью» Delphi «умеет»
использовать сетевые средства самой популярной в мире ОС — Windows для создания соответствующих клиентских мест, то есть специального программного обеспечения компьютеров пользователей. Нетрудно заметить, что между локальными и файл-серверными вариантами СУБД нет особых различий, так как в них все части собственно СУБД (кроме данных) находятся на компьютере клиента. По архитектуре они обычно являются однозвенными, но в некоторых случаях могут использовать сервер приложений. Недостатком файл-серверных систем является значительная нагрузка на сеть. Если, например, клиенту нужно отыскать сведения об одной из фирм-партнеров, по сети вначале передается весь файл, содержащий сведения о многих сотнях партнеров, и лишь затем в созданной таким образом локальной копии данных отыскивается нужная запись. Ясно, что при интенсивной работе с данными уже нескольких десятков клиентов пропускная способность сети может оказаться недостаточной, и пользователя будут раздражать значительные задержки в реакции СУБД на его запросы. Файл-сер* верные СУБД могут успешно использоваться в относительно небольших фирмах с количеством клиентских мест до нескольких десятков.
Клиент-серверные (двухзвенные) системы значительно снижают нагрузку на сеть, так как клиент общается с данными через специализированного посредника — сервер базы данных, который размещается на машине с данными. Сервер БД принимает запрос от клиента» отыскивает в данных нужную запись и передает ее клиенту. Таким образом, по сети передаются относительно короткий запрос и единственная нужная запись, даже если соответствующий файл с данными содержит сотни тысяч записей. Запрос к серверу формируется на специальном языке структурированных запросов (Structured Query Language, SQL, произносится ^сиквэл^), поэтому часто серверы БД называются SQL-серверами. Серверы БД представляют собой относительно сложные программы, разрабатываемые различными фирмами. К таким программам относятся, например, Microsoft SQL Server производства корпорации Microsoft, Sybase SQL Server корпорации Sybase, Oracle производства одноименной корпорации1, DB2 корпорации IBM и т. д. SQL-сервером является также и сервер InterBase корпорации Borland, который поставляется вместе с Delphi. Клиент-серверные СУБД масштабируются до сотен и тысяч клиентских мест. Распределенные СУБД могут содержать несколько десятков и сотен серверов БД. Количество клиентских мест в них может достгггать десятков и сотен тысяч. Обычно такие СУБД работают на предприятиях государственного масштаба, отдельные подразделения которых разнесены на значительной территории. К таковым, например, относятся подразделения Министерства обороны и Министерства внутренних дел. В распределенных СУБД некоторые серверы могут дублировать друг друга с целью достижения предельно малой вероятности отказов и сбоев, которые могут исказить жизненно важную информацию. Они используют собственные региональные средства связи. Интерес к распределенным СУБД возрос в связи со стремительным развитием Интернета. Опираясь на его возможности, распределенные системы строят не только предприятия государственного масштаба, но
Кстати, Oracle является второй но объемам доходов корпорацией, занимающейся исключительно созданием программного обеспечения (первой является, конечно, Microsoft).
и относительно небольшие коммерческие предприятия, обеспечивая своим сотрудникам работу с корпоративными данными на дому и в командировках.
Таблицы БД и связи между ними
Единицей хранящейся в БД информации является таблица. Каждая таблица представляет собой совокупность строк и столбцов, где строки соответствуют экземпляру объекта, конкретному событию или явлению, а столбцы — атрибутам (признакам, характеристикам, параметрам) этого объекта, события, явления. Ниже приведен пример таблицы» в которой содержатся сведения о продаже книг со склада. Столбцы описывают такие параметры» как дата продажи, название проданной книги, наименование покупателя, количество проданных ему книг. Каждая строка содержит сведения о конкретном событии — продаже книги покупателю. В терминах БД столбцы таблицы называются полями, а ее строки — записями.
Дата
Название книги
Покупатель
Отпущено
10.12.99
Borland C++ Builder 4
Магазин № 1
100
10.12.99
Delphi 5. Учебный курс
Магазин № 1
100
12.12.99
В сетях всемирной паутины
Дом книги
2000
Между отдельными таблицами БД могут существовать связи. Например» информация о покупателе в предыдущей таблице может дополняться в другой таблице.
ПокупательАдресТелефон
Магазин № 1107005, Москва, 2-я Бауманская ул., 12273-00-14
Дом книга105066, Москва, Измайловский б-р, 18/11165-18-99
Базы данных» между отдельными таблицами которых существуют связи, называются реляционными (от relation — связь, отношение).
Связанные отношениями таблицы взаимодействуют по принципу главная (master) —детальная (detail)1. В нашем примере таблица покупателей — главная, а таблица отпуска товаров — детальная. Главную таблицу часто называют родительской. а детальную — дочерней. Одна и та же таблица может быть главной по отношению к одной таблице БД и дочерней — по отношению к другой.
Первичные ключи и индексы
В каждой таблице БД может существовать первичный ключ — поле или набор полей, однозначно идентифицирующий запись. Значение первичного ключа в таблице БД должно быть уникальным, то есть в таблице не должно существовать двух или более записей с одинаковым значением первичного ключа.
Отношение «главная—детальная» иногда называют еще отношением < главная—подчиненная».
Первичные ключи облегчают установление связи между таблицами. В таблице покупателей таким ключом может быть одноименное поле. Установив связь по первичному ключу, мы можем выяснить, что, например, 10.12.99 со склада было отпущено 100 единиц книг «Borland C++ Builder 4» покупателю «Магазин № 1», который расположен по адресу: 107005, Москва, 2-я Бауманская ул., 12 (телефон для связи 273-00-14).
Поскольку первичный ключ должен быть уникальным, для него могут использоваться не все поля таблицы. В приведенном примере название покупателя вряд ли может быть уникальным (《Магазин № 1» может существовать не только в Москве, но и в любом другом городе), поэтому поле Покупатель не может использоваться в качестве первичного ключа. Значительно более редким является совпадение телефонов у двух разных покупателей, поэтому поле Телефон в большей степени подходит на роль первичного ключа. Если в таблице нет полей с уникальными значениями, для создания первичного ключа в нее обычно вводят дополнительное числовое поле, значениями которого СУБД может распоряжаться по своему усмотрению. Если, например, в таблицу покупателей добавить поле №, то она могла бы выглядеть так.
№
Покупатель
Адрес
Телефон
1
Магазин №1
107005, Москва, 2-я Бауманская ул” 12
273-00-14
2
Дом книги
105066, Москва, Измайловский б-р» 18/11
16548-99
Соответственно изменилась бы н связанная с ней таблица отпуска товаров.
Дата
Название книги
Покупатель
Отпущено
10.12.99
Borland C++ Builder 4
1
100
10.12.99
Delphi 5. Учебный курс
1
100
12.12.99
В сетях всемирной паутины
2
2000
Теперь в таблице отпуска товаров в поле Покупатель указывается значение первичного ключа, построенного по полю № таблицы покупателей, что позволяет установить однозначную связь между таблицами.
Индексы отличаются от первичных ключей тем, что не требуют непременной уникальности значений входящих в их состав полей. Они устанавливаются по полям, которые часто используются при поиске и сортировке данных: индексы помогут системе значительно быстрее найти нужные данные или отсортировать их в нужной последовательности.
Создание БД
Создать саму БД (не СУБД) средствами Delphi очень сложно, даже невозможно. Действительно, если вы выбрали двух- или трехзвенную архитектуру, вам не обойтись без сервера БД, который создать собственными силами очень трудно
(да и ни к чему, если на рынке предлагаются десятки таких программ, а в Интернеге при желании можно найти и бесплатный, но вполне приличный сервер MySQL). Если речь идет о файл-серверной БД, то и здесь понадобятся специальные средства. В Delphi для этих целей обычно используется утилита Database Desktop. Могут также применяться промышленные СУБД «Paradox», «dBASE» (корпорации Borland),《FoxPro》,《Access» (корпорации Microsoft) и др. В рамках этой книги я буду описывать средства Database Desktop и сервер InterBase, так как они входят в комплект поставки Delphi и являются собственными продуктами корпорации Borland.
Создание БД начинается с ее проектирования. На этом этапе анализируются информационные потоки с целью определить набор таблиц и их полей. Процесс проектирования в немалой степени зависит от опыта и интуиции разработчика, то есть является творческим, одиако некоторые его моменты можно формализовать. Одной из таких формализаций является требование, согласно которому реляционная база данных должна быть нормализована.
Нормализованной называется БД, в которой выполняется как минимум 3 условия. Выполнение условия называется приведением БД к соответствующей нормальной форме.
Первая нормальная форма (1НФ) требует, чтобы каждое поле таблицы было неделимым и не содержало повторяющихся групп. Пусть в таблице хранится информация о книгах. Эту информацию можно держать в единственном поле, но это противоречит 1НФ. В соответствии с ней в таблице должны быть поля Название, Автор, Издательство и др., совокупность которых дает исчерпывающую информацию о книге. Это облегчает реализацию таких запросов к БД, которые позволят узнать количество разных авторов, количество книг одного автора» количество книг, выпущенных определенным издательством, и т. п. Повторяющимися являются поля, содержащие сходную информацию. Если, например, таблица содержит информацию о покупателе и купленных им книгах, то, в соответствии с 1НФ, список книг должен выделяться в отдельную таблицу. В этом случае таблица покупателей будет главной, а таблица купленных ими книг — детальной. Между такими таблицами должна устанавливаться реляционная связь один ко многим.
Вторая нормальная форма (2НФ) требует, чтобы все поля одной таблицы зависели от первичного ключа — только в этом случае первичный ключ, как и требуется, будет определять уникальную информацию. Допустим, что мы в таблице отпуска книг составили первичный ключ по полям Номер накладной и Покупатель. Нетрудно заметить, что такой ключ будет избыточным: поле Покупатель однозначно определяется номером накладной, поэтому» в соответствии с 2НФ, оно не может входить в первичный ключ.
Третья нормальная форма (ЗНФ) требует, чтобы значение любого поля» не входящего в первичный ключ, никак не зависело от значения других полей. Если в таблице накладных содержатся поля Книга и Отпускная цена, второе поле явно зависит от первого и по требованию ЗНФ должно быть вынесено в отдельную таблицу. Общее правило выполнения ЗНФ таково: в таблице должны быть только не зависящие друг от друга поля, однозначно определяющие некоторый факт, вся
дополнительная информация о значении полей должна вьшоситься в отдельные таблицы. Например, в той же накладной на продажу книг должно быть поле Покупатель, но не должно быть характеризующих его полей Город, Адрес, Телефон и т. п. — эти данные должны быть в отдельной таблице Покупатели.
Как уже говорилось, проектирование БД — творческий процесс, а описанные выше требования носят лишь рекомендательный характер. На практике безусловное выпотаение этих требований (в особенности ЗНФ) приводит к появлению множества небольших по объему таблиц и может существенно замедлять работу с СУБД. Для повышения скорости ее работы проектировщики часто идут на сознательное нарушение описанных требований.
Демонстрационная БД «Книголюб»
Большинство примеров в этой книге относятся к демонстрационной БД «Книголюб», система управления которой предназначена для автоматизации работы крупного оптового поставщика книг. В этом разделе я попытаюсь описать основные функции оптового поставщика и создать проект соответствующей БД. Среди файлов к книге, которые можно загрузить с сайта издательства «Интер» (http:// www.piter.com), вы найдете два варианта этой БД (для файл-серверной СУБД и для СУБД с сервером InterBase). Все хранящиеся в ней данные взяты из реально существующей БД, однако информация о партнерах (поставщиках и покупателях) намеренно искажена.
Анализ информационных потоков
Оптовый поставщик является промежуточным звеном между издательствами (поставщики книг) и магазинами (покупатели книг). Наличие этого звена выгодно тем и другим: издательство, выпустив книгу, передает весь ее тираж или значительную его часть оптовому поставщику и( таким образом, не заботится об отслеживании многочисленных связей с магазинами; магазины, в свою очередь, находят у оптового поставщика огромный ассортимент книг, выпущенных многочисленными издательствами не только в России, но и в ближнем зарубежье.
На рис. 1.2 отображены взаимосвязи между оптовым поставщиком и его партнерами. Характерной особенностью является двусторонний обмен книгами как с поставщиками, так и с покупателями. Это связано с тем, что большинство покупателей (магазинов) берут книги без предварительной оплаты, обязуясь реализовать их в определенный срок. По истечении этого срока магазин обязан оплатить взятые им книги и, возможно, вернуть не проданные книги оптовому поставщику. На таких же условиях оптовый поставщик берет книги у издательств.
Итак, существует два вида документов, которыми обменивается оптовый поставщик со своими партнерами, — это накладные на отпуск, покупку или возврат книг и платежные извещения. В накладных указывается, кому, сколько и каких книг продано (или куплено), в платежных извещениях — суммы платежей и наименование партнера. Характерно, что в них обычно не указывается, за какие конкретные книги осуществляется платеж, — СУБД должна автоматически перераспределить
сумму платежа на книги, указанные в накладных, в соответствии с обычным правилом: оплачиваются самые ранние накладные по мере их поступления.
Рис. 1.2. Взаимосвязи оптового поставщика книг с партнерами
Проектирование БД
После анализа особенностей автоматизируемой области деятельности следует приступить к, возможно, самому важному этапу — проектированию будущей БД, которое заключается в определении состава полей ее таблиц и связей между таблицами. От того, насколько тщательно проведен анализ и насколько грамотно спроектирована БД, в существеннейшей мере зависят эффективность будущей СУБД и ее полезность для пользователя.
В нашем случае анализ показывает, что в БД должно быть как минимум 5 таблиц. В таблице FIRMS будут храниться все нужные сведения о партнерах — с указанием юридического адреса, контактных лиц, телефонов и, разумеется, полного названия каждого партнера. В этой же таблице будем хранить суммарный долг каждого покупателя (или каждому поставщику), который обычно называется сальдо. В таблице BOOKS разместим полные сведения о каждой книге, хотя бы раз купленной у какого-либо поставщика или полученной по обмену от другого оптового поставщика (практика обмена книгами между оптовыми поставщиками широко распространена; за книги, полученные или переданные по обмену, платежи не осуществляются). Таблица NAKLS будет предназначена для хранения сведений о накладных. В ней будут поля, в которых СУБД поместит дату отгрузки или получения партии книг, тип накладной (на покупку или продажу, с предоплатой или в рассрочку, с возвратом ранее проданных/купленных книг или с передачей их по обмену), наименование партнера, общую сумму накладной и т. п. Тут же возникает вопрос: а каким образом СУБД будет хранить сведения о собственно получаемых или передаваемых по накладной книгах? Ведь их состав и количество могут быть какими угодно: если осуществляется покупка книг у поставщика, в накладной обычно указываются лишь одна-две книги, которые покупаются крупными партиями; если книги покупает магазин, он может закупить до сотни наименований книг отаосительно небольшими партиями; не исключена и розничная продажа одной-единственной книги случайному покупателю (я сам много раз
покупал одну-две книги по относительно небольшой цене у того или иного оптового поставщика). Ясно, что в таблице NAKLS, как и в любой другой таблице ВД, не может быть переменного количества полей, поэтому, в соответствии с 1НФ, сведения о связанных с накладной книгах будем хранить в отдельной таблице MOVES: в ее полях укажем ссылку на соответствующую накладную, наименование и количество переданной/полученной книги. Наконец, в таблицу PAYMENTS поместим сведения о платежах: кто, кому и сколько платит.
Таким образом, таблица NAKLS оказывается центральной. Она должна иметь уникальное поле, которое будет однозначно определять каждую накладную. В дальнейшем по этому полю мы создадим первичный ключ, чтобы СУБД могла быстро найти нужную накладную. Каждой записи в NAKLS будет соответствовать произвольное количество записей в таблице MOVES (такая связь в терминологии БД называется связью один ко многим). В этой таблице ссылка на главную таблицу NAKLS определяется тем, что одно из ее полей будет содержать уникальный идентификатор накладной. По этому полю следует создать индекс, чтобы СУБД смогла быстро отыскать все книги, связанные с той или иной накладной. В таблице NAKLS будет также ссылка на уникальный идентификатор партнера из таблицы FIRMS, а в таблице MOVES — ссылка на уникальный идентификатор переданной/полученной книги (две последние связи называются связью один к одному). Таблица PAYMENTS имеет единственную связь — с таблицей FIRMS. Однако при появлении в ней очередной записи должны соответствующим образом изменяться суммы платежей в таблице NAKLS и сальдо в таблице FIRMS.
Ниже приводится описание пяти основных таблиц БД «Книголюб».
Таблица NAKLS
Имя поля
Назначение
NakllD
Уникальный идентификатор накладной. По этому полю нужно создать первичный ключ
NDate
Дата составления накладной. По этому полю нужно создать индекс для сортировки накладных по мере их поступления
NRetDate
Срок возврата нереализованн ых книг. По истечении этого срока возврат не принимается или возвращаемые книги уцениваются. Не используется в накладных обмена
NType
Тип накладной: 0 — покупка у поставщика; 1 — продажа покупателю; 2 — возврат поставщику; 3 — возврат от покупателя; 4 — книги получаются по обмену; 5 — книги передаются по обмену; 6 — покупка с предоплатой;
7 — продажа с предоплатой
NCoeff
Уникальный идентификатор партнера (поле FirmlD таблицы FIRMS) Величина скидки/наценки. Переносится из поля FCoeff таблицы firms, так как это поле со временем может меняться
NSum
NPayedSum
NRetSum
Сумма накладной с учетом значения поля NCoef f Оплаченная сумма. Не используется в накладных обмена Сумма возврата. Не используется в накладных обмена
Таблица BOOKS
Демонстрационная БД «Книголюб» 29
Имя поля
Назначение
Bookid
BName BAuthor BPublish
BYear
BPages
BISBN
BStand
BQuan BPrice
BOpt
BRozn
Уникальный код книги (первичный ключ)
Название книги (индексное поле)
Аатор(ы)
Издательство
Год выпуска
Количество страниц
Код ISBN
Стандарт упаковки (количество книг в пачке)
Остаток книг на складе
Цена покупки книги
Цена оптовой продажи
Цена розничной продажи
Таблица HRMS
Имя поля
Назначение
Firmld
FName FAddress
FCity FPhone
FEMail
FPerson
FFinDelta FCngDelta FCpeff FRetDays
Уникальный идентификатор партита (первичный ключ)
Наименование партнера (индексное поле)
Адрес
Город
Телефон(ы)
Адрес электронной почты
Контактное лицо (лица)
Финансовое сальдо
Обменное сальдо
Коэффициент скидки/наценки
Количество дней для возврата
Таблица MOVES
Имя поля
Назначение
Moveld NakllD MBook MQuan
MPrice
Уникальный идентификатор (первичный ключ)
Код накладной из поля Naklld таблицы NAKLS (индексное поле)
Код книги из поля Bookid таблицы BOOKS (индексное поле)
Количество экземпляров книги
Цена одного экземпляра с учетом скидки/наценки
Таблица PAYMENTS
Имя поляНазначение
PaylD Уникальный идентификатор платежного документа (первичный ключ)
PFinnКод партнера изполя Firmldтаблицы FIRMS
POutНаправление платежа: True —партнеру;False — от партнера
PDateДата платежа
РЭшпСумма платежа
В таблице NAKLS в поле NType содержится код, указывающий тип накладной. Чтобы работа с таблицей стала более удобной, введем дополнительную таблицу TYPES, в которой будем хранить расшифровку типа накладной.
Таблица TYPES
Имя поляНазначение
Type IDКод накладной (0..7)
TNameРасшифровка кода
Имена таблиц и полей
В файл-серверных БД имя таблицы совпадает с именем файла, в котором размещаются все содержащиеся в ней данные. Поскольку 32-разрядные версии Windows разрешают длинные русскоязычные имена файлов, было бы заманчиво назвать таблицы КНИГИ, НАКЛАДНЫЕ и т. п. Я не советую вам делать этого по той простой причине, что кириллицу нельзя использовать в SQL (точнее, это можно делать, только заключив полное название таблицы в кавычки). А так как даже в файл-серверных СУБД часто приходится применять SQL-запросы, это может затруднить их формирование. По той же причине не следует использовать кириллицу в именах полей.
ПРИМЕЧАНИЕ
Поскольку .NET Framework работает с символами Unicode, в именах таблиц и полей можно использовать символы национального алфавита.
В именах полей полезно ставить префикс из одной-двух букв названия таблицы (в таблице NAKLS все имена начинать с буквы《N渺,в FIRMS — с <F> и т. п.). Это исключит вероятность того, что вы случайно назовете поле одним из зарезервированных в SQL слов и просто не сможете составить нужный запрос.
ПРИМЕЧАНИЕ
Исключение составляет поле NakllD в таблице M00VES. Дело в том, что по полям NakllD между таблицами NAKLS и MOVES будет создана реляционная связь «один ко многим». В технологии ADO.NET имена такого рода полей и тип хранящихся в них данных должны быть одинаковыми.
Механизмы BDE и ODBC
Характерной особенностью программ, созданных с помощью Delphi и предназначенных для работы с файл-серверньши базами данных, является их зависимость от специальной библиотеки программ, которая называется BDE (Borland Database Engine — машина баз данных корпорации Borland). BDE представляет собой набор библиотек DLL, предназначенных для низкоуровнего доступа к данным самых разных форматов. BDE автоматически устанавливается в процессе установки Delphi и регистрируется в реестре 32-разрядной версии Windows. BDE <умеете работать с таблицами самых распространенных СУБД, причем как файл-серверных (dBase, Paradox, FoxPro, Clipper), так н клиент-серверных (InterBase, Microsoft SQL Server, Oracle и др.). В BDE имеется собственный интерпретатор языка SQL, что позволяет создавать запросы не только к серверам БД, но и к таблицам файл-сервера.
Без установки и регистрации BDE на компьютере не может работать нн одна программа БД, созданная в Delphi и использующая м^анизм BDE. Это обстоятельство существенно затрудняет распространение программ, так как вместе с программой должен поставляться и набор библиотек BDE.
Альтернативой BDE может служить система драйверов ODBC (Open Data Base Connection — открытое соединение с БД). Драйверы ODBC выполняют сходные с BDE функции низкоуровнего доступа к данным и должны распространяться вместе с программой.
В Delphi 2005 имеются технологии, позволяющие обойтись без BDE или ODBC: ADO.NET (см. главу 2), dbDo.NET (см. главу 4), dbExpress.NET (см. главу 5) и IBX.NET (см. главу 6).
Создание таблиц файл-серверных БД
Как уже говорилось, в файл-серверных БД (а описываемый далее пример создан на основе файл-серверной БД) все таблицы размещаются в одном каталоге (папке). Поэтому перед созданием БД создадим ее каталог. Пусть это будет каталог C:\BIBLDATA. Создание таблиц файл-серверных БД осуществляется с помощью утилиты (вспомогательной программы) Database Desktop (DBD), входящей в комплект поставки Delphi.
Утилита DBD решает целый ряд задач, связанных с таблицами фай л- серверных БД. С ее помощью можно создавать или изменять структуру таблицы, строить ее первичные ключи и индексы, создавать и изменять записи, просматривать их и т. д. Запустите DBD с помощью команды Tools ► Database Desktop главного меню. Первое, что необходимо сделать, — это настроить рабочий каталог утилиты. Выберите команду File ► Working Directory и установите в появившемся окне ссылку на каталог C:\BIBI_DATA (рис. 1.3).
Рис. 1.3. Установка рабочего каталогаРис. 1.3. Установка рабочего каталогаДля создания таблицы NAKLS выберите команду File ► New ► Table. DBD откроет okikj Create Table, и котором можно выбрать тип таблицы. Тип таблицы определяет многие ее свойства. Тип Paradox 7 можно считать паи- луншнм для файл-сервсрных таблиц: щелчком на кнопке ОК согласитесь с вариантом Paradox 7, предложенным по умолчанию. На экране появится окно (рис. 1.4), предназначенное для создания/редактирования структуры таблицы.
Рис. 1.3. Установка рабочего каталога
Рис. 1.3. Установка рабочего каталога
Cf総瞰e p€»adcm 7 RMe: f UtrtttSd }尊
Fietd tostef:Table gfGpefties:j
'「£,.' 丨厂 L Required FieldI
Entef a held name up io 25 characters long.Entef a held name up io 25 characters long.Рис. 1.4. Окно создания структуры таблицыРис. 1.4. Окно создания структуры таблицы三岳::來^参翁金承修然侬經承喻遂犠發森然第率繇慧您戀貝■ !!
Entef a held name up io 25 characters long.
Entef a held name up io 25 characters long.
Рис. 1.4. Окно создания структуры таблицы
Рис. 1.4. Окно создания структуры таблицы
Каждому7 iicjk) создаваемо!! таблицы соответствует одна запись в таблице Field roster этого окна: в колонку Field Name нужно поместить имя гимн, в колонку Туре символ, определяющий тип хранимых в поле данных, в колонку Size — число, определяющее длину поля (требуется не для всех типов полей), и, наконец, в колонку Key — символ звездочки (), если по значениям этого ноля нужно построить первичньп! ключ.
Введите название uepnoio поля, Naklld (первый епмво.! названия поля для таблиц Paradox DBD всегда вводится прописным), и нажмите клавишу табуляции ;их ii(?”no1ad к следующей колонке, в KCTopoii вводится тип поля. Н?1жмите клавишу npttoc.'ia, чтобы утилита DBD “сказала список возможных типов, и выберите
Создание таблиц файл-серверных БД 33
в нем тип Long. Щелкните на колонке Key. Нажмгпс клавишу пробела, чтобы создать ПО ИОЛ К) первичный ключ.
Продолжите ивод тюлсЛ таблицы NAKLS так, как показано на рис. 1.5. Для первых четырех【юлск установите флажок Required Field, означающий, что при вводе очередной записи в эти поля обязательно должны быть помещены значения, 一 за этим будет следить СУБД. Четыре других поля могут нс определяться в момент ввода очередной записи. Имеет смысл определить для них значения по умолчанию и строке Default value: для ноля NCoef f таким значением будет 1, для остальных - 0.
1 Restructure Paradoxk^W^Rndows Ы|Ьг ЫАЮ.$ CB “ 蕊七‘ ^^" 席
field loclQffield loclQfField NameField Namef №klld 2 NDate 3 WetDate 4 NType 5<NFirrn ~ € NCcefT' / 7 NSurpf №klld 2 NDate 3 WetDate 4 NType 5<NFirrn ~ € NCcefT' / 7 NSurp:Typ^^Size ;Key'::Typ^^Size ;Key':;二$泌i n;二$泌i n8 t4PayedSum9 NRetSum8 t4PayedSum9 NRetSumTable properties! iValidify ChecksTable properties! iValidify Checks"[Г' 1. Required FieldJ 2- Minimum vdue:"[Г' 1. Required FieldJ 2- Minimum vdue::-q 3 Maximum yak»::-q 3 Maximum yak»:4 Oefault value:4 Oefault value:
field loclQf
field loclQf
Field Name
Field Name
f №klld 2 NDate 3 WetDate 4 NType 5<NFirrn ~ € NCcefT' / 7 NSurp
f №klld 2 NDate 3 WetDate 4 NType 5<NFirrn ~ € NCcefT' / 7 NSurp
:Typ^^Size ;Key':
:Typ^^Size ;Key':
;二$泌
i n
;二$泌
i n
8 t4PayedSum
9 NRetSum
8 t4PayedSum
9 NRetSum
Table properties
! iValidify Checks
Table properties
! iValidify Checks
"[Г' 1. Required FieldJ 2- Minimum vdue:
"[Г' 1. Required FieldJ 2- Minimum vdue:
:-q 3 Maximum yak»:
:-q 3 Maximum yak»:
4 Oefault value:
4 Oefault value:
L 冶ighQick q( pfe$£ Spacebar to choose з held Wpe.L 冶ighQick q( pfe$£ Spacebar to choose з held Wpe.5 Picture:5 Picture:厂Pack T出e厂Pack T出eAwtJjAwtJj
L 冶ighQick q( pfe$£ Spacebar to choose з held Wpe.
L 冶ighQick q( pfe$£ Spacebar to choose з held Wpe.
5 Picture:
5 Picture:
厂Pack T出e
厂Pack T出e
AwtJj
AwtJj
I . S&g ^1Save As., |I . S&g ^1Save As., |CancelCancel
I . S&g ^1Save As., |
I . S&g ^1Save As., |
Cancel
Cancel
Рис. 1.5. Структура полей таблицы NAKLS
По нолю NDate нужно определить индекс (в термикологии таблиц Paradox он называется вторичным). Как уже говорилось, в отличие от первичных ключей, индексы могут содержать нсуникальные значения и служат для быстрого поиска иух<ной записи (группы Bannceii). С помощью этого индекса мы сможем быстро
отыскать группу накладных, выданных такого-то числа. Для определения индекса раскроете список Table properties в правом верхнем углу окна, выберите пункт Secondary Indexes п щелкните на появившейся кнопке Define. В окне Define Secondary Index (])ис. 1.6) и сплскс полей таблицы выделите (щелчком) nojeNData и затем щелкните на кнопке со стрелкой вправо, чтобы перенести поле в список Indexed fields. Замечу, что таким способом можно перенести не одно, а несколько полей. Индекс, построенный по нескольким полям, называется составным.
NType NFum NCoeff NSum NPa>dSum NRetSianNType NFum NCoeff NSum NPa>dSum NRetSianIndexed fiekk:Indexed fiekk::х^w^通 J #:х^w^通 J #
NType NFum NCoeff NSum NPa>dSum NRetSian
NType NFum NCoeff NSum NPa>dSum NRetSian
Indexed fiekk:
Indexed fiekk:
:х^w^通 J #
:х^w^通 J #
季睜W#‘
:Г UEe
i 炉 Ma^taned
o* I c”@ J H9 I
Рис. 1.6. Определение индексного поля (полей)
С помощью флажков группы Index options можно определить следующие особенности индекса:
Unique — индекс будет содержать уникальные значения;
Maintained — индексные поля сортируются по возрастанию значений;
Case sensitive — индекс, чувствителен к регистру букв в текстовых полях;
Descending — индексные поля сортируются по убыванию значений.
В нашем случае (а также при определении индексов в других таблицах демонстрационной БД) оставьте эти флажки без изменений (установлен только флажок Maintained) и щелкните на кнопке OK. DBD запросит имя индекса (в таблицах Paradox, как н в большинстве серверов БД, индексы именуются) — введите имя Nakls_ date и щелкните на кнопке ОК. Во вновь появившемся окне определения структуры таблицы щелкните на кнопке Save as л затем укажите имя файла — Nakls.
Мы только что создали структуру таблицы NAKLS. Для ее наполнения лучше воспользоваться ее копией, имеющейся на сайте издательства: www.piter.com. Руководствуясь описанием полей, вы можете самостоятельно создать структуры ос- тальннх таблиц демонстрационной БД, а вот реальные таблицы лучше взять на указанном сайте.
Свойства таблиц Paradox 7
Как уже говорилось, тип таблиц Paradox 7 предпочтителен при создании файл- серверных БД. Таблицы Paradox 7 по сравнению с другими поддерживают самый богатый набор разных типов полей, что позволяет автоматически следить за правильностью вводимых в поля данных (пункт Validity Checks в списке Table properties), выбирать данные из другой таблицы (Lookup Table), строить вторичные индексы, в том числе составные (Secondary Indexes), следить за ссылочной целостностью БД (Referential Integrity), защищать таблицу от несанкинонированного доступа (Password Security), выбирать языковой драйвер (Table Language). Поскольку вам, возможно, понадобится создавать таблицы Paradox для реальной файл-серверной БД, в этом разделе рассматриваются их свойства.
Типы полей
В табл. 1.1 представлены тапы полей, которые могут использоваться в таблицах Paradox. В этой таблице в колонках《Туре》и 《Size》указаны, соответственно» условный символ типа и его размер, то есть те данные, которые помещаются в одноименные колонки таблицы Field roster DBD.
Таблица 1.1. Типы данных в таблицах Paradox
Туре
Size
Тип
Описание
А
1-255
Alpha
Текстовое поле указанной длннн
N
Number
Числа с плавающей запятой в диапазоне от -10ж до +10307 с 15 значащими десятичными разрядами
$
Money
Денежное поле. Содержит вещественные числа с фиксированной запятой, шестью знаками целой части н двумя знаками дробной
S
Short
Целые числа в диапазоне от -32 768 ло +32 767
I
Long Integer
Целые числа в диапазоне от -2 147 483 64 8 до +2 147 483 647
#
0-32
BCD
Двоично-десятичные веп!ествениые числа. Size — количество разрядов после запятой
D
Date
Дата в диапазоне от 1.01.0000 до 31.12.9999
Т
Time
Время с точностью до миллисекунд
@
Timestamp
Дата и время
м
1-240
Мемо
Мемо-поле для размещения произвольных текстовые строк неограниченной длины. Первые Size символов хранятся в основной таблице, остальные —в файле с расширением .МВ
F
0-240
Formatted Memo
Мемо-поле для размеикешж форматированного текста в формате RTF
продолжение 少
Таблица 1Д (продолжение)
Type SizeТип
Описание
G0-240 Graphic
Графическое изображение в формате BMP. Size байтов этого поля хранится в основной таблице, остальные — в отдельном файле
о0-240 OLE
LLogical
Объект OLE
Логическое поле. Содержит значение True или False
+Autoincrement
в0-240 Binary
Автоинкрементное поле
Набор байтов произвольной длины. Первые Size байтов хранятся в основной таблице, остальные — в отдельном файле
Y1-255 Bytes
Набор из size байтов (целиком хранится в таблице)
Контроль содержимого полей
По умолчанию сразу после открь【тия окна редактирования структуры таблицы в списке Table properties выбран пункт Validity Checks (см. рис. 1.5), что позволяет контролировать содержимое полей.
С помощью флажка Required Field вы можете потребовать обязательного заполнения поля при вводе новой записи — за этим будет следить BDE. Также на BDE можно возложить контроль за минимальным и максимальным значениями числового поля (строки Minimum Value и Maximum Value). В строке Default Value можно указать значение поля по умолчанию — при вводе новой записи значение в это поле поместит BDE. С помощью строки Picture можно задать шаблон для автоматического форматирования значения поля. Например, если задан шаблон (###) ###-#### и в поле введена строка 9151653939, она будет автоматически преобразована к виду (915)165-3939.
За более полной информацией о шаблонах обратитесь к встроенной справочной службе DBD.
Таблица подстановки
Для какого-либо поля таблицы иногда требуется установить однозначную связь с полем другой таблицы. В этом случае BDE будет следить за тем, чтобы значение вновь вводимой записи в поле первой таблицы было бы одним нз значений указанного поля в другой таблице, которая в этом случае называется таблицей подстановки. Например, в нашей демонстрационной БД поле NakllD таблицы MOVES должно содержать ссылку на накладную в таблице NAKLS. Если с помощью DBD установить связь между этим полем и полем NakllD таблицы NAKLS, при вводе или редактировании таблицы MOVES BDE отвергнет любые значения, которые не совпадают с одним из значений поля Nakl工D таблицы подстановки NAKLS.
Свойства таблиц Paradox 137
Для ус гановления связи нужно выбрать пункт Table Lookup в списке Table properties и щелкнуть на кнопке Define. В появинтемся окне (рис. 1.7) в списке Fields выбирается поле, за значениями которого нужно следить, и щелчком на кнопке со стрелкой вправо имя этого поля переносится в строку Field name. Затем в списке Lookup table выбирается нужная таблица и щелчком на кнопке со стрелкой влево имя первичного юночевого поля -noil таблицы переносится в строку Lookup field.
E通代”’.蹒睜曝歡雜MBook{S) 'MQuan ⑸МРйсе ⑶E通代”’.蹒睜曝歡雜MBook{S) 'MQuan ⑸МРйсе ⑶Fieidname;4>J рэ®й "Lookup held jjjjjjppr Lookup jjipe --―…”—— ! # ^ust current fieldFieidname;4>J рэ®й "Lookup held jjjjjjppr Lookup jjipe --―…”—— ! # ^ust current fieldLookup table:加康w丽一Lookup table:加康w丽一@BOOKS.DB EARMS DB @ MoverDR固球阖吟雌矗綴瀛瀚BPAYMENTS.DBB9Type$.db@BOOKS.DB EARMS DB @ MoverDR固球阖吟雌矗綴瀛瀚BPAYMENTS.DBB9Type$.dbРис. 1.7. Установление связи с таблицей подстановкиРис. 1.7. Установление связи с таблицей подстановкиi「Al£arre$ponding fieldsi「Al£arre$ponding fields• r Lookup дссев& —Ji Г Fd qo help注 Hfi^andfi• r Lookup дссев& —Ji Г Fd qo help注 Hfi^andfiRnve(o(Aia仕 c\hbldata\g^5欣一Rnve(o(Aia仕 c\hbldata\g^5欣一
E通代”’
.蹒睜曝歡雜
MBook{S) 'MQuan ⑸
МРйсе ⑶
E通代”’
.蹒睜曝歡雜
MBook{S) 'MQuan ⑸
МРйсе ⑶
Fieidname;
4>J рэ®й "
Lookup held jjjjjjpp
r Lookup jjipe --―…”—— ! # ^ust current field
Fieidname;
4>J рэ®й "
Lookup held jjjjjjpp
r Lookup jjipe --―…”—— ! # ^ust current field
Lookup table:
加康w丽一
Lookup table:
加康w丽一
@BOOKS.DB EARMS DB @ MoverDR
固球阖吟雌矗綴瀛瀚
BPAYMENTS.DB
B9Type$.db
@BOOKS.DB EARMS DB @ MoverDR
固球阖吟雌矗綴瀛瀚
BPAYMENTS.DB
B9Type$.db
Рис. 1.7. Установление связи с таблицей подстановки
Рис. 1.7. Установление связи с таблицей подстановки
i「Al£arre$ponding fields
i「Al£arre$ponding fields
• r Lookup дссев& —J
i Г Fd qo help
注 Hfi^andfi
• r Lookup дссев& —J
i Г Fd qo help
注 Hfi^andfi
Rnve(o(Aia仕 c\hbldata\
g^5欣一
Rnve(o(Aia仕 c\hbldata\
g^5欣一
ПРИМЕЧАНИЕ
Связь будет установлена только в том случае, если поле, за значением которого нужно сл(71пть, имеет такой же тип, как и первое индексное поле в таблице подстановки. Так как в глблицах Paradox вторичный индекс можно создать только при паи'шчип в габлицс первичного к-иоча. который, в свою очередь, можно создать только в первом поле, подстановочное поле должно быть ключевым и первым в списке полей таблицы подстановки.
Назначение переключателей:
Just current field — проверяется соответствие только связанных полей;
All corresponding fields — проверяется соответствие всех полей обеих таблиц (в этом случае структуры обеих таблиц должны быть идентичными);
Fill no help — при редактировании проверяемого поля таблица подстановки не иоказываегся;
Help and fill — при редактировании проверяемого поля показывается таблица подстановки.
Вторичные индексы
Процесс создания вторичных индексов описан в разделе «Создание таблиц файл- ссрвернмх В口少.В таблицах Paradox вторичный индекс может быть создан только
38 Глава 1 • Введение в базы данных
в том случав, если предварительно в ней создан первичный ключ. В свою очередь, первичный ключ может быть создан только для одного или нескольких первых полей.
Ссылочная целостность
Ссылочная целостность — это особый механизм, снособствующуш поддержанию непротивореч11 вых сведений в таблицах БД, связанных реляционными отношс' ниями. В дехюнстрационной БД таблица NAKLS содержит данные о накладных, а таблица MOVES — о связанных с ними книгах. Перед удалением данных о на- клад!Ю11 нужно предварительно удалить связанный с ней список книг, иначе таблица MOVES будет содержать записи о «ничейных» книгах. Другой пример. Если мы захотим удалить запись в таблице MOVES (то есть удалить из накладной данные о какой-либо книге), нам следует соответствующим образом изменить количество книг на складе (таблица BOOKS) и сальдо партнера ( таблица FIRMS). Если таблицы связаны механизмом ссылочной целостности, СУБД буавт автоматически блокировать попытки изменения поля связи в родитсльско1г таблице, пока соот- ветствуюишм образом нс изменены связанные с ней записи в дочерней таблице. Для установления ссылочной целостности нужно выбрать пункт Referential Integrity в списке Table properties и щелкнуть на кнопке Define. Откроется окно Referential Integrity, показанное на рис. 1.8.
工呼工呼Мо^;С: :-■ NakllD [I]' ⑴…6闵 MQuan [S) MPiis [$]Мо^;С: :-■ NakllD [I]' ⑴…6闵 MQuan [S) MPiis [$]СЫ4關СЫ4關Раегйк⑦Раегйк⑦З;З;Р Strict 1е{мегШв| integrityР Strict 1е{мегШв| integrity「0k.「0k.Hatter:0 FIRMS.DB EMoves.DB;ENAKLS.DB fflPAYMENTS.DB BTypes.dbHatter:0 FIRMS.DB EMoves.DB;ENAKLS.DB fflPAYMENTS.DB BTypes.dbr Update rule - .启 口《socter Update rule - .启 口《socteCancel jCancel j
工呼
工呼
Мо^;С: :-■ NakllD [I]' ⑴…6闵 MQuan [S) MPiis [$]
Мо^;С: :-■ NakllD [I]' ⑴…6闵 MQuan [S) MPiis [$]
СЫ4關
СЫ4關
Раегйк⑦
Раегйк⑦
З;
З;
Р Strict 1е{мегШв| integrity
Р Strict 1е{мегШв| integrity
「0k.
「0k.
Hatter
:0 FIRMS.DB EMoves.DB
;ENAKLS.DB fflPAYMENTS.DB BTypes.db
Hatter
:0 FIRMS.DB EMoves.DB
;ENAKLS.DB fflPAYMENTS.DB BTypes.db
r Update rule - .启 口《socte
r Update rule - .启 口《socte
Cancel j
Cancel j
Рис. 1.8. Установление ссылочной целостности
В списке Fields выбирается поле связи редактируемой таблицы (она должна быть дочерней), а в списке Table — нужная родительская таблица. После щелчков на кнопках со стрелками имена полей связи переносятся в строки Child fields и Parent's key. Далее нужно щелкнуть на кнопке OK. DBD запросит имя вновь создаваемой ссылочной целостности и затем создаст ее. После этого попытка удаления информации о любой накладной будет отвергаться до тех пор, пока не удалены данные обо всех связанных с ней книгах.
С помощью переключателей в группе Update rule определяются правила поддержания ссылочной целостности:
Prohibit — BDE отвергает любые изменения в связанном поле родительской табл]гцы без соответствующего изменения записей в дочерней таблице; удаление записи родительской таблицы блокируется до удаления связанных с ней записей в дочерней таблице;
Cascade — BDE автоматически производит каскадные изменения в дочерней таблице при изменениях родительской таблицы1.
Парольная защита
Любая таблица Paradox может быть полностью или частично защищена от нссанкцио- нироват<ного доступа. Для этого в списке Table properties выбирается пункт Password Security и щелчком на кнопке Define откр1явается соответствующее дигьпоговое окно (рис. 1.9), Пароль может содержать от 1 до 15 любых символов, в том числе пробелов. Он чувствителен к регистру букв. С помощью кнопки Auxiliary Passwords вызывается дополнительное окно, в котором можно уточнить, какие поля и как защищаются.
Выбор языкового драйвера
Если таблица имеет текстовые поля, для нее нужно указать языковой драйвер. Для этого в списке Table properties выбирается пункт Table Language н щелчком на кнопке Define откр|>1ва- стся Аналоговое окно Table Language (рис. 1.10). Для правильного отображения русскоязычного текста следует выбирать драйвер Pdox ANSI Cyrillic или Paradox Сугг 866. Первый использует кодовую страницу 1251 для Windows, второй —страницу 866 для MS-DOS.
Рис. 1.9. Окно определения пароляРис. 1.9. Окно определения пароляВНИМАНИЕ
Рис. 1.9. Окно определения пароля
Рис. 1.9. Окно определения пароля
Устанавливать языковой драйвер следует даже для таблиц, которые содержат одни числовые поля. Дело в том, что в программе вы будете показывать не условные числовые обозначения партнера или книги, а с помощью подстановочных (lookup) полей дополните таблицу полями из других таблиц. Если для таблицы не установлен нужный языковой драйвер, содержимое подстановочных полей окажется искаженным.
Мне не удалось добиться каскадных изменений — на практике BDE работает только в режиме Prohibit
Создание таблиц клиент-серверных БД
Таблицы и все относящееся к ним (индексы, триггеры, генераторы и т. д.) в серверных БД хранятся в одном файле — фштле базы данных. Поэтому перед созданием таблиц необходимо создать этот файл. Каждый промышленный сервер поставляется с утилитами, позволяющими работать с ним и не требующими для этого каких-либо дополнительных средств. Вместе с сервером InterBase, входящим в поставку Delphi, поставляется утилита IBConsole. Разыщите одноименную команду ее запуска в профаммной группе InterBase (кнопка Пуск, далее Все программы и т. д.) и запустите утилиту (рис. 1.11).
Рис. 1.11. Окно утилиты IBConsole
Сначала нужно зарегистрщювать сервер (в сети moi^t работать несколько серверов). Выберите в меню команду Server ► Register, открыв окно регистрации сервера, показанное на рис. 1,12.
ПРИМЕЧАНИЕ
Расширение .GDB является стандартным для(|)ailioB БД сервера InterBase. В списке строки Default Character Set нужно выбрать кодировку текстовых noJieii. Если вы собираетесь работать с технологией ADO.NET, следует остаиить в этой строке неопределенное значение (пушсг None). Для всех других техиоловнь а также при создании при- 71ожени11 Win32 м(»жш)установить кодировку WIN1251. Однако опыт показывает, что с неоиргделенной кодпроикоЙ текстовые поля нормхчьно работают и в этом случае.
Установите переключатель Local Server. Если вы уже работали с утилитой IBConsoIe и регистрировали локальный сервер, этот переключатель окажется недоступным, а при открытии окна утилиты в нем пы увидите перечеркнутый значок локального сервера. В этом случае щелкните на значке и в правом окне пьюсрите Un-Register.
Введите в строке User Name имя SYSDBA, а в строке Password — пароль masterkey. После регистрации сервера нужно создать фа!1Л БД. Выберите п меню команду Database ► Create Database. отк]1ын окно создания фа^ла БД (рис. 1.13).
В таблице File(s) введите маршруг дос тупа и имя фп『ЕМ например C:\BIBLDATA\ IB_BIBL.GDB, а в строке Alias — псевдоним BZL например BIBL. после чего закройте окно щелчком на кнопке ОК. Создание таблиц н всех остальных сут-
更 Cie^te Database更 Cie^te Database$色旧;Local Seim$色旧;Local SeimРис. 1.13. Создание файла БДРис. 1.13. Создание файла БДHOCTeii серверной БД осуществляется с помощью команд на языке SQL, точнее, на его подмножестве 一 языке DDL (Dala Definition Language — язык определения данных). Выберию в меню Tools ► Interactive SQL, огкрыв окно Interactive SQL (рис. 1.14).
更 Cie^te Database
更 Cie^te Database
$色旧;Local Seim
$色旧;Local Seim
Рис. 1.13. Создание файла БД
Рис. 1.13. Создание файла БД
В этом окне верхняя панель преднагзначена для ввода команд или запросов, в нижней отображается результат запроса.
Язык SQL (DDL) описывается в приложении Б, поэтому его конструкции здесь не поясняются. Вот как создается таблица TYPES БД «Книголюб»:
CREATE TABLE TYPES(
TYPE丄口 SMALLINT NOT NULL PRIMARY KEY,
TNAME VARCHAR{23)}
Создание генератора для поля TYPE工D:
CREATE GENERATOR GEM_T¥PE;
SET GENERATOR GEN_TYRE TO 0
Создание триггера:
CREATE TRIGGER BEF_INS一TYPE FOR TYPES BEFORB INSERT AS
BEGIN
XEW.TYPEID 二 GEN_工D(GEHJTYPE, 1);
END
Вш)д залпсл:
INSERT INTO TYPES(FYPEID, TNAME)
VALUES(0, "Поставка на реализацию")
ВНИМАНИЕ —
Ввод записи с русскоязычными нолями в БД, для которых в строке Default Character Set окна Create Database указано значение None, средствами)ггилиты IBConsoIc невозможен. Используйте для этого утилиту SQL Explorer.
Пример простой программы
В этом разделе на примере создания несложной программы я постараюсь пояснить основные приемы программирования для БД. Окно работающей программы показало на рис. 1.15.
1 01.03.2000 Точка. Социальны! университет Продажа на реализацию1 01.03.2000 Точка. Социальны! университет Продажа на реализациюTlmHacwiHSrTTAS^^S^^^^|Козф-TlmHacwiHSrTTAS^^S^^^^|Козф-ss2 01.0 3.2000 ;Яномр 3:01.03.2000 ИКС ООО '4 ^01.03.2x6 :дасс-паблишерз,5 :01.03.2000 'Розни*<ай гродажа ^Шо1.03.2000 ,0*«а мгиэм2 01.0 3.2000 ;Яномр 3:01.03.2000 ИКС ООО '4 ^01.03.2x6 :дасс-паблишерз,5 :01.03.2000 'Розни*<ай гродажа ^Шо1.03.2000 ,0*«а мгиэмПроАвмл с предоплатойПроАвмл с предоплатой0,00р. i S50,00p,1 30.04.20000,00р. i S50,00p,1 30.04.200088O1.D3.2OOO :ООО Издательство Ъолидж''01.03.200Q 'ПродалитЪ01.03.2000 :ИлитаO1.D3.2OOO :ООО Издательство Ъолидж''01.03.200Q 'ПродалитЪ01.03.2000 :Илита10 ^01.03.2000 000 Издательство "Нопидж"10 ^01.03.2000 000 Издательство "Нопидж"наМИаaие6僞MY,i向语支"宀二員,二."不:наМИаaие6僞MY,i向语支"宀二員,二."不:'Продама на реалиэвцию :Г^мход по обмену Продаже с предоплатой :Продажа нй реалимиж :Поставка на рвалимцмо'Продама на реалиэвцию :Г^мход по обмену Продаже с предоплатой :Продажа нй реалимиж :Поставка на рвалимцмо45 337,S0p.:6 782,00р.45 337,S0p.:6 782,00р.335,92р.; 0(00pJ 0,00р.;234,00р.:335,92р.; 0(00pJ 0,00р.;234,00р.:0,00р. 1,04 31-03,20000,00р'.: 0,75 4 0.04.20000,00р. 1,04 31-03,20000,00р'.: 0,75 4 0.04.20000f00p, 0,00р.0f00p, 0,00р.:Продажа на реалимцпо Z 76"50р,::Продажа на реалимцпо Z 76"50р,:2 320,ТОр, :0,00р. : 2 329,70р.isseiioop.,茄苏:蜀:捐 4 瀛 3£2 320,ТОр, :0,00р. : 2 329,70р.isseiioop.,茄苏:蜀:捐 4 瀛 3£'Продажа на реапимцж'Продажа на реапимцж8S5f00p..8S5f00p..Поставке на рвапиэаииюI写5 610,整>Поставке на рвапиэаииюI写5 610,整>0,00р.:0,00р.;о®;0,00р.:0,00р.;о®;0,00р. 0,00р. 6,OOP:0,00р. 0,00р. 6,OOP:1 01,03.2000 1,0* 02.03.2000 : 1J 30,04.2000 : '1 窗.而:2000’ 0(7S:31.03.2000 0.75 31.03.20001 30^04.^001 01,03.2000 1,0* 02.03.2000 : 1J 30,04.2000 : '1 窗.而:2000’ 0(7S:31.03.2000 0.75 31.03.20001 30^04.^00История экономических учений/ Белоусое/ ФениксИстория фипософж.Учебник для студентов ВУЭов/ Кох«новский/ ФеииксИстория экономики-,Уч®6нм1С длй высшей школы/ Комотолое/ Акадеинческий проектФилософия.Учебник для JOG мка/ Камке/ ЛогосИстория экономических учений/ Белоусое/ ФениксИстория фипософж.Учебник для студентов ВУЭов/ Кох«новский/ ФеииксИстория экономики-,Уч®6нм1С длй высшей школы/ Комотолое/ Акадеинческий проектФилософия.Учебник для JOG мка/ Камке/ Логос~^№<1&]1^а.::―…:]12 .俱映’1529,70р.444,00р.557,20р,~^№<1&]1^а.::―…:]12 .俱映’1529,70р.444,00р.557,20р,
1 01.03.2000 Точка. Социальны! университет Продажа на реализацию
1 01.03.2000 Точка. Социальны! университет Продажа на реализацию
TlmHacwiHSrTTAS^^S^^^^|Козф-
TlmHacwiHSrTTAS^^S^^^^|Козф-
s
s
2 01.0 3.2000 ;Яномр 3:01.03.2000 ИКС ООО '4 ^01.03.2x6 :дасс-паблишерз,
5 :01.03.2000 'Розни*<ай гродажа ^Шо1.03.2000 ,0*«а мгиэм
2 01.0 3.2000 ;Яномр 3:01.03.2000 ИКС ООО '4 ^01.03.2x6 :дасс-паблишерз,
5 :01.03.2000 'Розни*<ай гродажа ^Шо1.03.2000 ,0*«а мгиэм
ПроАвмл с предоплатой
ПроАвмл с предоплатой
0,00р. i S50,00p,1 30.04.2000
0,00р. i S50,00p,1 30.04.2000
8
8
O1.D3.2OOO :ООО Издательство Ъолидж''
01.03.200Q 'ПродалитЪ
01.03.2000 :Илита
O1.D3.2OOO :ООО Издательство Ъолидж''
01.03.200Q 'ПродалитЪ
01.03.2000 :Илита
10 ^01.03.2000 000 Издательство "Нопидж"
10 ^01.03.2000 000 Издательство "Нопидж"
наМИаaие6僞MY,i向语支"宀二員,二."不:
наМИаaие6僞MY,i向语支"宀二員,二."不:
'Продама на реалиэвцию :Г^мход по обмену Продаже с предоплатой :Продажа нй реалимиж :Поставка на рвалимцмо
'Продама на реалиэвцию :Г^мход по обмену Продаже с предоплатой :Продажа нй реалимиж :Поставка на рвалимцмо
45 337,S0p.:6 782,00р.
45 337,S0p.:6 782,00р.
335,92р.; 0(00pJ 0,00р.;
234,00р.:
335,92р.; 0(00pJ 0,00р.;
234,00р.:
0,00р. 1,04 31-03,2000
0,00р'.: 0,75 4 0.04.2000
0,00р. 1,04 31-03,2000
0,00р'.: 0,75 4 0.04.2000
0f00p, 0,00р.
0f00p, 0,00р.
:Продажа на реалимцпо Z 76"50р,:
:Продажа на реалимцпо Z 76"50р,:
2 320,ТОр, :0,00р. : 2 329,70р.
isseiioop.,茄苏:蜀:捐 4 瀛 3£
2 320,ТОр, :0,00р. : 2 329,70р.
isseiioop.,茄苏:蜀:捐 4 瀛 3£
'Продажа на реапимцж
'Продажа на реапимцж
8S5f00p..
8S5f00p..
Поставке на рвапиэаииюI写5 610,整>
Поставке на рвапиэаииюI写5 610,整>
0,00р.:
0,00р.;
о®;
0,00р.:
0,00р.;
о®;
0,00р. 0,00р. 6,OOP:
0,00р. 0,00р. 6,OOP:
1 01,03.2000 1,0* 02.03.2000 : 1J 30,04.2000 : '1 窗.而:2000’ 0(7S:31.03.2000 0.75 31.03.2000
1 30^04.^00
1 01,03.2000 1,0* 02.03.2000 : 1J 30,04.2000 : '1 窗.而:2000’ 0(7S:31.03.2000 0.75 31.03.2000
1 30^04.^00
История экономических учений/ Белоусое/ Феникс
История фипософж.Учебник для студентов ВУЭов/ Кох«новский/ Феиикс
История экономики-,Уч®6нм1С длй высшей школы/ Комотолое/ Акадеинческий проект
Философия.Учебник для JOG мка/ Камке/ Логос
История экономических учений/ Белоусое/ Феникс
История фипософж.Учебник для студентов ВУЭов/ Кох«новский/ Феиикс
История экономики-,Уч®6нм1С длй высшей школы/ Комотолое/ Акадеинческий проект
Философия.Учебник для JOG мка/ Камке/ Логос
~^№<1&]1^а.::―…:]
12 .俱映’
1529,70р.
444,00р.
557,20р,
~^№<1&]1^а.::―…:]
12 .俱映’
1529,70р.
444,00р.
557,20р,
Рис. 1.15. Окно программы на этапе прогона
Как видно из рисунка, программа позволяет просматривать накладные и связанные с ними списки книг. Напомню, что все необходимые для программа файлы БД вы найдете на сайте издательства «Питер» (http://www.piter.com).
Разработка главной формы
Начните новый проект VCL Forms и измените следующие свойства пустой формы, заданные по умолчанию:
Caption = * Накладные на книги'
Name 二'fmNakls'
После изменения свойств сразу сохраните модуль в специально отведенной для этого папке под именем fmNaklsU, а проект — под именем Nakls.
Поместите на форму две панели TPane 1, задайте для их свойств Align значения alBottom: нижняя из них предназначена для размещения кнопок навигатора и кнопки закрытая программы, а расположенная над ней — для размещения сетки
DBGrid, в которой будет отображаться список юшг. Чтобы пользователь программы мог менять высоту этой панели, поместите на пустую часть формы вешку разбивки TSplittier (категория Additional палитры компонентов), для се свойства Al ign задайте значение alBottom, для свойства Beveled — значение True и для свойства Height — значение 5. Поместите на 巾орму еще одну панель и задаете для се свойства Align значение alClient — на этой панели будет расположена сетка DBGrid с данными о накладных.
Поместите на верхнюю и среднюю панели по компоненту TDBGrid (вкладка Data Controls) и для их свойства Align задайте значение alClient.
Очистите свойство Caption самой нижней панели и поместите на нее навигатор БД TDBNavigator (вкладка Data Controls) и кнопку TBitBtn (вкладка Additional). Навигатор расположите у левого края панели, а кнопку — у правого. Раскройте список свойства Anchors кнопки и выровняйте навигатор по правому краю: задав значение False для свойства akLeft и True для свойства akRight. Для свойства Kind кнопки задайте значение bkClose. Вид окна к этому моменту показан на рис. 1.16.
Рис. 1.16. Главное окно программы на этапе разработки
Сохраните вес сделанные вами изменения модуля главной формы на диске.
Создание псевдонима БД
Перед тем как двигаться да.лыпе, сделаем очень важны!! шаг: создадим псевдоним для нашей учебной БД. Псевдоним БД — это просто имя БД. Для файл-сервер- ных БД псевдоним определяет путь доступа к файлам базы данных. В дальнейшем мы, возможно, захотим изменить его. В этом случае нам не придется исправлять зтет путь в многочисленных компонентах доступа к данным — достаточно изменить его в псевдониме, и псе ссылающиеся на псевдоним компоненты будут связаны с новым местом размещения данных. Роль псевдонима особенно велика
в клиент-серверных БДТ в которых он содержит многочисленные дополнительные свойства, управляющие доступом к серверу.
Создать псевдоним можно либо с помощью Администратора BDE (Пуск ► Панель управления ► BDE Administrator), либо с помощью очень полезной упьчкты Database Explorer (SQL Explorer). Так как в дальнейшем нам придется много раз прибегать к ее услугам, настроим пункт Tools главного меню Delphi. Щелкните на этом пункте и выберите команду Configure Tools. В открывшемся окне щелкните на кнопке Add, а во вновь появившемся — на кнопке Browse. С помощью диалогового окна разыщите в папке BIN каталога размещения Delphi файл dbexplor.exe утилиты SQL Explorer (рис. 1.17).
jsQL Explorer
;也内《П:
(C:\progran Files\Borland\BD5\3.0\Bin\cfoexplor.exe
Cancel ' 1
世wHngdr;
|C;\Program Hes\Borland^BD5\3.0\Bin
:Н版j
>НМ做er$:
▼ Macros
1Browse... 1
Рис. 1.17. Настройка вызова утилиты SQL Explorer из меню Tools Delphi
Запустите утшпггу SQL Explorer, на вкладке Databases открывшегося окна щелкните правой кнопкой мыши на узле Database и выберите команду New в контекстном меню. Утилтгга предложит выбрать тип вновь создаваемого псепдопкма. Согласитесь с вариантом Standard, предлагаемым по умолчанию, — псевдонимы именно этого типа предназначены для обслуживания файл-ссрвсрных БД с таблицами Paradox. Сразу после этого появится имя псевдонима STANDARD 1, предлагаемое по умолчанию, и на вкладке Definition будут перечислены его свойства (рис. 1.18).
Рис. 1.18. Определение псевдонима
Воспользуемся тем, что выделено имя STANDARDS, чтобы сразу заменить его именем BIBLDATA. После этого переедите на вкладку Definition if в пустом ноле справа от свойства PATH введите маршрут доступа к файлам БД: С : \BIBLDATA. Па вкладке Databases щелкните на вновь созданном псевдониме правой кнопкой мыши и выберите команду Apply в контекстном меню. В появившемся после этого диалоговом окне подтвердите необходимость запомнить вновь созданный псевдоним.
Если теперь на вкладке Databases щелкнуть на значке свернутого узла слева ог имени псевд(М1има, а затем — на значке свсрнупн'О узла Tables, вы увидите все табл иды БД «Книголюб». Шсужнув на любой из них и открыв вкладку Data, вы сможете увидеть содержимое выбранной таблицы (рис. 1.19).
AI £Ш«Ью Д1е$мAI £Ш«Ью Д1е$мDrtabasub 10KgMу 1-第 В!Ш.'АГД:* [35 ^Si,E°便冏.08;*画Huves-CB;•闻NAKiS.DB!.tfflРА'ЛКНТб.Сб}■•面T*pesqj♦. •冷 D0OEMC6i」点№ SifiLDrtabasub 10KgMу 1-第 В!Ш.'АГД:* [35 ^Si,E°便冏.08;*画Huves-CB;•闻NAKiS.DB!.tfflРА'ЛКНТб.Сб}■•面T*pesqj♦. •冷 D0OEMC6i」点№ SifiLi Corttntsc?COC*S.D6DefrAon. D«* |fnterSQlji Corttntsc?COC*S.D6DefrAon. D«* |fnterSQljЭроМР . ^NameЭроМР . ^Name1 10 минут на /рок MS Weed 2X02 10 кинут не урок Wndowi 9В3 J0 хикут на урс*<.Освой самостоятб>ыю MS ЕхЗ 20004」00,.омпо«емтоа общего калмачемия библиотеки DdphS5 IX! секрет реестра '^rtndow* NT6 12 урикое tuHwxdjLttMwA длступньЛ сегюучнтель лля мех7.!3uwob к успеху(ir>t пракпгцеслив совета как бсктро достичь Касесы вВ ЧС Бумгалтерив.Самоучитель.Bepciwi 74 и 7,? в вотисса* ” о^сстах1 10 минут на /рок MS Weed 2X02 10 кинут не урок Wndowi 9В3 J0 хикут на урс*<.Освой самостоятб>ыю MS ЕхЗ 20004」00,.омпо«емтоа общего калмачемия библиотеки DdphS5 IX! секрет реестра '^rtndow* NT6 12 урикое tuHwxdjLttMwA длступньЛ сегюучнтель лля мех7.!3uwob к успеху(ir>t пракпгцеслив совета как бсктро достичь Касесы вВ ЧС Бумгалтерив.Самоучитель.Bepciwi 74 и 7,? в вотисса* ” о^сстах]pother IФултон •АрхангепьскиЙД»#*елс]pother IФултон •АрхангепьскиЙД»#*елсКомягинКомягин
AI £Ш«Ью Д1е$м
AI £Ш«Ью Д1е$м
Drtabasub 10KgMу 1
-第 В!Ш.'АГД
:* [35 ^S
i,E°便冏.08
;*画Huves-CB
;•闻NAKiS.DB
!.tfflРА'ЛКНТб.Сб
}■•面T*pesq
j♦. •冷 D0OEMC6
i」点№ SifiL
Drtabasub 10KgMу 1
-第 В!Ш.'АГД
:* [35 ^S
i,E°便冏.08
;*画Huves-CB
;•闻NAKiS.DB
!.tfflРА'ЛКНТб.Сб
}■•面T*pesq
j♦. •冷 D0OEMC6
i」点№ SifiL
i Corttntsc?COC*S.D6
DefrAon. D«* |fnterSQlj
i Corttntsc?COC*S.D6
DefrAon. D«* |fnterSQlj
ЭроМР . ^Name
ЭроМР . ^Name
1 10 минут на /рок MS Weed 2X0
2 10 кинут не урок Wndowi 9В
3 J0 хикут на урс*<.Освой самостоятб>ыю MS ЕхЗ 2000
4」00,.омпо«емтоа общего калмачемия библиотеки DdphS
5 IX! секрет реестра '^rtndow* NT
6 12 урикое tuHwxdjLttMwA длступньЛ сегюучнтель лля мех
7.!3uwob к успеху(ir>t пракпгцеслив совета как бсктро достичь Касесы в
В ЧС Бумгалтерив.Самоучитель.Bepciwi 74 и 7,? в вотисса* ” о^сстах
1 10 минут на /рок MS Weed 2X0
2 10 кинут не урок Wndowi 9В
3 J0 хикут на урс*<.Освой самостоятб>ыю MS ЕхЗ 2000
4」00,.омпо«емтоа общего калмачемия библиотеки DdphS
5 IX! секрет реестра '^rtndow* NT
6 12 урикое tuHwxdjLttMwA длступньЛ сегюучнтель лля мех
7.!3uwob к успеху(ir>t пракпгцеслив совета как бсктро достичь Касесы в
В ЧС Бумгалтерив.Самоучитель.Bepciwi 74 и 7,? в вотисса* ” о^сстах
]pother I
Фултон •АрхангепьскиЙ
Д»#*елс
]pother I
Фултон •АрхангепьскиЙ
Д»#*елс
Комягин
Комягин
tiltafftf hbOOkS.DB.'tiltafftf hbOOkS.DB.'Рис. 1,19. Отображение содержимого таблицы в окне SQL ExplorerРис. 1,19. Отображение содержимого таблицы в окне SQL ExplorerINFORMIXINFORMIX;Diabase Driver Name;Diabase Driver NameSTANDARDDriver para。Microsoft VisualSTANDARDDriver para。Microsoft VisualMicrosoft Access Driver (*,mdj)Microsoft Access Driver (*,mdj)Рис. 1.20. Выбор имени сервераРис. 1.20. Выбор имени сервераПсевдоним BIBLDATA открывает доступ к «)а^л・ серверной БД. Чтобы получить доступ к клиент-серверной БД, в окне определения типа БД следует выбрать имя используемого вами сервера БД. например INTRBASE (рис. 1.20). После щелчка на кнопке ОК содержимое окна утилиты будет зависеть от выбранного сервера. Для сервера InterBase вид окна показан на рис. 1.21.Псевдоним BIBLDATA открывает доступ к «)а^л・ серверной БД. Чтобы получить доступ к клиент-серверной БД, в окне определения типа БД следует выбрать имя используемого вами сервера БД. например INTRBASE (рис. 1.20). После щелчка на кнопке ОК содержимое окна утилиты будет зависеть от выбранного сервера. Для сервера InterBase вид окна показан на рис. 1.21.Параметры, задаваемые в этом окне, зависят от тина сервера. Для InterBase следует параметру LANGDRIVER присвоить значение1 Pdox ANSI Cyrillic (выбирается в сиискс. раскрываклцемся после щелчка на кнопке в строке LANGDRIVER), параметру SERVER NAME — маршрут доепша к файлу БД, а параметру USER NAME - имя SYSDSA.Параметры, задаваемые в этом окне, зависят от тина сервера. Для InterBase следует параметру LANGDRIVER присвоить значение1 Pdox ANSI Cyrillic (выбирается в сиискс. раскрываклцемся после щелчка на кнопке в строке LANGDRIVER), параметру SERVER NAME — маршрут доепша к файлу БД, а параметру USER NAME - имя SYSDSA.K;ik уже oiMeuiL'iDcij, установка язык(ш(>г<> драй верп не сбнзнтиьпа.K;ik уже oiMeuiL'iDcij, установка язык(ш(>г<> драй верп не сбнзнтиьпа.
tiltafftf hbOOkS.DB.'
tiltafftf hbOOkS.DB.'
Рис. 1,19. Отображение содержимого таблицы в окне SQL Explorer
Рис. 1,19. Отображение содержимого таблицы в окне SQL Explorer
INFORMIX
INFORMIX
;Diabase Driver Name
;Diabase Driver Name
STANDARD
Driver para。Microsoft Visual
STANDARD
Driver para。Microsoft Visual
Microsoft Access Driver (*,mdj)
Microsoft Access Driver (*,mdj)
Рис. 1.20. Выбор имени сервера
Рис. 1.20. Выбор имени сервера
Псевдоним BIBLDATA открывает доступ к «)а^л・ серверной БД. Чтобы получить доступ к клиент-серверной БД, в окне определения типа БД следует выбрать имя используемого вами сервера БД. например INTRBASE (рис. 1.20). После щелчка на кнопке ОК содержимое окна утилиты будет зависеть от выбранного сервера. Для сервера InterBase вид окна показан на рис. 1.21.
Псевдоним BIBLDATA открывает доступ к «)а^л・ серверной БД. Чтобы получить доступ к клиент-серверной БД, в окне определения типа БД следует выбрать имя используемого вами сервера БД. например INTRBASE (рис. 1.20). После щелчка на кнопке ОК содержимое окна утилиты будет зависеть от выбранного сервера. Для сервера InterBase вид окна показан на рис. 1.21.
Параметры, задаваемые в этом окне, зависят от тина сервера. Для InterBase следует параметру LANGDRIVER присвоить значение1 Pdox ANSI Cyrillic (выбирается в сиискс. раскрываклцемся после щелчка на кнопке в строке LANGDRIVER), параметру SERVER NAME — маршрут доепша к файлу БД, а параметру USER NAME - имя SYSDSA.
Параметры, задаваемые в этом окне, зависят от тина сервера. Для InterBase следует параметру LANGDRIVER присвоить значение1 Pdox ANSI Cyrillic (выбирается в сиискс. раскрываклцемся после щелчка на кнопке в строке LANGDRIVER), параметру SERVER NAME — маршрут доепша к файлу БД, а параметру USER NAME - имя SYSDSA.
K;ik уже oiMeuiL'iDcij, установка язык(ш(>г<> драй верп не сбнзнтиьпа.
K;ik уже oiMeuiL'iDcij, установка язык(ш(>г<> драй верп не сбнзнтиьпа.
Object Qicbwwy 聯 MlewЬ X k^ *> ЙDatebases 辰Uwwry j. > 屯 Databases+!時 BIBLDATA:*i 駿 DBDEMOS生*电此晔±・电 IB_BIBL1251干 jg iBLocalObject Qicbwwy 聯 MlewЬ X k^ *> ЙDatebases 辰Uwwry j. > 屯 Databases+!時 BIBLDATA:*i 駿 DBDEMOS生*电此晔±・电 IB_BIBL1251干 jg iBLocalОО^юги *ОО^юги *DeMon jDeMon j•七盲 Localserver*:旨 Xtreme Sample Database 2003+■ База Аамых M5 Access丰電 Файлы dBAS湛十 Файлы Excel•七盲 Localserver*:旨 Xtreme Sample Database 2003+■ База Аамых M5 Access丰電 Файлы dBAS湛十 Файлы ExcelTypeBATCH COUNT BLOB SIZE ' 'BLOBS TO CACHE COMMIT RETAINENABLE BCDENABLE SCHEMA CACHE LANGDRIVERMAX ROWS OPEN MODE ROLE NAME SCHEMA CACHE DIR SCbCMA CACHE SIZE SCHEMA CACHE TIME SERVER NAME ' SQLPAS5THRU MODE SQLQRYMODE USER NAMEWAIT ON LOCK5TypeBATCH COUNT BLOB SIZE ' 'BLOBS TO CACHE COMMIT RETAINENABLE BCDENABLE SCHEMA CACHE LANGDRIVERMAX ROWS OPEN MODE ROLE NAME SCHEMA CACHE DIR SCbCMA CACHE SIZE SCHEMA CACHE TIME SERVER NAME ' SQLPAS5THRU MODE SQLQRYMODE USER NAMEWAIT ON LOCK5INTRBA5E2СЮ3264FALSEFALSEFALSEPcfox ANSI Cyrillic-1READ/WRITEINTRBA5E2СЮ3264FALSEFALSEFALSEPcfox ANSI Cyrillic-1READ/WRITE88儲^^^^j^g输SHARED AUTOCOMMIT儲^^^^j^g输SHARED AUTOCOMMITSYSDBA FALSESYSDBA FALSE
Object Qicbwwy 聯 Mlew
Ь X k^ *> Й
Datebases 辰Uwwry j
. > 屯 Databases
+!時 BIBLDATA
:*i 駿 DBDEMOS
生*电此晔
±・电 IB_BIBL1251
干 jg iBLocal
Object Qicbwwy 聯 Mlew
Ь X k^ *> Й
Datebases 辰Uwwry j
. > 屯 Databases
+!時 BIBLDATA
:*i 駿 DBDEMOS
生*电此晔
±・电 IB_BIBL1251
干 jg iBLocal
ОО^юги *
ОО^юги *
DeMon j
DeMon j
•七盲 Localserver
*:旨 Xtreme Sample Database 2003
+■ База Аамых M5 Access
丰電 Файлы dBAS
湛十 Файлы Excel
•七盲 Localserver
*:旨 Xtreme Sample Database 2003
+■ База Аамых M5 Access
丰電 Файлы dBAS
湛十 Файлы Excel
Type
BATCH COUNT BLOB SIZE ' '
BLOBS TO CACHE COMMIT RETAIN
ENABLE BCD
ENABLE SCHEMA CACHE LANGDRIVER
MAX ROWS OPEN MODE ROLE NAME SCHEMA CACHE DIR SCbCMA CACHE SIZE SCHEMA CACHE TIME SERVER NAME ' SQLPAS5THRU MODE SQLQRYMODE USER NAME
WAIT ON LOCK5
Type
BATCH COUNT BLOB SIZE ' '
BLOBS TO CACHE COMMIT RETAIN
ENABLE BCD
ENABLE SCHEMA CACHE LANGDRIVER
MAX ROWS OPEN MODE ROLE NAME SCHEMA CACHE DIR SCbCMA CACHE SIZE SCHEMA CACHE TIME SERVER NAME ' SQLPAS5THRU MODE SQLQRYMODE USER NAME
WAIT ON LOCK5
INTRBA5E
2СЮ
32
64
FALSE
FALSE
FALSE
Pcfox ANSI Cyrillic
-1
READ/WRITE
INTRBA5E
2СЮ
32
64
FALSE
FALSE
FALSE
Pcfox ANSI Cyrillic
-1
READ/WRITE
8
8
儲^^^^j^g输
SHARED AUTOCOMMIT
儲^^^^j^g输
SHARED AUTOCOMMIT
SYSDBA FALSE
SYSDBA FALSE
Name of the target saryer.
Рис. 1.21. Определение псевдонима БД для сервера InterBase
Связь с данными
Для связи таблиц с БД воспользуемся компонентом TDatabase категории BDE палитры компонентов Delphi: перенесите его на форму. В окне инспектора объектов раскроете список свойства AliasName и выберите псевдоним BIBLDATA. В строке свойства DatabaseName введите произвольное имя (например, ААА) так называемого локального псевдонима, который создает компонент TDatabase.
Локальный псевдоним доступен только в той программе, в которой используется компонент TDatabase. Этот компонент выполняет множество полезных функций, обеспечивающих связь программы с БД. Для файл-серверных систем только с его помощью можно решшзоиать транзакции — специальный механизм доступа к данным, повышающий их достоверность и непротиворечивость. В клиент-серверных системах он, кроме того, способен передать серверу БД имя пользователя, его пароль и ряд других параметрон, оптимизирующих связь с сервером и избавляющих пользователя программы о丁 обязательной регистрации на сервере. После определения псевдонима БД и создания локального псевдонима исчезнет красный знак вопроса слева от компонента в окне структуры, что сшшетельсгву- ет о готовности компонента к работе. Поскольку в нашей простои программе мы не будем непосредственно обращаться к компоненту, можно оставить для него имя Databasel, заданное по умолчанию, но я все-таки рекомендую изменить его на DB: в дальнейшем на примере этой программы я продемонстрирую работу
механизма транзакци!!, и в программном коде нам придется обращаться к методам и свойствам этого компонента.
Теперь перенесите на форму компонент ТТаЫе (категория BDE). В окне инспектора объектов для свойства DatabaseName нового компонента установите имя локального псевдонима АДА.
Компонент TTable является набором данных (НД). Наборы данных используются преимущественно в фай.ч-серверных системах для доступа к данным из какой- либо одной таблицы БД. Чтобы подготовить компонент к работе, необходимо определить имя этой таблицы: раскройте список его свойства TableName и выберите в нем таблицу NAKLS. В дальне11И1ем нам придется мною раз обращаться к методам и свойствам этого компонента, поэтому измените его имя Tablel, заданное по умолчшппо, на имя связанной с iuim таблицы: в строке свойства Нате введите Nakls. Чтобы данные из НД Nakls смогла отобразить сетка DBGridl в славном окне программы, ее нужно связать с НД с помощью специального компонента TDateiSource: найдите его в категории Data Access палитры компонентон и перенесите на форму. Укажите в кгнестие значения свойства DataSet компонента ссылку на компонент Nakls, а в качестве значения свойства 口aLaScuL 匚邑 верх- ueii сетки DBGridl — ссылку на компонент DataSourcel.
Теперь подготовим вторую пару, ТТаЫе — TDataSource, для отображения данных из таблицы MOVES во второй сетке главного окна: поместите на форму набор данных ТТаЫе и источник данных TDataSource; свяжите IIД с таблицей MOVES и дайте ему имя Moves. Свяжите источник данных с таблицей MOVES, а сетку DBGrid2 — с источником DataSource2. Вид формы к -)тому моменту показан на рис. 1.22.
Рис. 1.22. Окно формы с двумя наборами данных
Наборы данных Nakls и Moves связаны реляционным отношением один ко ,и//о- 2&н: единственной записи (накладной) в первом НД может соответствовать произвольное количество записей (книг) во втором. Чтобы НД《знали» об тем н согласованно отображали данные, их нужна предварительно подготовить. Для этого в свойство Mastersource таблицы MOVES поместите ссылку на компонент DataSourcel и щелчком на кнопке раскро11те окно редактора его свойства MasterFields (рис. 1.23).
Рис 1.23. Редактор свойства MasterFields
Раскройте список Available Indexes н выберите индекс Move_Nakl. Щелкните на единственном поле NakllD в списке Details Fields и на поле NakllD в списке Master Felds. После этого станет доступна кнопка Add — щелкните на ней. В области Coined Fields появится нужная связь NakllD т NakllD. Закройте окно редакк^ра щелчком на кнопке ОК. Раскройте список свойства IndexName таблицы MOVES и выберите индекс Move_Nakl.
Щелкните на таблице MOVES и откройте НД: в окне инспектора объектов поместите в его свойство Active значение True. Точно так же откройте таблицу NAKLS. Свяжите навигатор баз данных DBNavigatorl в нижней части окна с источником DataSourcel.
Создание объектов-полей
Если вы на этом этапе выполните прогон программы, то увидите (рис. 1.24), что сетки связаны друг с другом; при перемещении указателя текущей записи в верхней сетке автоматически меняется содержимое нижней сетки.
Однако сами данные использовать практически невозможно, так как вместо имен партнеров или нанменованн" книг в соответствующих колонках сеток видны лишь их идентификаторы. Кроме того, вас, очевидно, не удовлетпоршш бы и заголовки колонок, в которых по умолчанию выводятся названия соответствующих полей.
ьйнш 3 :1nM好込?』NReTC&e |№Vpe |NHrm ]NCoeFF |N5umьйнш 3 :1nM好込?』NReTC&e |№Vpe |NHrm ]NCoeFF |N5um1 01.03.2000 30.04.2000I ;541550,D0p.a。/2 01.03.2000 31.03.20007:10!bCK335,92р.335,92p3 01.03.2000 10.04.2000 :120,7545 33 7,50р.qoop4 01.03.2000 01.03.200043516 782,00р.OjOOp5 :01.03.2000 02.03.2000 •7;581,04234,00р.231 ODp§01,03.2000 30,04.2000 ;1 ;55IJ:2 328,7g.G,DOp7 01,03.200) 30.04.2000 J681:55 6Ю,00р.60 2СЛ,65P1 01.03.2000 30.04.2000I ;541550,D0p.a。/2 01.03.2000 31.03.20007:10!bCK335,92р.335,92p3 01.03.2000 10.04.2000 :120,7545 33 7,50р.qoop4 01.03.2000 01.03.200043516 782,00р.OjOOp5 :01.03.2000 02.03.2000 •7;581,04234,00р.231 ODp§01,03.2000 30,04.2000 ;1 ;55IJ:2 328,7g.G,DOp7 01,03.200) 30.04.2000 J681:55 6Ю,00р.60 2СЛ,65P8 01-03.2000 31.03.2000 ;8 01-03.2000 31.03.2000 ;0,75 : 2 767,50р:0,00p^0,75 : 2 767,50р:0,00p^►►156 :802 j12:4S,10p..166;796:;1529,70р.176soq4:4%00p.1862025:557,20p.196497j2535,ZUp.156 :802 j12:4S,10p..166;796:;1529,70р.176soq4:4%00p.1862025:557,20p.196497j2535,ZUp.薇詬一]極/三T紘*:『引йо®y •二力制cе薇詬一]極/三T紘*:『引йо®y •二力制cеРис. 1.24. Предварительный прогон программыРис. 1.24. Предварительный прогон программы
ьйнш 3 :1nM好込?』NReTC&e |№Vpe |NHrm ]NCoeFF |N5um
ьйнш 3 :1nM好込?』NReTC&e |№Vpe |NHrm ]NCoeFF |N5um
1 01.03.2000 30.04.2000
I ;541
550,D0p.
a。/
2 01.03.2000 31.03.2000
7:
10!
bCK
335,92р.
335,92p
3 01.03.2000 10.04.2000 :
1
2
0,75
45 33 7,50р.
qoop
4 01.03.2000 01.03.2000
4
35
1
6 782,00р.
OjOOp
5 :01.03.2000 02.03.2000 •
7;
58
1,04
234,00р.
231 ODp
§01,03.2000 30,04.2000 ;
1 ;
55
IJ
:2 328,7g.
G,DOp
7 01,03.200) 30.04.2000 J
6
8
1
:55 6Ю,00р.
60 2СЛ,65P
1 01.03.2000 30.04.2000
I ;541
550,D0p.
a。/
2 01.03.2000 31.03.2000
7:
10!
bCK
335,92р.
335,92p
3 01.03.2000 10.04.2000 :
1
2
0,75
45 33 7,50р.
qoop
4 01.03.2000 01.03.2000
4
35
1
6 782,00р.
OjOOp
5 :01.03.2000 02.03.2000 •
7;
58
1,04
234,00р.
231 ODp
§01,03.2000 30,04.2000 ;
1 ;
55
IJ
:2 328,7g.
G,DOp
7 01,03.200) 30.04.2000 J
6
8
1
:55 6Ю,00р.
60 2СЛ,65P
8 01-03.2000 31.03.2000 ;
8 01-03.2000 31.03.2000 ;
0,75 : 2 767,50р:0,00p^
0,75 : 2 767,50р:0,00p^
►
►
15
6 :
802 j
12:
4S,10p..
16
6;
796:;
15
29,70р.
17
6
soq
4:
4%00p.
18
6
2025:
5
57,20p.
19
6
497j
25
35,ZUp.
15
6 :
802 j
12:
4S,10p..
16
6;
796:;
15
29,70р.
17
6
soq
4:
4%00p.
18
6
2025:
5
57,20p.
19
6
497j
25
35,ZUp.
薇詬一]極/三T紘*:『引йо®y •二力制cе
薇詬一]極/三T紘*:『引йо®y •二力制cе
Рис. 1.24. Предварительный прогон программы
Рис. 1.24. Предварительный прогон программы
Чтобы показать в сетках имена партнеров и названия книг, нам нужно расширить исходные НД, добавив к ним подстановочные {lookup) поля из других таблиц. Для этого завершите прогон программы и вернитесь к редактору форм.
Дбойн1э!М щелчком на компоненте Nakls откройте окно редактора полей, щелкните в окне редактора правой кнопкой мыши и в контекстном меню выберите команду Add all fields — окно редактора заполнится списком всех полей таблицы NAKLS. Этот список означает, что теперь для каждого поля НД Nakls создан специальный объект со своими свойствами, методами и событиями. Если вы щелкнете на любом поле в окне редактора полей, то в окне инспектора объектов станут доступными свойства и события объекта-поля. По умолчанию Delphi присваивает объекту-полю имя, полученное сцеплением имени НД и имени поля, так чти теперь в программе окажутся компоненты с именами NaklsNakllD, NaklsNFirm, NaklsNDate и т. Д.
Создание объектов-полей для каждого используемого в программе НД можно считать признаком хорошего стиля программирования, так как они упрощают доступ к данным и дают программисту дополнительные возможности. Например, с помощью свойства DisplayLabel вы можете изменить заголовки соответствующих колонок в сетках отображения данных, а с помощью обработчика события OnGetText — формат отображения данных и т. д. При этом следует помнить, что, если для НД создан хотя бы один объект-поле, соответствующий НД будет содержать значения только тех полей, для которых созданы объекты, и наоборот, если для НД не созданы объекты-поля, он содержит данные из всех нолей соответствующей таблицы.
Напомню, что мы собираемся расширить НД за счет добавления к ним подстановочных полей нз других таблиц. Без объектов-полей в этом случае нам просто не обойтись — это еще один веский довод в пользу их создания.
Создайте объекты-поля н для НД Moves.
Чтобы присоединить к наборам данных поля из других таблиц, нам нужно вначале создать для этих таблиц соответствующие НД: поместите на форму еще три компонента ТТаЫе. В свойстве DatabaseName каждого сошлитесь на локальный псевдоним ААА. Свяжите первый из них с таблицей FIRMS и дайте ему имя таблицы, второй НД — с таблицей BOOKS и дайте компоненту имя Books, третий —с таблицей TYPES и дайте компоненту имя Types (эта таблица содержит расшифровку кода типа накладной). Вновь двойным щелчком на компоненте Nakls откройте окно редактора полей и щелчком правой кнопкой мыши вызовите его контекстное меню. Выберите в меню команду New Field, чтобы открыть окно конструктора нового поля (рис. 1.25).
Рис. 1.25. Окно конструктора нового поля
С 1ЮМ0Щ11Ю конструктора нового поля можно создать в НД новые поля одного из трех типов (тип задается переключателями в группе Field type):
Data — поля содержат произвольные данные;
Calculated — поля содержат вычисляемые данные;
Lookup — поля содержат данные из таблицы подстановки.
Поле первого типа будет отображаться в сетке пустой колонкой, которую можно заполнить в обработчике события OnGetText этого ноля. Вьрпггляемое поле заполняется в обработчике события OnCalcFields набора данных. Для заполнения подстановочного поля данные берутся из нужного поля другого НД.
В строке Name окна конструктора поля введите имя нового поля Firm, раскройте список Туре и выберите для поля тип String, его размер Size установите равным 40, установите переключатель Lookup, раскройте список полей Key Fields и выберите и нем поле NFirm, в списке Dataset выберите НД Firms, в списке Lookup Fields —
ключевое поле FirmID и, наконец, в списке Result Field — поле FName. Закройте окно конструктора щелчком на кнопке ОК.
В БД есть небольшая таблица подстановки TYPES, содержащая два поля: поле TypelD типа Short (первичный ключ) н текстовое поле TName, В поле Type ID указаны возможные значения поля NType (тип накладной) и виде чисел от 0 до 7, а в поле TName — расшифровка смысла типа (покупка книг, продажа книг, обмен и т. д.). Создайте для НД Nakls подстановочное поле с именем Туре текстового типа, длиной 23 символа, выбрав ключевым поле Nrrypet свяжите его с полем Type ID набора данных Types и укажите в качестве результирующего поле TName этого НД.
Для НД Moves создайте три подстановочных ноля с именами Name, Author и Publish, связав их с помощью поля МВоок с НД Books (поле ВоокЮ) и указав в качестве результирующих полей BName, BAuthor, BPublish соответственно. Эти поля нам понадобятся для формирования составного поля Название книги/Автор/Издательство в списке книг. Размеры полей — 75, 30 м 40 символов соответственно.
Создание объектов-столбцов
После того как мы создали подстановочные поля, связанные с ними ключевые поля NaklsNFirm, NaklsNType и MoveMBook стали «лишними»: нс имеет смысла рядом с названием партнера или книги показывать в сетке соответствующий идентификатор. В то же время удалить связанные с ними объекты-поля нельзя, так как НД лишится ключевого поля и подстановочная связь будет разрушена. Конечно, можно для объектов-полей поместить значения False в их свойства Visible и тем самым《спрятать» их и не показывать в сетке. Однако «спрятанные* поля окажутся невидимыми не только в ссткс, но и в любом другом визуализирующем компоненте Delphi (эта компоненты сосредоточены на вкладке Data Controls палитры компонентов), что затруднит редактирование и ввод данных для накладных или списка книг.
Выходом из положения является создание для сетки объектов-столбцов — специальных компонентов, облегающих управление отображением данных. С их помощью можно изменять шрифт и цвет колонок, формировать их заголовки и т. д. Для создания объектов-столбцов нужно вызвать редактор столбцов (рис. 1.26) — для этого перейдите к форме fmNaklstr главного окна и дважды щелкните мышью на сетке DBGridl.
Как и в случае объектов-полей, действует следующее правило: если для сетки не создан ни один объект-столбец, в ней отобра
жаются все не «спрятанные» объекты-поля; н наоборот, если создан хотя бы один объект-столбец, сетка будет отображать дгжные только из обьекгов-столбцов.
Чтобы создать объект-столбец, нужно щелкнуть на кнопке Add New редактора столбцов или нажать клавишу Ins. Выделив (щелчком) появившийся в окне компонент TColumn, мы с помощью инспекгора объектов можем менять его свойства. Раскройте список свойства FieldName и выберите поле NakllD. Раскройте список вложенных свойств сложного свойства Title и в его вложенное свойство Caption введите заголовок столбца — № накл. Поместите в свойство Width ширину колонки 40 (в пикселах экрана). Руководствуясь табл. 1.2, создайте остальные объекты-столбцы для сеток.
Таблица 1.2. Значения свойств FieldName, Caption и Size объектов-столбцов для сеток
FieldName
Caption
Width
Компонент DBGridi
NData
Дата
60
Firm
Партнер
150
Type
Тип накладной
130
NSum
Сумма
60
NPayedSum
Оплата
60
NRetSum
Возврат
60
NCoeff
Коэффициент
35
NRetDate
Срок
60
Компонент DBGrid2
Name
Название книги/Автор/Издательство
500
MQuan
Количество
40
MPrice
Цена
45
Обработчик события OnGetText
Первый столбец в нижней сетке, как это видно из его заголовка, должен содержать текст, составленный из трех подстаново1пшх полей. Чтобы реализовать такое составное поле, воспользуемся обработчиком события OnGetText объекта-поля MoveName. Переадите к форме и вызовите редактор полей для НД Moves. Щелкните на поле Name и откройте вкладку Events в окне инспектора объектов. Дважды щелкнув в правой части строки события OnGetText, наш^шите такой обработчик:
procedure TForml.MoveNameGetText(Sender: TField; var Text: String; DisplayText: Boolean);
begin
Text := MoveName.Value + '/ * +MoveAuthor.Value + ‘/‘ +
MovePublish.Value end;
Событие OnGetText возникает всякий раз, когда программа обращается к полю с целью отображения его содержимого в любом визуализирующем компоненте. Программист в обработчике этого события должен поместить нужную строку в переменную Text. В нашем случае строка получается объединением значений в подстановочных объектах-полях MoveName, MoveAuthor и MovePublish.
Бизнес-правила
Наша простая программа для отображения содержания накладных и связанных с ними списков книг готова. Вы можете ее запустить и просматривать накладные. Не советую вставлять и редактировать записи в накладных и списках книг или удалять их, так как в нашей программе еще не реализован комплекс биз^ес-праеш. Бизнес-правила определяют реакцию системы на добавление, изменение или удаление данных, обеспечивая непротиворечивость и ссылочную целостность БД, Если, например, вы удалите запись из списка книг какой-либо накладной, программа должна автоматически изменить сумму в соответствующей накладной, количество книг на складе и сальдо партнера, в противном случае мы получим недостоверную накладную, неверное количество книг и ошибочное сальдо. Такая реакция программы и реализует бизнес-правило удаления книг.
Бизнес-правила разрабатываются на основе тщательного изучения автоматизируемой области человеческой деятельности. Для файл-серверных систем они обычно реализуются в комплексе обработчиков событий AfterXXXX — BeforeXXXX компонентов-наборов данных TTable или TQuery. В клиент-серверных системах эти де(1ствия, как правило, реализуются на сервере БД с помощью триггеров — процедур, которые автоматически запускаются при вставке, изменении или удалении записей (см. главу 7).
Рассмотрим небольшой пример, реализующий часть бизнес-правил, связанных с удалением данных о накладной. Перед удалением данных о накладной надо удалить список связанных с ней книг, иначе в таблице MOVES появятся записи, которые ссылаются на несуществующую запись в таблнне NAKLS. Наиболее подходящим местом для реализации этого бизнес-правила является обработчик события BeforeDelete набора данных Nakls. Это событие автоматически генерируется перед удалением записи. Перейдите к форме, щелкните на НД Nakls в правой панели модуля и дважды щелкните в строке события BeforeDelete в окне инспектора объектов. Напишите такой обработчик:
procedure TForml.NaklsBeforeDelete(DataSet: TDataSet);
begin
while not Move.EOF do // Пока в списке книг есть хотя бы Move.Delete // одна книга, удаляем ее
end;
В обработчике учитывается то обстоятельство, что НД Moves связан с текущей записью НД Nakls отношением один ко многим и, следовательно, содержит данные только по тем книгам, которые относятся к удаляемой накладной.
Аналогичным образом (с помощью обработчика BeforeDelete НД Move) реализуются бизнсс-правила, связанные с удалением информации о книге из списка книг.
Транзакции
Транзакциями называется группа действий, пер匕водящая БД из одного целостного состояния в другое и выполвдющаяся по принципу «либо все, либо ни одного》. Необходимость в транзакциях вызвана тем, что одновременно в одной сети с одними и теми же данными могут работать несколько пользователей. Транзакции определенным образом изолируются друг от друга. Изоляция разрешает одному пользователю видеть данные, которые уже изменены другим пользователем, и эти изменения подтверждены. В результате достигается высокая степень защиты целостности и непротиворечивости данных.
В описываемых далее технолопшх есть средства управления транзакциями. Управление заключается в том, что с помощью методов соответствующих компонентов серверу БД передается команда Begin (начать транзакцию), после чего в БД делаются те или иные изменения и серверу передается команда Commit (подтвердить изменения). При получении команды Begin сервер создает буфер для изменяемых данных. При получении команды Commit данные из буфера переносятся в таблицы БД. При этом сервер по всем полям либо по ключевым полям ищет записи. в которые следует внести изменения. Если в процессе изменения данных значения полей изменены в рамках конкурирующей транзакции (другим пользователем), сервер не сможет найти запись и отвергнет изменения. При этом в клиентской программе возбуждается исключение. В процессе обработки исключения программа может дать команду Rollback (откатать изменения), которая заставит сервер восстановить состояние БД, бывшее к моменту начала транзакции. В рамках технологии BDE.NET, например, клиентская программа управляет транзакциями с помощью трех методов компонента TDatabase: StartTransaction (начинает транзакцию), Commit (подтверждаеттранзакцию) н Rollback (отменяет все изменения, сделанные с момента старта транзакции):
Databasel.StartTransaction; // Стартуем транзакцию
...// Любые изменения в любых таблицах
try
Databasel .Commit// Пытаемся подтвердить изменения
except
Databasel.Rollback// Откат, есля подтвердить не удалось
end;
ПРИМЕЧАНИЕ
Откат транзакции ликвадирует также все последствия возможного срабатывания триггеров на сервере БД в рамках отмененной транзакции.
Сервер InterBase обеспечивает три уровня изоляции транзакций: Dirty Read, Read Committed и Repeatable Read. Пусть* например, пользователь А решил изменить коэффициент скидки/наценки в накладной продажи книг, а пользователь Б
мгновение спустя пытается вставить в эту же накладную данные о новой книге. Какой коэффициент будет использовать Б, если пользователь А успел его изменить, но еще не подтвердил транзакцию? Это зависит от того, насколько изолирована транзакция Б от любых других транзакций иных пользователе".
При уровне изоляции Dirty Read (буквхпьпый перевод — т'рязное чтение) пользователь Б видит любые изменения в данных, даже если они еще нс подтверждены. В этой ситуации может нарушиться непротиворечивость данных: если пользователь А по каким-либо причинам откатит сделанные нм изменения, пользователь Б никак не узнает об этом, и вставка данных о книге проедет с измененным коэффициентом, хотя в накладной коэффициент останется прежним. В результате сумма в накладной может оказаться неверной (одна из конкурирующих транзакций, как описано далее, может быть отвергнута сервером, поэтому сумма, возможно, будет верной). Уровень Dirty Read、фактически, не изолирует транзакции. Только этот уровень возможен для фанл-серверлых БД, вот почему в СУБД этого типа транзакции используются крайне редко.
Уровень Read Committed (чтение подтверждений) разрешает транзакции видеть только подтвержденные изменения. В описанпоЛ выше ситуации пользователь Б получит нак.падную с прежним коэффициентом. Однако если в ходе транзакции он еще раз прочитает накладную, в которую пользователь А успел внести и подтвердить изменение коэффициента, Б увнднт эти изменения. Этот уровень рекомендуется для клиент-серверных БД.
Для клиент-серверных БД возможен также уровень Repeatable Read (повторяющееся чтение). На этом уровне изоляции также читаются только подтвержденные изменения, однако раз прочитанная запись помещается в локальный буфер н повторно читается из этого буфера, то есть повторное чтение не позволит увпдепэ изменений, внесенных другим пользователем, даже если эти изменения подтверждены. Успех или неуспех транзакции во многом зависит от того, по каким столбцам сервер ищет в таблице запись, чтобы внести в нее изменения. Если в нашем примере пользователь А первым подтвердит изменения, а у пользователя Б транзакция настроена на поиск записи по всем полям, его транзакция будет отвергнута, так как в этом случае сервер ищет запись, в которой все столбцы имеют те значения, которые были к моменту старта транзакции Б. Если транзакция настроена на поиск записи, у которой ключевые столбщ>1 и столбцы с изменениями остались прежними, транзакция Б пройдет успешно, так как оба пользователя изменяли разные столбцы, и может быть нарушена непр(ггиворсчивость данных. Еще хуже защищаются данные в случае, если транзакция требует от сервера искать запись только по ключевым столбцам.
Таким образом, уровень изоляции Read Committed в сочетании с настройкой транзакщя! на поиск записей по всем полям в максимальной степени защищает данные от искажения в условиях многопользовательской работы.
4喫
Технология ADO.NET 陵
Технолоптя AD0.NET является базовой технологией для работы с БД на платформе .NET Framework. Она обслуживает серверы MS SQL Server и Oracle, а также серверные н файл-серверные БД, доступные с помощью драйверов ODBC.
На рис. 2.1 представлены основные компоненты технологии ADO.NET.
Здесь база данных — реальная серверная БД или XML-файл; связь — компоненты, обеспечивающие связь с данными; адаптеры —компоненты, форми|)ующие SQL-запросы к серверу БД или драйверу ODBC для получения и/или модификации данных; набор данных — компонент, обеспечивающий виртуальное хранилище для полученных и, возможно, измененных данных; визуализация — компоненты, обеспечивающие внзугшьное предстанление данных.Характерным для технологии является нал)гчие промежуточного буфера — набора данных. Набор данных (класс DataSet) предоставляет удобный механизм чтения и обновления данных и инкапсулирует п себе, в общем случае, множество таблиц и связей между ними. Набор данных (НД) не связан напрямую с источником данных. Это — виртуальный объект. Таблицы, с которыми он работает, могут быть загружены из источника данных или созданы динамически. После загрузки данных в DataSet эти данные могут быть изменены без внесения измененкй в источник данных. Зафиксировать изменения в БД можно только после обращения к методу Update набора данных.Для визуализации данных в Delphi разработан единственный объект класса DataGrid (категория Data Controls).Здесь база данных — реальная серверная БД или XML-файл; связь — компоненты, обеспечивающие связь с данными; адаптеры —компоненты, форми|)ующие SQL-запросы к серверу БД или драйверу ODBC для получения и/или модификации данных; набор данных — компонент, обеспечивающий виртуальное хранилище для полученных и, возможно, измененных данных; визуализация — компоненты, обеспечивающие внзугшьное предстанление данных.Характерным для технологии является нал)гчие промежуточного буфера — набора данных. Набор данных (класс DataSet) предоставляет удобный механизм чтения и обновления данных и инкапсулирует п себе, в общем случае, множество таблиц и связей между ними. Набор данных (НД) не связан напрямую с источником данных. Это — виртуальный объект. Таблицы, с которыми он работает, могут быть загружены из источника данных или созданы динамически. После загрузки данных в DataSet эти данные могут быть изменены без внесения измененкй в источник данных. Зафиксировать изменения в БД можно только после обращения к методу Update набора данных.Для визуализации данных в Delphi разработан единственный объект класса DataGrid (категория Data Controls).八v八vСвязьСвязь_Л&ФЁЛЧ<_Л&ФЁЛЧ<VVНабор данныхНабор данныхВизуализацияВизуализацияРис 2.1. Основныекомпонентытехнологии ADO.NETРис 2.1. Основныекомпонентытехнологии ADO.NET
Здесь база данных — реальная серверная БД или XML-файл; связь — компоненты, обеспечивающие связь с данными; адаптеры —компоненты, форми|)ующие SQL-запросы к серверу БД или драйверу ODBC для получения и/или модификации данных; набор данных — компонент, обеспечивающий виртуальное хранилище для полученных и, возможно, измененных данных; визуализация — компоненты, обеспечивающие внзугшьное предстанление данных.
Характерным для технологии является нал)гчие промежуточного буфера — набора данных. Набор данных (класс DataSet) предоставляет удобный механизм чтения и обновления данных и инкапсулирует п себе, в общем случае, множество таблиц и связей между ними. Набор данных (НД) не связан напрямую с источником данных. Это — виртуальный объект. Таблицы, с которыми он работает, могут быть загружены из источника данных или созданы динамически. После загрузки данных в DataSet эти данные могут быть изменены без внесения измененкй в источник данных. Зафиксировать изменения в БД можно только после обращения к методу Update набора данных.
Для визуализации данных в Delphi разработан единственный объект класса DataGrid (категория Data Controls).
Здесь база данных — реальная серверная БД или XML-файл; связь — компоненты, обеспечивающие связь с данными; адаптеры —компоненты, форми|)ующие SQL-запросы к серверу БД или драйверу ODBC для получения и/или модификации данных; набор данных — компонент, обеспечивающий виртуальное хранилище для полученных и, возможно, измененных данных; визуализация — компоненты, обеспечивающие внзугшьное предстанление данных.
Характерным для технологии является нал)гчие промежуточного буфера — набора данных. Набор данных (класс DataSet) предоставляет удобный механизм чтения и обновления данных и инкапсулирует п себе, в общем случае, множество таблиц и связей между ними. Набор данных (НД) не связан напрямую с источником данных. Это — виртуальный объект. Таблицы, с которыми он работает, могут быть загружены из источника данных или созданы динамически. После загрузки данных в DataSet эти данные могут быть изменены без внесения измененкй в источник данных. Зафиксировать изменения в БД можно только после обращения к методу Update набора данных.
Для визуализации данных в Delphi разработан единственный объект класса DataGrid (категория Data Controls).
八
v
八
v
Связь
Связь
_Л&ФЁЛЧ<
_Л&ФЁЛЧ<
V
V
Набор данных
Набор данных
Визуализация
Визуализация
Рис 2.1. Основныекомпонентытехнологии ADO.NET
Рис 2.1. Основныекомпонентытехнологии ADO.NET
Он способен предоставлять данные в табличном виде (в виде сетки). Замечательной особенностью базового класса System. Control является предусмотренное в нем свойство DataBindings, предназначенное для ссылки на связанные с объектом данные. Таким образом, любой визуальный компонент WinForms способен визуализировать данные, получаемые из DataSet.
Классы ADO.NET
Все классы ADO.NET входят в систему общих типов CTS платформы .NET Framework и условно делятся на требующие соединения с БД (соединенные классы) и не требующие соединения (разъединенные классы) (рис. 2.2).
Соединенные классыСоединенные классыКласс мостовогоКласс мостовогоРазъединенные клессыРазъединенные клессыРис. 2.2. Классы ADO.NETРис. 2.2. Классы ADO.NET
Соединенные классы
Соединенные классы
Класс мостового
Класс мостового
Разъединенные клессы
Разъединенные клессы
Рис. 2.2. Классы ADO.NET
Рис. 2.2. Классы ADO.NET
Соединенные классы
Соединенные классы могут реализовать свою функциональность только при установленном соединенш! с БД. Некоторые из них перечислены в табл. 2.1.
Таблица 2.1. Соединенные классы ADO.NET
Класс
Описание
Connect: 1 и 门
Содержит информацию об источнике данных, включая его расположение, имя и другие параметры, специфические для определенлого хранилища данных. Класс Connection — это канал, через который другие классы получают доступ к данным. Он также способен управлять транзакциями
Command
Позволяет применить к данным нужную SQL-команду, в том числе SELECT, все команды языка DLL, обращение к хранимой процедуре и т. д.
Класс
Описание
DataReader
Обеспечивает однонаправленное (только вперед) чтение данных. Обычно используется совместно с классом DataAdapter
DataAdapter
Мостовой класс (bridging class) — реализует связь между разъединенными л соединенными классами. На первом этапе он переносит данные из соединенных в разъединенные классы, предоставляя пользователю возможность манипулировать ими. На втором этапе, наоборот, переносит измененные данные из разъединенных в соединенные классы, внося необходимые изменения в реа.пьные таблицы баз данных (ТБД)
Parameter
Содержит параметры для реа/шзапии параметрического запроса к БД
Transaction
Позволяет объединить группу последова7'ельных обращений к БД в единый блок, выполняемый по принципу «либо все, либо ни одного». Если в ходе выполнения какой-либо команды возникнет ошибка, позволяет откатить (rollback) все ранее сделанные в пределах текущей транзакции изменения. Если ошибка не возникает, подтверждает (commit) все изменения, сделанные данной транзакцией
Разъединенные классы
В табл. 2.2 представлены разъединенные классы AD0.NET. Функциональность этих классов не зависит от текущего соединения с источником данных.
Таблица 2.2. Разъединенные классы ADO.NET
Класс
Описание
DataSet
Класс DataSet реализует реляционную БД в оперативной памяти, которой можно управлять, полностью отключив ее от физического хранилища данных
DataTableCollection
Коллекция таблиц данных в наборе данных. Позволяет получить доступ к конкретной таблице
DataTable
Содержит данные в виде таблицы. Столбцы (columns) таблицы есть аналог полей (fields) ТБД, а строки (гош) — аналог записей (records) ТБД
DataRelation
Инкапсулирует реляционные связи (relation) между таблицами данных DataTable. Класс DataSet имеет свойство DataRelationCollection, содержащее коллекцию объектов DataRelation
DataColumn
Хранит информацию о структуре столбца таблицы данных. Сюда относится информация о типе данных, доступности, способе вычисления значений и т. п. Этот класс доступен в свойстве DataColumnCoollection класса DataSet
продолжение 少
Таблица 2.2 (продолжение)
Класс
Описание
DataRow
Предоставляет свойства и мегоды для редактиронания данных в отдельных столбцах таблицы. Класс поддерживается коллекцией DataRowCollection
Constraint
Содержит ограничения на возможность изменения данных в разъединенной БД (ограничения внешних ключей, реалн- зац!1я каскадных изменений и т. п.). Поддерж11вается коллекцией Constraintcollection
DataView
Позволяет предоставлять данные в DataSet нужным способом за счет их фильтрации, сортировки и подобных действий
Провайдеры данных ADO.NET
Провайдеры данных ADO.NET предоставляют соединенным классам конкретные механизмы доступа к тем или иным хранилищам данных. Обычно они оперируют низкоуровневыми функциями (API-фупкциями) промышленных серверов БД или аналогичными средствами других источников данных.
Провайдеры Microsoft
Корпорация Microsoft укомплектовала платформу .NET Framework всрснн 1.1 четырьмя провайдерами, описанными в табл. 23.
Таблица 2.3. Провайдеры данных платформы .NET Framework версии 1.1
Провайдер
Описание
SQL Server
Обеспечивает доступ к серверу MS SQL Server версии 7.0 и выше. Классы провайдера данных расположены в пространстве имен System. SqlClient
OLE DL
Обеспечивает доступ к источникам данных, поддерживающим технологию OLE DB. Классы провайдера расположены в нростраистне нмен System.Data.OleDb
ODBC
Обеспечивает доступ к источникам данных с помощью технологии ODBC (Open Database Connection — открытое соединение с базой данных). Классы провайдера расположены в пространстве имев System. Data.odbc
Oracle
Обеспечивает доступ к промышленному серверу Oracle версий 8.i и 8.1.7. Классы провайдера расположены в пространстве имен System.Data. OracleClient
ПРИМЕЧАНИЕ
Провайдеры OLE DB, Oracle и ODBC не устанавливаются по умолчанию, но входят в комплект поставки Delphi 2005. Для их установки следует выбрать команду Component ► Installed .NET Components и в открывшемся окне установить флажки рядом с классами OdbcXXXY, OleDbXXXX и OracleXXXX. Эти компоненты, как и компоненты провайдера SQL Server, появятся в категории Data Components палитры компонентов Delphi.
Провайдер Borland
В состав инструментальных средств Delphi 2005 включен провайдер BDP (Borland Data Provider — провайдер данных корпорации Borland). Это — единственный провайдер, открывающий доступ к нескольким типам источников данных, в том числе к базам данных промышленных серверов InterBase, Oracle, IBM DB2, MS SQL Server и Sybase, а также к СУБД Access, входящей в состав MS Office Professional. Компоненты провайдера расположены в категории Borland Data Provider, а классы провайдера определены в пространстве имен Bor land. Dat a. Provider.
Описанные ранее соединенные классы Connection, Command и др. в реализации провайдеров имеют соответствующий префикс. Для примера в табл. 2.4 показано соответствие имен классов для разных провайдеров.
Таблица 2.4, Соответствие имен классов провайдеров
Базовый класс
SQL Server
OLE DB
BDP
Connection
SqlConnection
OleDbConnection
BdpConnection
Command
SqlCommand
OleDbCommand
BdpCommand
DaLaAdapter
SqlDataAdapter
OleDbDataAdapter
BdpDataAdapter
DataReader
SqlDataReader
OleDbDataReader
BdpDataReader
Transaction
SqlTransaction
OleDbTransaction
BdpTransaction
Все соединенные классы реализуют общие базовые интерфейсы, такие как IDbConnection» IDbCommand н т. д., поэтому в функциональном плане, а также в большинстве своих свойстй, методой и событий они идентичны. Далее в разделах этой главы описываются детали работы с провайдером BDP, так как он един- ственньп!, поддерживающий «родные» для Delphi базы данных сервера InterBase (этот сервер так же, как и Delphi, разработан корпорацией Borland). Однако этот материал в полной мере применим и к любому другому провайдеру.
Простой пример
Прежде чем начать детальный анализ многочисленных объектов технологии ADO.NET, выполним простой пример, который проиллюстрирует основные приемы работы с указанными ранее объектами. В примере (проект Source\Ch02\Nakls\ Nakls.dpr) будет отображаться реляционная связь между таблицами NAKLS и MOVES БД «Книголюб». В отличие от примера, приведенного в главе 1, в этом примере используется серверный вариант БД.
Конструирование проекта
Начните новый проект WinForms (File ► New ► Windows Forms Application — Delphi for .NET) и подготовьте устапойлсние связи с БД «Книголюб». Для этого в окне менеджера проектов щелкните на вкладке, помеченной значком 趙,чтобы вызвать окно Data Explorer (рис. 2.3).
g Provideisg Provideis士:写 DB2 田•写 Interbase 扌写MSAccess 中豆MSSQL :+ ® Oracle :*■序 SYBASE士:写 DB2 田•写 Interbase 扌写MSAccess 中豆MSSQL :+ ® Oracle :*■序 SYBASEjU ±11jU ±11Рис. 2.3. ОкноData ExplorerРис. 2.3. ОкноData Explorer『:” Password?.:;; UswName,日Г\m…卜衿、出中*々歹•:: CommitRetain^■:\ LoginPrompl, QuoteObiec"S RoleNamej SeiveiChaiSet SQLDialectj ■ Trarwaciionlsolation.卜 WaitOnLockt蹿濺發套縱翁磁然発专:* Assembly『:” Password?.:;; UswName,日Г\m…卜衿、出中*々歹•:: CommitRetain^■:\ LoginPrompl, QuoteObiec"S RoleNamej SeiveiChaiSet SQLDialectj ■ Trarwaciionlsolation.卜 WaitOnLockt蹿濺發套縱翁磁然発专:* Assemblymasterkey $y*dbamasterkey $y*dbaFalseFalse Fake myfoteFalseFalse Fake myfoteЭReadCommittedFalseЭReadCommittedFalseBoiland. Data.lnlefba*e.Ve<»ion>2.0.0:Boiland. Data.lnlefba*e.Ve<»ion>2.0.0:
g Provideis
g Provideis
士:写 DB2 田•写 Interbase 扌写MSAccess 中豆MSSQL :+ ® Oracle :*■序 SYBASE
士:写 DB2 田•写 Interbase 扌写MSAccess 中豆MSSQL :+ ® Oracle :*■序 SYBASE
jU ±11
jU ±11
Рис. 2.3. Окно
Data Explorer
Рис. 2.3. Окно
Data Explorer
『:” Password
?.:;; UswName
,日Г\m…卜衿、出中*々
歹•:: CommitRetain
^■:\ LoginPrompl
, QuoteObiec"
S RoleName
j SeiveiChaiSet SQLDialect
j ■ Trarwaciionlsolation
.卜 WaitOnLockt
蹿濺發套縱翁磁然発专
:* Assembly
『:” Password
?.:;; UswName
,日Г\m…卜衿、出中*々
歹•:: CommitRetain
^■:\ LoginPrompl
, QuoteObiec"
S RoleName
j SeiveiChaiSet SQLDialect
j ■ Trarwaciionlsolation
.卜 WaitOnLockt
蹿濺發套縱翁磁然発专
:* Assembly
masterkey $y*dba
masterkey $y*dba
False
False Fake myfote
False
False Fake myfote
Э
ReadCommitted
False
Э
ReadCommitted
False
Boiland. Data.lnlefba*e.Ve<»ion>2.0.0:
Boiland. Data.lnlefba*e.Ve<»ion>2.0.0:
62 Глава 2 • Технология ADO.NET
В этом окне демонстрируются соединения со всеми шестью возможными источниками данных. Раскройте узел Interbase. По умолчанию в нем определено соединение IBConnl с демонстрационной БД, поставляемой вместе с сервером InterBase. Добавим новое соединение. Щелкните на узле npaBoii кноп- Koii мыши и в контекстном меню выберите команду Add New Connection. В новом окне задайте имя соединения 1ВСопп2 и щелкните па кнопке ОК. В окне редактора соединения (рис. 2.4) все свойства можно оставить по умолчанию, кроме cnoiicTBa Database: ии'лкните на кнопке в строке этого свойства и установите ссылку на файл C:\BiblData\IB_Bibl.gdb (разумеется, этот файл следует предварительно загрузить с caiiTa www.piter.com). Закрой те окно редактора соединения щелчком на кнопке ОК.
CartnecUwSeU 谏
白 <W«N■他#*■ • . . ;■ -、;: :': ?
;彫顧% /fc^XKS^ C \BlblDat-MB_BIBLGDB
22
2
2
Рис. 2.4. Окно редактора соединения
ПРИМЕЧАНИЕ
В технологии ASP.NET, обсуждаемой в части И этой книги* при работе с БД InterBase и соединении сзепуст укаэыпать правильное DNS-имя1 узла сети, па котором запущен сервер InterBase. Если сервер запущен на вашем компьютере, ссылку следует отредактировать следующим образом: localhost :С : \BiblData\IB_B19L.gdb.
DNS (Domain Name Sysleni — система ломенных имен) — это, по сущсстоу, раенреде.ичг мая база данных, позволяющая нс имени определить меслоиахождсние узла сети.
Простой пример 63
Теперь раскройте новый узел соединения 1ВСопп2, затем — узел Tables. Разыщите в списке узла таблицу NAKLS и перетащите (Drag&Drop) ее на пустую форму. В результате к проекту будут добавлены компоненты BdpConnect ionl и BdpDataAdapterl, причем первый будет настроен на связь с файлом БД IB_BIBL*gdb, а второй — на отображение и модификацию главной таблицы NAKLS 8Toii БД.
Добавьте к Лроекту еще один адаптер BdpDataAdapter2 (категория Borland Data Provider) “ щелчком правой кнопкой мыши вызовите его контекстное меню, в котором выберите команду Configure Data Adapter. В окис конфшурирования (рис. 2.5) выберите таблицу MOVES и щелкните на кнопке Generate SQL
C^nmand J Preview Data | OdtaSel |BOOKSCRED:DEBC^nmand J Preview Data | OdtaSel |BOOKSCRED:DEBFIRMSNAKLS■ PAYMENTS'TYPESFIRMSNAKLS■ PAYMENTS'TYPES^pwecticn |S^EJ^^S?T"“ SQL Commands . ~;:〜♦二i 勺 /d犷 Update扌 R (rnirt“ Mele^pwecticn |S^EJ^^S?T"“ SQL Commands . ~;:〜♦二i 勺 /d犷 Update扌 R (rnirt“ Melegenerate SQLgenerate SQL广 SimM广 SimMSetect :| Update | : ln$«T Detete |Setect :| Update | : ln$«T Detete |MOVEID NAKUD MBOOK MQUAN MPRICEMOVEID NAKUD MBOOK MQUAN MPRICEselect моуею7йак1ЖмвЖ MPRICE FROM MOVESselect моуею7йак1ЖмвЖ MPRICE FROM MOVES
C^nmand J Preview Data | OdtaSel |
BOOKS
CRED
:DEB
C^nmand J Preview Data | OdtaSel |
BOOKS
CRED
:DEB
FIRMS
NAKLS
■ PAYMENTS
'TYPES
FIRMS
NAKLS
■ PAYMENTS
'TYPES
^pwecticn |S^EJ^^S?T"
“ SQL Commands . ~;:〜♦二
i 勺 /d犷 Update
扌 R (rnirt“ Mele
^pwecticn |S^EJ^^S?T"
“ SQL Commands . ~;:〜♦二
i 勺 /d犷 Update
扌 R (rnirt“ Mele
generate SQL
generate SQL
广 SimM
广 SimM
Setect :| Update | : ln$«T Detete |
Setect :| Update | : ln$«T Detete |
MOVEID NAKUD MBOOK MQUAN MPRICE
MOVEID NAKUD MBOOK MQUAN MPRICE
select моуею7йак1ЖмвЖ MPRICE FROM MOVES
select моуею7йак1ЖмвЖ MPRICE FROM MOVES
OKOKCancel
OK
OK
Рис. 2.5. Конфигурирование адаптера для таблицы MOVES
В результате адаптер BdpDataAdapter2 будет настроен на отображение и модификацию детальной таблицы MOVES.
Добавьте к проекту компонент DataSet (категория Data Controls). Поместите на форму сетку DataGrid (категория Data Controls или Crystal Reports) со значением Client свойства Dock.
Настройка набора данных
Настройка набора данных затспючается в указании хранящихся в нем данных и связей между ними. Для этого в компоненте определены два свойства-коллекции: Tables и Relations. Первое задает таблицы (точнее, результаты SQL-запросов) и их поля, второе — реляционные связи между ними.
Для связи НД с нужными таблицами поместите в свойства DataSet адаптеров ссылку на компонент DataSetl и откройте их (поместите значение True в их свойства Ас匸ive)L
Теперь необходимо определить реляционную связь между таблицами. Раскройте редактор свойства Relation компонента DataSetl и щелкните на кнопке Add. Никое окно содержит имя реляционной связи (Relationl), главной таблицы NAKLS (список Parent table) и детальной таблицы MOVES (список Child table).
ПРИМЕЧАНИЕ
Эти имена определяются порядком открытия адаптеров. Если первым вы открыли адшгер BdpDataAdapter2, имена поменяются местами. В этом случае с помощью списков установите правильные имена.
Поскольку имя реляционной связи (Relationl) будет отображаться в окне работающей программы, имеет смысл его изменить: введите в верхней строке имя Книги по накладной. Под списками располагается таблица Columns, предназначенная для выбора ключевых полей. Щелкните в столбце Key Columns, раскройте список и выберите ключевое поле NAKLID. Затем точно так же выберите это поле в столбце Foreign Key Columns (рис. 2.6).
Speaf^ the My* that rel^e tables in your dataset ,Earent table:£hid table:[naklF'3 {moves ~3Speaf^ the My* that rel^e tables in your dataset ,Earent table:£hid table:[naklF'3 {moves ~3
Speaf^ the My* that rel^e tables in your dataset ,
Earent table:£hid table:
[naklF'3 {moves ~3
Speaf^ the My* that rel^e tables in your dataset ,
Earent table:£hid table:
[naklF'3 {moves ~3
匾噺薪下:U:「;产三 zД 闷函^M 侬研Г: E Lhj
…naSjd―
Рис. 2.6. Окно установления реляционной связиРис. 2.6. Окно установления реляционной связиЧтобы избежать ненужно" путаницы, сначала откройте адаптер BdpDacaAdapter 1 и уж затем — BdpDataAdapcer2. Ссылки на таблицы появляются в коллекции Tables набора данных ио мере открытия адаптеров. При установлении реляционной связи НД снптасг первую таблицу в 9Toii коллекции главной, а вторую — детальной.Чтобы избежать ненужно" путаницы, сначала откройте адаптер BdpDacaAdapter 1 и уж затем — BdpDataAdapcer2. Ссылки на таблицы появляются в коллекции Tables набора данных ио мере открытия адаптеров. При установлении реляционной связи НД снптасг первую таблицу в 9Toii коллекции главной, а вторую — детальной.
Рис. 2.6. Окно установления реляционной связи
Рис. 2.6. Окно установления реляционной связи
Чтобы избежать ненужно" путаницы, сначала откройте адаптер BdpDacaAdapter 1 и уж затем — BdpDataAdapcer2. Ссылки на таблицы появляются в коллекции Tables набора данных ио мере открытия адаптеров. При установлении реляционной связи НД снптасг первую таблицу в 9Toii коллекции главной, а вторую — детальной.
Чтобы избежать ненужно" путаницы, сначала откройте адаптер BdpDacaAdapter 1 и уж затем — BdpDataAdapcer2. Ссылки на таблицы появляются в коллекции Tables набора данных ио мере открытия адаптеров. При установлении реляционной связи НД снптасг первую таблицу в 9Toii коллекции главной, а вторую — детальной.
ПРИМЕЧАНИЕ
В технологии ADO.NET первичный ключ главной таблицы и нторичньв! к」н)ч детальной таблицы должны содержать данные строго пд>шакового типа л иметь одинаковые пазвания.
Прогон программы
Осталось настроить компонент DataGrid на отображение данных нз главной таблицы. Раскройте список свойства Datasource компонента GataGrid и выберите в нем главную таблицу DataTablel.
Особенностью технологии является то обстоятельство, что обычно набор данных заполняется по требованию профаммы. Для этого □ интерфейсе формы zcpkuh предусмотреть специальную кнопку или использовать обработчик события Load формы. Я предпочитаю конструктор формы. Сразу за обращением к процедуре InitializeComponent напишите две строки для заполнения двух таблиц:
constructor TWinForm.Create;
begin
inherited Create;
//
// Required for Windows Form Designer support
//
Initiali zeComponen t;
// TODO: Add any constructor code 占fte丁 InizializсСотрол£-nr um/l //
BdpDataAdapterl.Fill(DataTablel);// Заполняем 7-储 таблицу
BdpDataAdapter2 .Fill (Da taTable2 ) ;/ / Заполняем 2-心 丁о亡,口汇口.『
BdpConnec t ion1.Close;
end;
После запуска программы появится окно, показанное на рис. 2.7.
寳寸
+、EW ・iw¥,Wz ~ r.
『МАЮЮ
^' TNDATE 亠
NRETDA1E
30.042000 '
]_NTYPE_ —
厂
;NCOEFF
1
炉少. 550
pPAYEDSP—』
此2
01.03.2000
31.03.2000
7
1,04
335,919
335.919j
ЕВ'З
01.012000
10.04.2000
1
0.75
45337,5
o5
田%
01.03.20СЮ
01.03.2000
4
1
6782
0-:
©5
01 03 2(ХЮ
02 03 2000
7
1,04
234
234
01.03.20СЮ
30.04.2000
1
1.1
2323,699
0
Ш 7
01.03.2000
30.04 2000
0
.1
155610
60201.652
屈8
01.03.2000
31.03.2000
1
0.75
2767,5
0
田卩
01.03.2000
31.03.2000
1
075
855
0
由几
;ОТ .03.2000
30.04.2000
0
1
155610
0
01.03.2000
31.03.2000
1
0,75
264E0
0
由12
01.03 2000
01.03.2000
3
1
2Э58.9
0j
6河13
оюз.госю
31.03.2000
0
1
6487.5
4":.
Рис. 2.7. Окно без отображения детальных данных
3 Зак 449
В этом окне не отображаются детальные данные, но каждая запись в таблице снабжается значком со знаком + (плюс), щелчок на котором подготавливает окно к показу детальных записей: правей и ниже значка появляется надпись Книги по накладной (название реляционной связи); после щелчка на надписи в окне демонстрируются главная запись и все связанные с ней детальные записи (рис. 2.8).
Рис. 2.8. Отображение детальных данных
Чтобы вернуть окно к первоначальному виду, нужно щелкнуть на кнопке с направленной влево маленькой стрелкой в правом верхнем углу окна и закрыть ])аскрытый узел.
Применение объекта Connection
Объекты класса Connection осуществляют соединение приложения ADO.NET с источниками данных. Несмотря на то что для каждого провайдера данных разработан свой класс Connection, эти классы решают общие задачи, такие как аутентификация пользователей, работа с сетями, идентификация баз данных, буферизация соединений и обработка транзакций.
Класс Connection реализует интерфейс IDbConnection, определенный в пространстве имен System. Data. Свойства и методы интерфейса перечислены и табл. 2.5 и 2.6.
Таблица 2.5. Свойства интерфейса IDbConnection
СвойствоОписание
property Connectionstring: String; Содержит параметры соединения в формате пар «имя—значением
property ConnectionTimeout:
Определяет период времени (в секундах),
Integer;
в пределах которого должно установиться соединение. По умолчанию — 15 с
Применение объекта Connection
67
Свойство
Описание
property Database; String;
property State: Connectionstate;
Содержит имя текущей базы данных
Содержит состояние соединения: Close или Орел
Таблица 2.6. Методы интерфейса IDbConnection
Метод
Описание
function BeginTransaction:
Инициализирует начало очередной тран-
iDbTransaction;
закции
procedure ChangeDatabase (conet
DatabaseName: String);
Изменяет текущее имя базы данных
procedure Close;
Закрывает соединение с источником данных
function CreateCcunmand TDbCornmand;
Создает объект команды (то есть объект, реализующий шперфейс iDbCommand), связанный с текущим соединением
procedure Open;
Открывает соединение с источником данных
Задание значения свойства Connectionstring
Свойство Connectionstring имеют все провайдеры данных, однако у каждого из них свой набор параметров, которые должно содержать это свойство. Обычно это свойство устанавливается с помощью редактора соединения, в котором» как правило, необходимо указать базу данных, имя пользователя и пароль. Все прочие параметры следует оставить без изменения.
Если по каким-либо причинам необходимо программное указание значения свойства Connectionstring, рекомендую на этапе конструирования создать нужное соединение и запомнить строку Connectionstring. Например:
constructor TWinForml.Create;
/ / Этот констуктор создает и тестирует соединение с БД иКниголюбн var
Conn: BdpConnect ion;
const
ConnStr = 'assembly=Borland.Data.Interbase, Version=2.0.0.0, 1 +
1Culture=neutral, PublicKeyToken=91d62ebb5b0dlblb;* + 'database=C:\BiblData\IB_BIBL1251.gdb;username=sysdba;' + *password=masterkey';// Строка соединения
begin
inherited Create;
InitializeComponent;
Conn := BdpConnection.Create(ConnStr);// Создаем соединение
try
Conn.Open;// Открываем его...
if Conn.State = ConnectionState.Open then // и тестируем
Text := 1 OK';
finally
Conn. С lose;/ / Затсрываем соединение
end;
end;
В приведенном примере строка Connectionstring устанавливает связь с БД «Книголюб» (сервер InterBase). В ней помимо маршрута доступа к файлу БД, имени пользователя и пароля следует указать параметры сборки (параметр Assembly). В примере удалены некоторые параметры (vendorclient, provider), которые присутствуют в строке, создаваемой средствами IDE, но которые, как показывает практика, излишни. Прл подготовке примера я создал соединение средствами IDE, перенес его строку Connectionstring в константу CormStr конструктора формы и методом проб н ошибок выяснил, что указанные параметры можно опустить. При работе с другими источниками данных провайдера BDP или при работе с другими провайдераш! конкретный состав строки соединения следует подбирать подобным образом (а проще — ничего не менять в этой строке).
Работа с транзакциями
Следующий метод стартует транзакцию:
function BeginTransaction(Level: IsolationLevel;
TransName: String): BdpTransaction
Параметр Level задает уровень нзоляцнм транзакций и может принимать одно из следующих значений:
ReadCommited — данные блокируются на момент их чтения, но могут изменяться другими пользователями до окончания текущей транзакции;
DirtyRead — нет изоляции транзакций;
RepeatableRead — данные блокируются и не могут изменяться другими пользователями до окончания текущей транзакции.
Параметр TransName определяет имя транзакции. Функция возвращает объект класса BdpTransасtion, у которого есть методы Commit (подтверждает транзакцию) и Rollback (откатывает транзакцию).
ПРИМЕЧАНИЕ
В заключительном разделе этой главы описывается пример использования транзакций.
Получение метаданных
Получить метаданные текущего соединения можно с помощью такого метода:
function GetMetedata: ISQLMetadata;
Метод возвращает интерфейс ISQLMetadata, с помощью которого можно получить такие данные, как доступные соединению таблицы, их 1шдексы и поля. Интерфейс не имеет свойств. Его методы представлены в табл. 2.7.
Таблица 2.7. Методы интерфейса ISQLMetadata
Метод
Описание
function GetColumns (szTableName, saColumnName: String; eCol: ColumnType)DataTable;
Возвращает объект DataTable. содержащий поля таблицы
function Getlndices (szTableName:
String; ulndexType: IndexType): DataTable;
Возвращает объект DataTable, содержащий индексы таблицы
function GetProcedureParams (scTableName, szParamName: String): DataTable;
Возвращает объект DataTable, содержащий параметры хранимой процедур1>1
function GetProcedures( szProcName:
String; eProc: ProcTypeH DataTable;
Возвращает объект DataTable, содержащий перечень хранимых процедур
procedure GetProperty(eMetaProp:
MetaDataProps; out Value: Object);
Возвращает требуемый параметр метаданных
function GetTables (szTableName:
String; eTable: TableType)DataTable;
Возвра1лает объект DataTable, содержащий список всех таблиц заданного типа или имени
procedure Setproperty(eMetaProp: MetaDataProps; Value: Object);
Устанавливает нужное свойство метаданных
Компонент имеет единственное событие statechange, обработчик которого получает два параметра: текущее состояние компонента и его исходное состояние.
События соединения
Класс BdpConnection имеет единственное событие statechange, которое возникает при изменении его свойства State. Обработчик события в свойствах Currentstate и Original State объекта е получает новое и исходное состояния соединения соответственно. Другие провайдеры имеют свой набор событий. Например, класс SqlConnection помимо события Statechange имеет еще событие InfoMessage, которое возникает, когда сервер БД передает информационное сообщение или предупреждение.
Применение объектов Command и DataReader
Объект BdpCommand используется для передачи серверу БД какой-либо команды языка SQL. Результат может не содержать данных вообще, содержать агрегатное значение или содержать множество данных, возвращаемых командой SELECT.
Класс BdpCommand реализует интерфейс IDbCommand, свойства н методы которого перечислены в табл. 2.8 и 2.9.
Таблица 2.8. Свойства интерфейса IDbCommand
Свойство
Описание
property ConiniandText: String;
Содержит текст команды
property CommandTimeOut: Integer;
Определяет максимальный период выполнения команды в секундах
property ComandType: CommandType ;
Тип команды: StoredProcedure — обращение к хракимой процедуре; TableDirect - обращение к таблице; Text — SQL-команда
property Connection: IDbConnection;
Ссылка на объект Connection
property Parameters:
Коллекция параметров для параметриче-
IDataParameterCollection;
с кого запроса
property Transaction:
Транзакция, в рамках которой будет выпол-
IDbTransatcion;
няться команда
property UpdateRowSource:
Определяет, как именно результат выпол*
UpdateRowSource;
нения команды применяется к редактируемой записи
Таблица 2.9. Методы интерфейса IDbCommand
Метод
Описание
procedure Cancel ;
Пытается прекратить выполнение команды
function CreateParameter;
Создает экземпляр класса IDbParametr
function ExecuteNonQuery: Integer;
Выполняет команду и возвращает количество затронутых ею записей
function ExequteReader:
Выполняет команду и возвращает экземп-
IDataReader;
ляр объекта IDataReader
function ExecuteScalar: Object;
Выполняет запрос и возвращает первый столбец первой записи
procedure Prepare;
Подготавливает обращение к хранимой процедуре
Объект, реализующий интерфейс IDbCommand, выполняет команды при помощи одаого из трех методов: Execut eNonQuery, Exe cut eReader или ExecuteScalar. Специальные реализации интерфейса могут быть дополнены другими методами. Например, класс SqlCommand обладает методом Execut eXMLReader, позволяющим обратиться к данным, хранящимся в XML-файле.
Использование метода ExecuteNonQuery
В результате выполнения некоторых SQL-операторов никакие данные не возвращаются. Такими операторами являются INSERT, DELETE, UPDATE, а также обращение к хранимым процедурам, не возвращающим никаких данных.
Для реализации подобных команд интерфейс IDbCommand имеет метол ExecuteNonQuery» который выполняет команду и возвращает количество затронутых ею записей.
В следующем примере (проект Ch02\CommExecNonQuery\ExecNonQueryDemo.dpr) демонстрируется использование метода. К проекту присоединены связной компонент BdpConnectionl, настроенный на связь с БД «Книголюба, и компонент- команда BdpCommandl. В поле TextBoxl вводится текст SQL-команды, не возвращающей данные (рис. 2.9).
Рис. 2.9. Демонстрация метода ExecuteNonQuery
Ниже показан обработчик щелчка на кнопке ExecuteNonQuery:
procedure TWinForml.Buttonl_Click(sender: System.Object;
e: System.EventArgs}; var RowsChanged: Integer;
begin if TextBoxl.Text <> 1' then// Есть текст команды?
begin//-Да, Пытаемся выполнить
BdpCommandl.CommandText :二 TextBoxl.Text; //Переносим команду BdpConnectionl.Open;//Открываем соединение
try
RowsChangecl :二 BdpCommandl.ExecuteNonQuery; //Выполняем команду finally
BdpConnectionl.Close;// Закрываем соединение
end; / / Сообща ем о количестве измснотых записей : Label2.Text := 'Изменено записей: ' + RowsChanged.ToString; end; end;
Выполнение параметрических запросов
В большинстве случаев запрос имеет изменяемые параметры, что позволяет гибко реагировать на запросы пользователя. В этом случае в текст запроса на месте
изменяемых параметров вставляются символы-заменители. Для провайдера BDP такими заменителями являются символы вопроса (?). Например:
SELECT COUNT(*) FROM Houks WHERE ^Publish 二?
Эгот запрос возвращает количество наименований книг какого-либо издательства, причем символ вопроса заменяет конкретное название издательства. 11тобы вставить в запрос нужное значение параметра (имя издательства), используется объект класса Sdpparameter. При его создании в конструкторе BdpPammeter . Create указываются название параметра, тип и размер данных.
Приведенный выше запрос возвращает единственное значение класса ^Object, поэтому для его выполнения нужно использовать метод ExecuteScalar.
В следующем примере (проект Ch02\CommParamQuerY\ParamQueryDemo,dpr) создается окно, показанное на рис. 2.10.
Выберите исПзгввние :юд-ва х шелкййтё ::кВмполнмтьм
BHV-Самкт-Пете:Бином ВильямсНолвджBHV-Самкт-Пете:Бином ВильямсНолвджSelect count(♦)心 сэт from books uherb spubiish
BHV-Самкт-Пете:
Бином Вильямс
Нолвдж
BHV-Самкт-Пете:
Бином Вильямс
Нолвдж
ВЫПО ЛНИТЬ I
■ Наименоввний книг издательства Питер: 17《
Рис. 2」0・ Окно работающей программы
К проекту присоединен объект BdpConnectionl, наст]юенны11 на связь с БД vKiinnuioo^. Ниже показан обработчик щелчка на кнопке Выполнить:
procedure TWin?orm2.Bur tonl_Click(sender': System.Object; e: System.TventAigs);
var
Cird : BdpCcmmand ;
Ffir : BdpPar-amelei ;
Ob'i : o.Ohject;
begin
if LisLBoxl. Select erllc em <> NIL then / / Выбрано название изд-ве! ?
begin/ / -Да . Готова и выполняем запрос
х / СА;зз$ё?и команду :
Fmd : - BciriC'omrnar.d . Ct eate (Text Boxl. Text: , BdpConnect i onl);
Гез二曰см параметр л вставляем его в коллекции Parameters:
Pcir : - Crr.^1. Fnrsrn»?t cr^ . АсИ ( 1 FUB ' , Bc^pType . St ring , 25 );
/ / начете параметра берем мз списка :
P^r . Va I up : - ListzBoxl.号卩J ec::e<ilLem;
BdpConnectionl.Open;// Открываем соединение с БД
try
Obj : - Cmd. ExecuteScalar ;/ / Выполняем параметрическмй запрос
〃 Отображаем результат:
Labell.Text := System.&String.Format(
* Наименований книг издательства {0}: {1}', Par.Value, obj); finally
BdpConnectionl.Close; •// Закрываем соединение
end;
end; end;
Для форматирования результата задействован метод Format класса System. String. Подробности преобразования строк и использования других классов широкого назначения платформы .NET приведены в приложении Д.
Пример свидетельствует о том, что в провайдере BDP имена параметров никак не используются. Если в запросе имеется несколько символов-заменителей, то кон- кретаые значения параметров берутся из коллекции BdpCommand. Parameters последовательно: первый символ вопроса заменяется значением первого элемента коллекции, второй — второго и т. д.
Провайдеры данных Microsoft используют именованные символы-заменители вида @Имя. Например:
SELECT COUNT{*) FROM Customers WHERE Country = OCountry
При создании параметра первым указывается его имя, затем тип и размер:
Par :二 SqlCommandl.Parameters.Add(1OCountry',SqlDBType.NVarChar,15}; Par.Value := * USA';
Соответствие параметров и их значений устанавливается не порядком определения параметра в коллекции Parameters, а их именами в строке запроса и коллекции.
Получение множества результатов запроса
Для получения множества результатов запроса используется метод Execu t eRe ader класса BdpCommand. Этот метод возвращает объект класса BdpDataReader, исполняющий интерфейс IDataReader. Свойства н методы интерфейса представлены в табл. 2.10 и 2.11 соответственно.
Таблица 2.10. Свойства интерфейса IDataReader
СвойствоОписание
property Depth: integer;Указывает глубину вложенности записей
property isClossed: Boolean;Содержит True, если объект закрыт
property RecordsAffected: Integer; Содержит количество измененных записей
Таблица 2.11. Методы интерфейса IDataReader
Метод
Описание
procedure Close;
Закрывает объект
function GetSchemaTabl: DataTable;
Возвращает схему данных
function NextResult: Boolean;
Переводит курсор к следующей записи и возвращает True, если данные не исчерпаны
function Read: Boolean;
Читает очередную запись и переводит курсор к следующей. Возвращает False, если данных для чтения больше нет
Класс BdpDataReader имеет два важных свойства:
Item: ^Object — индексированное свойство для доступа к нужному полю записи;
FieldCoimt: Integer — количество полей в записи.
В качестве индекса свойства Item можно указывать имя поля или его индекс (индексация начинается с нуля). Это свойство — умалчиваемое, поэтому два следующих обращения идентичны:
var
DataRdr: BdpDataReader;
Res: String;
Res :二 DataRdr[0].ToString;
Res := DataRdr.Item[0].ToString;
Для демопстрацин метода Execut eReade г подготовлен проект Ch02\CommExecReader\ ExecReaderDemo.dpr, который создает окно, показанное на рис. 2.11.
Рис- 2.11. Окно примера
Обработчик щелчка на кнопке Выполнить показан ниже:
procedure TWinForm.Button1_Click(sender: System.Object;
e: System.EventArgs); var
Cmd: BdpCommand;
Rdr: BdpDataReader;
begin
Cmd := BdpConunand.Create('SELECT * FROM TYPES', BdpConnectionl); BdpConnectionl.Open;
try
Rdr := Cmd.ExecuteReader;
while Rdr.Read do
TextBoxl.AppendText(
Systexn.&String.Format ( ' {0}(1} 1 #13#10, Rdr[0] , Rdr [ 1 ]));
filially
BdpConnectionl.Close;
end; end;
Символы #13#10 обеспечивают перенос отображаемого текста на следующую строку.
К проекту добавлен компонент BdpConnectionl, настроенный на связь с БД «Книголюб».
Класс DataAdapter
Класс DataAdapter представляет собой мост между источником данных и разъединенными объектами, которые позволяют визуализировать данные и управлять ими. Адаптер получает данные из источника данных и помещает их в виртуальное хранилище информации — объект класса DataSet. Кроме того, он кэширует измененрш, предоставляя пользователю возможность отказаться от сделанных изменений или внести их в источник данных.
Класс исполняет интерфейс I DBDa t a Adapt er, в котором предусмотрены четыре строковых свойства: Select Command, Insert Command, Del et eCommand, Updat eCommand. В этих свойствах хранятся соответствующие SQL-команды для получения и изменения данных. Каждая команда сопровождается своей коллекцией параметров, обеспечивающей параметрический запрос.
Набор данных DataSet полностью разъединен с исходными данными, поэтому он не имеет никакой информации о соотношении хранящихся в нем данных с исходными данными. Для решения этой задачи в класс DataAdapter включена коллекция Tab 1 eMappingsт содержащая объекты DataTableMapping. Каждый объект DataTableMapping соотносит хранящийся в НД DataSet объект класса DataTable с реальным источником информации (таблицей БД, представлением, XML-файлом и т. и.). Имя таблицы в НД заносится в свойство DataSetTable объекта DataTableMapping, а имя источника информации —в его свойство SourceTable. Для детализации связей между полями
TableMappingsTableMappingsDataTableMappingDataTableMappingDataSetColumnDataSetColumnDataSourceColumnDataSourceColumnDataSetTableDataSetTableSourceTableSourceTableРис. 2.12. Схема коллекции TableMappingsРис. 2.12. Схема коллекции TableMappingsкаждый Da t aTab 1 eMapp ing имеет коллекцию DataColumnMapping, в которой каждому полю DataSetColumn набора данных ставится в соответствие поле DataSourceColumn источника данных (рис. 2.12).Свойства, методы и события классаВ табл. 2.12 представлены свойства класса BdpDataAdapter.Весьма удобным является свойство Active. Как уже отмечалось, разъединенный НД класса DataSet не имееткаждый Da t aTab 1 eMapp ing имеет коллекцию DataColumnMapping, в которой каждому полю DataSetColumn набора данных ставится в соответствие поле DataSourceColumn источника данных (рис. 2.12).Свойства, методы и события классаВ табл. 2.12 представлены свойства класса BdpDataAdapter.Весьма удобным является свойство Active. Как уже отмечалось, разъединенный НД класса DataSet не имеет
TableMappings
TableMappings
DataTableMapping
DataTableMapping
DataSetColumn
DataSetColumn
DataSourceColumn
DataSourceColumn
DataSetTable
DataSetTable
SourceTable
SourceTable
Рис. 2.12. Схема коллекции TableMappings
Рис. 2.12. Схема коллекции TableMappings
каждый Da t aTab 1 eMapp ing имеет коллекцию DataColumnMapping, в которой каждому полю DataSetColumn набора данных ставится в соответствие поле DataSourceColumn источника данных (рис. 2.12).
Свойства, методы и события класса
В табл. 2.12 представлены свойства класса BdpDataAdapter.
Весьма удобным является свойство Active. Как уже отмечалось, разъединенный НД класса DataSet не имеет
каждый Da t aTab 1 eMapp ing имеет коллекцию DataColumnMapping, в которой каждому полю DataSetColumn набора данных ставится в соответствие поле DataSourceColumn источника данных (рис. 2.12).
Свойства, методы и события класса
В табл. 2.12 представлены свойства класса BdpDataAdapter.
Весьма удобным является свойство Active. Как уже отмечалось, разъединенный НД класса DataSet не имеет
соотношения хранимых им данных с реальными данными БД или другого источника данных. Если в свойство DataSet адаптера поместить ссылку на НД и в свойство Active установить True, произойдет автоматическое сопоставление данных. В результате сложные свойства Tab 1 eMappings в адаптере и Tables в НД окажутся нужным образом сформированы. Единственное, что, возможно, придется сделать, — заменить безликие имена таблиц Table, ТаЫе2 и т. д. в DataSet. Tables более осмысленными. Замечу, что коллекция DataSet .Relations» определяющая реляционные связи между таблицами, автоматически не формируется.
Таблица 2.12. Свойства класса BdpDataAdapter
Свойство
Описание
property AcceptShangesDuringFill: Boolean;
Определяет, будет ли вызываться метод AcceptChages после добавления DataRow к DataTable во время операции наполнения
property Active: Boolean;
Еслм содержит True, НД, указанный в свойстве DataSet, заполняется схемой данных, возвращаемых командой SELBCT
property Cont i nueApdateOnError:
Boolean;
Запрещаст/разрешает генерацию исключения при возникновении ошибки в момент подтверждения изменений
property DataSet: DataSet;
Содержит ссылку на связанннй с компонентом НД класса DataSet
property De1eteCommand: String;
Содержит команду dblets
property TnsertCommand: String;
Содержит команду INSBRT
property MaxRecords: Integer;
Определяет максимальное количество записей, которые будут переданы в НД'
Свойство
Описание
property MissingMappingAction: MissingMappingAction;
Определяет реакцию на добанление данных, когда не установлено соответствие исходных данных и данных в НД
property MissingSchemaAct ion:
Определяет реакцию на добавление данных.
MissingSchemaActiong;
property SelectCommand: String; property StarLRecord: Integer;
когда схема данных в НД ошибочна
Содержит команду SELECT
Оггределяет номер записи, с которой начинается наполнение НД
property TableMappings:
Da ti aTabl eMapp ingCo 1 lection;
property UpdateCormnand: String;
Коллекция обьсктов DataTahl sMappi ng
Содержит команду UPDATE
С помощью редактора свойства Tabi eMappings программист может соотнести дагшые нужным ему образом. Например, заменить названия полей осмысленными (рис. 2.13).
For each с曲м In the $сигс#.1аЫа> specify Hw name of the
Г眠a©智吋产幻厘m^Г眠a©智吋产幻厘m^曰曰Бригсе table;Бригсе table;Q^tasettabb:Q^tasettabb:SpilMiniMpcAigs:SpilMiniMpcAigs:Рис, 2.13, Изменение названий полей в НДРис, 2.13, Изменение названий полей в НДDaUset ColumnsN9Тип_накладнойDaUset ColumnsN9Тип_накладнойSource ColumnsSource Columns:「TNAME:「TNAME8гЙ£рйМ^&йймп in the dataset 苗阻
Г眠a©智吋产幻厘m^
Г眠a©智吋产幻厘m^
曰
曰
Бригсе table;
Бригсе table;
Q^tasettabb:
Q^tasettabb:
SpilMiniMpcAigs:
SpilMiniMpcAigs:
Рис, 2.13, Изменение названий полей в НД
Рис, 2.13, Изменение названий полей в НД
DaUset Columns
N9
Тип_накладной
DaUset Columns
N9
Тип_накладной
Source Columns
Source Columns
:「TNAME
:「TNAME
Свойство MaxRecords определяет количество записей, считываемых из источника за одно обращение к методу Fill. Оно по умолчанию равно 100, то есть из источника считывается не более 100 записей. Если количество просматривае- мых/изменяемых записей больше, нужно скорректировать это свойство.
Свойство StartRecord определяет порядковый номер (нумерация начинается с нуля) первой считываемой записи. Если в таблице определен первичный ключ, считываемые записи заменяют собой уже имеющиеся в НД записи с таким же первичным ключом, в противном случае — добавляются в конец.
Методы компонента перечислены в табл. 2.13.
Таблица 2.13. Методы компонента BdpDataAdapter
Метод
Описание
function CreateTableMappings:
DataTableMappingCollection;
Создает объект класса DataTableMap- pingCollection
function CreateRowUpdatedEvent (DatRow: DataRow; Command: IDbCommand; StatementType: statementType;
TableMapping: DataTableMapping): RowUpde t edEv en t Ar g s;
Создает аргументы для события Row-
Updated
function CreateRowUpdatingEvent
(DatRow: DataRow; Command:工DbConunand;
StatementType: StatementType;
TableMapping: DataTableMapping): RowUpdetingEventArgs;
Создает аргументы для события RowUpdating
function Fill (DataSet: DataSet):
Integer;
Наполняет данными НД DataSet и возвращает количество прочитанных записей
function FillSchema(DataTable: DataTable; SchemaType: SchemaType; Cominand: IDbConunand; Behavior: CommandBehavior): DataTable;
Возвращает схему данных в объекте DataTable
type IDataParameters = array of IdataParameter; function GetFillParameterd: IDataParameters;
Возвращает массив параметров, установленных пользователем для предложения SBL2CT
type DataRows = array of DataRow; function Update (Data: DataRows): Integer;
Подтверждает изменения, сделанные в массиве записей, и возвращает количество измененных записей. См. перегруженные методы
Обратите внимание: в свойствах адаптера нет ссылки на компонент класса BdpConnection. Спрашивается — каким образом адаптер определяет связной компонент? При создании экземпляра адаптера используется один из перегруженных конструкторов, которому задается команда SELECT и строка соединения (или компонент класса BdpConnect ion). Если компонент создается на этапе разработки формы, среда автоматически выбирает нужный конструктор. На этапе прогона это должен делать программист. В следующем примере (ChO2\DataTable\ FillDataTable.dpr) иллюстрируются техника программного создания адаптера и использование его метода Fill для заполнения объекта DataTable. В примере создается окно, показанное на рис. 2.14.
Класс DataAdapter 79
.0*1i2.0*1i2|4 5 6 7|4 5 6 7Поставка на реализацию Продажа на реализацию Возврат поставки Возврат продажи Приход по обмену Уход по обмену Поставка с предоплатой Продажа с предоплатойПоставка на реализацию Продажа на реализацию Возврат поставки Возврат продажи Приход по обмену Уход по обмену Поставка с предоплатой Продажа с предоплатойI TYPEID | TNAMEI TYPEID | TNAME**
.0
*1
i2
.0
*1
i2
|4 5 6 7
|4 5 6 7
Поставка на реализацию Продажа на реализацию Возврат поставки Возврат продажи Приход по обмену Уход по обмену Поставка с предоплатой Продажа с предоплатой
Поставка на реализацию Продажа на реализацию Возврат поставки Возврат продажи Приход по обмену Уход по обмену Поставка с предоплатой Продажа с предоплатой
I TYPEID | TNAME
I TYPEID | TNAME
*
*
Опфыгьтвбгеш^
Рис. 2.14. Окно примера
К проекту присоединен компонент BdpConnectionl, связанный с БД «Книголюб», а на пустую форму помещена сетка DataGrid. Вот обработчик щелчка на кнопке Открыть таблицу:
procedure TWinForm.Buttonl__Click(sender: System.Object; e: System.EvencArgs);
var
DA: BdpDataAdapter;
DT: DataTable;
begin
// Др* создании адаптера указываем строку запроса
// х связной компонент:
DA := BdpDataAdapter.Create('SELECT *DA := BdpDataAdapter.Create('SELECT *DT := DataTable.Create;//BdpConnectionl.Open;//try DA.Fill(DT);//finallyBdpCon nec t ion1.Close;//end;DT := DataTable.Create;//BdpConnectionl.Open;//try DA.Fill(DT);//finallyBdpCon nec t ion1.Close;//end;DataGridl.DataSource := DT; // end;DataGridl.DataSource := DT; // end;FROM TYPES', BdpConnectionl); Создаем таблицу DataTable Открываем соединениеНаполняем таблицуЗакрываем соединениеПоказываем таблицу в сеткеFROM TYPES', BdpConnectionl); Создаем таблицу DataTable Открываем соединениеНаполняем таблицуЗакрываем соединениеПоказываем таблицу в сетке
DA := BdpDataAdapter.Create(
'SELECT *
DA := BdpDataAdapter.Create(
'SELECT *
DT := DataTable.Create;//
BdpConnectionl.Open;//
try DA.Fill(DT);//
finally
BdpCon nec t ion1.Close;//
end;
DT := DataTable.Create;//
BdpConnectionl.Open;//
try DA.Fill(DT);//
finally
BdpCon nec t ion1.Close;//
end;
DataGridl.DataSource := DT; // end;
DataGridl.DataSource := DT; // end;
FROM TYPES', BdpConnectionl); Создаем таблицу DataTable Открываем соединение
Наполняем таблицу
Закрываем соединение
Показываем таблицу в сетке
FROM TYPES', BdpConnectionl); Создаем таблицу DataTable Открываем соединение
Наполняем таблицу
Закрываем соединение
Показываем таблицу в сетке
Метод Fill наполняет НД DataSet или, как это сделано в предыдущем примере, объект класса DataTable в соответствии с SQL-запросом Select Command. Если это свойство не определено, возникает исключение.
Для фиксации изменений, сделанных пользователем в НД, используется метод Update. Перед обращением к нему должны быть определены соответствующие
параметрические запросы: при вставке записи — запрос Insert Command, при уда-пении — De 1 et eCommand, при изменении — Updat eCommand.
Компонент имеет два события: RowUpdated и Rowupdating. Первое возникает после выполнения метода Update, второе — перед выполнением.
DataSet — набор данных
Наборы данных DataSet представляют собой хранилища данных в оперативной памяти и являются центральными объектами в архитектуре ADO.NET. Данные хранятся в коллекции объектов класса DataTable, доступ к которой открывает cuoiictbo Tables компонента. При манипулировании данными в НД сохраняются резервные копии измененных данных. Это позволяет либо внести сделанные изменения в источник данных, либо отменить их. Вместе с таблицами в объектах класса DataRelation хранятся реляционные связи между данными. Доступ к коллекции этих объектов открывает свойство Relations. Свойства Namespace и Prefix используются для обработки данных в виде XML-файлов.
Друше свойства класса DataSet перечислены в табл* 2.14.
Таблица 2.14. Свойства класса DataSet
Свойство
Описание
property CaseSensetive: Boolean;
Если содержит True» операции поиска и сравнения строк учитывают высоту букв
property Def aultViewManager: DataVi ewManager;
Возвращает коллекцию наборов данных, использующихся для фильтрации, сортировки к других операций нал хранимыми в НД данными
property Enf orceConstraints: Boolean;
Включаст/отключает действие оп)аничений при выполнении метода update
property HasError: Boolean;
Возвращает True, если хотя бы один объект
DataTable имеет ошибку
В табл. 2.15 указаны некоторые методы класса DataSet.
Таблица 2.15. Методы класса DataSet
Метод
Описание
procedure AcceptChanges;
Подтверждает все изменения, сделанные в НД
procedure Clear;
Удаляет из компонента все данные
function GetChanges: DataSet;
Возвращает все изменения в отдельном НД
function GetXML: String;
Возвращает данные в виде XML-таблицы
function HasChanges: Boolean;
Возвращает True, если НД был изменен
Метод
Описание
procedure Merge(DataSet);
procedure Merge(DataRow);
Объединяет заданный НД, DataRow или DataTable с текущим НД
procedure Merge (DataTable); function ReadXMLfST: Stream):
Читает XML-данные из потока (см. перекры-
XMLReadMode;
procedure Rejectchanges;
тые методы)
Откатывает все изменения в данных
Компонент имеет единственное специфичное событие MergeFailed, возникающее при ошибке в методе Merge. Обработчик события получает строку с описанием ошибки и ошибочный объект DataTable.
Отличительной особенностью технологии ADO.NET является ее тесная интеграция с файлами формата XML (extended Markup Language — расширенный язык разметки; подробнее о языке см. приложение В). Обмен данными между различными компонентами реализуется с помощью такого рода файлов. В компоненте DataSet есть соответствующие методы для чтения/записи XML.
В следующем примере (Ch02\XML\ProjectXML.dpr) демонстрируется техника работы с этими методами (рис. 2.15):
Начните новое приложение WinFonns.
《NewDataSel〉《NewDataSel〉;\ ;: J TYPEtl tNAME;\ ;: J TYPEtl tNAME! 4! 4Поставка на реализа Продажа на реализа Возврат поставки Возврат пропажи Приход по обмену Уход по обмену Поставка с предолла Продажа с предоплаПоставка на реализа Продажа на реализа Возврат поставки Возврат пропажи Приход по обмену Уход по обмену Поставка с предолла Продажа с предоплаGeO<MLGeO<ML<TYPES><TYPEID>O</TYPEID><TNAME>Поставка на реализаиикх/ТNAME></TYPES><TYPES><TYPEID>1</TYPEID><ТМАМЕ>Г1ром*а на реализацию</ТМДМЕ></TYPES><TYPES><TYPEID>2</TVPEID><T NAM Е>8озврггт постдокн</Т NAM E ></TYPES><TYPES><TYPEID>3</TYPEID><ТЫАМЕ>Возврагт продажи</ТЫАМЕ></TYPES><TYPES><TYPEID>4</TYPEID><ТИАМЕ>Прихсл по обмену</ТЫАМЕ></TYPES><TYPES><TYPEID>5</TYPEID><ТМАМЕ>Уход по обмену/TNAME><TYPES><TYPEID>O</TYPEID><TNAME>Поставка на реализаиикх/ТNAME></TYPES><TYPES><TYPEID>1</TYPEID><ТМАМЕ>Г1ром*а на реализацию</ТМДМЕ></TYPES><TYPES><TYPEID>2</TVPEID><T NAM Е>8озврггт постдокн</Т NAM E ></TYPES><TYPES><TYPEID>3</TYPEID><ТЫАМЕ>Возврагт продажи</ТЫАМЕ></TYPES><TYPES><TYPEID>4</TYPEID><ТИАМЕ>Прихсл по обмену</ТЫАМЕ></TYPES><TYPES><TYPEID>5</TYPEID><ТМАМЕ>Уход по обмену/TNAME>、WriteXML、WriteXML
《NewDataSel〉
《NewDataSel〉
;\ ;: J TYPEtl tNAME
;\ ;: J TYPEtl tNAME
! 4
! 4
Поставка на реализа Продажа на реализа Возврат поставки Возврат пропажи Приход по обмену Уход по обмену Поставка с предолла Продажа с предопла
Поставка на реализа Продажа на реализа Возврат поставки Возврат пропажи Приход по обмену Уход по обмену Поставка с предолла Продажа с предопла
GeO<ML
GeO<ML
<TYPES>
<TYPEID>O</TYPEID>
<TNAME>Поставка на реализаиикх/ТNAME>
</TYPES>
<TYPES>
<TYPEID>1</TYPEID>
<ТМАМЕ>Г1ром*а на реализацию</ТМДМЕ>
</TYPES>
<TYPES>
<TYPEID>2</TVPEID>
<T NAM Е>8озврггт постдокн</Т NAM E >
</TYPES>
<TYPES>
<TYPEID>3</TYPEID>
<ТЫАМЕ>Возврагт продажи</ТЫАМЕ>
</TYPES>
<TYPES>
<TYPEID>4</TYPEID>
<ТИАМЕ>Прихсл по обмену</ТЫАМЕ>
</TYPES>
<TYPES>
<TYPEID>5</TYPEID>
<ТМАМЕ>Уход по обмену/TNAME>
<TYPES>
<TYPEID>O</TYPEID>
<TNAME>Поставка на реализаиикх/ТNAME>
</TYPES>
<TYPES>
<TYPEID>1</TYPEID>
<ТМАМЕ>Г1ром*а на реализацию</ТМДМЕ>
</TYPES>
<TYPES>
<TYPEID>2</TVPEID>
<T NAM Е>8озврггт постдокн</Т NAM E >
</TYPES>
<TYPES>
<TYPEID>3</TYPEID>
<ТЫАМЕ>Возврагт продажи</ТЫАМЕ>
</TYPES>
<TYPES>
<TYPEID>4</TYPEID>
<ТИАМЕ>Прихсл по обмену</ТЫАМЕ>
</TYPES>
<TYPES>
<TYPEID>5</TYPEID>
<ТМАМЕ>Уход по обмену/TNAME>
、WriteXML
、WriteXML
Рис. 2.15. Демонстрация работы с XML
На пустую форму поместите три панели. Их свойствам Dock присвойте значения Bottom, Left и Fill.
На нижнюю панель поместите три кнопки (GetXMLt Clear, WriteXML).
На левой панели расположите сетку DataGrid (категория Data Controls), на правой — компонент Text Box. Для каждого из них в свойство Dock поместите значение Fill. Кроме того, в свойство Multiline компонента TextBox поместите значение True.
Выберите в меню команду View ► Data Explorer и в открывшемся окне Data Explorer раскройте узлы Interbase, IBConn2 и Tables.
Перетащите (Drag&Drop) таблицу Types из окна Data Explorer в любое место формы. В результате в нижней части редактора формы появятся невизуальные компоненты BdpConnect и BdpDataAdapter, причем они будут настроены на связь с таблицей Types и отображение всех ее полей.
Перетащите на форму компонент DataSet (категория Data components).
Поместите в свойство DataSet компонента BdpDataAdapter ссылку на компонент DataSetl, а в свойство Active — значение True. В свойстве Datasource сетки укажите ссылку на таблицу DataTablel. В результате сетка должна заполниться значениями записей из таблицы Types.
Напишите такие обработчики событий для кнопок:
procedure TWinForm.ButtonS.-Click(sender: System.Object; e: System.EventArgs);
// Щелчок на кнопке ReadXML begin
DataSetl .ReadXMH *Data*)/ / Читаем данные из файла
end;
procedure TWinForm.Button2_Click(sender: System.Object; e: System.EventArgs);
〃 Щелчок на кнопке Clear begin
DataSetl.Tables[0] .Clear// Очтаем таблицу в ВД
end;
procedure TWinForm.Buttonl_Click(sender: System.Object;
e: System.EventArgs);
// Щелчок на кнопке GetXML var
F: TextFile;
begin
Textboxl. Text : = DataSetl .GetXml; // Читаем таблицу а формате XML Assign(F, 'Data 1);// и записываем ее в файл
Rewrite(F);
WriteLn(F, TextBoxl.Text);
CloseFile(F)
end;
DataTable — таблица НД
Объекты DataTable предназначены для хранения данных в НД. Они содержат поля (объекты DataColumn) и записи (объекты DataRow). В одном НД может храниться сколько угодно объектов DataTable.
Многие свойства DataTable дублируют соответствующе свойства DataSet. Например, свойство HasError: если хотя бы у одной таблицы это свойство имеет значение True, аналогичное свойство НД имеет то же значение.
Оригинальные свойства и методы DataTable представлены в табл. 2.16 и 2.17.
Таблица 2.16. Свойства класса DataTable
Свойство
Описание
property ChiIdRelations: DataRelationCollection;
Определяет набор связей с дочерними таблицами
property Columns: DataColumn Collection;
Коллекция полей таблицы
property Constraints:
ConstraintCollection;
Коллекция ограничений, накладываемых на значения полей
property DataSet: DataSet;
Ссылка на компонент НД, являющийся контейнером таблицы
property DefualtView: DataView;
Возвращает набор данных» использующихся для фильтрации, сортировки и других операций над хранимыми в НД данными
property Disp1ayExpres sion:
String;
Определяет выражение, значение которого будет отображаться в компонентах визуализации
property ExtendedProperties: PropertyCollection;
Определяет расширенный набор параметров, которые можно добавить к свойству DataColumn, DataTable или DataSet
property MinimumCapasity: Integer;
Определяет минимальное количество записей в таблице (по умолчанию — 25)
property ParentRelations:
DataRelationCollection;
Определяет набор связей с родительскими таблицами
property Rows: DataRowCollection;
Определяет коллекцию записей
property TableNcnne: String;
Содержит имя таблицы
Таблица 2.17. Методы класса DataTable
Метод
Описание
procedure AcceptChanges;
Подтверждает все изменения, сделанные в таблице
продолжение 夕
Таблица 2.17 (продолжение)
Метод
Описание
procedure Beginlnit;
Сигнализирует визуальным компонентам о начале инициализации таблицы
procedure BeginLoadData;
Отючючает систему индексов и ограничений перед чтением данных
procedure Clear;
Очищает таблицу от данных
function Compute(Expr, Filter:
String): Object;
Вычисляет результат выполнешш действий, указанных в выражении Ехрг, над группой записей, заданных фильтром Filter
fxmction Copy: DataTable;
Создает копию таблицы
function Createlnstance: DataTable;
Создает экземпляр таблицы
procedure Endlnit;
Сигнализирует визуальным компонентам о завершении инициализации таблицы
procedure EndLoadData;
Включает систему индексов и ограничений после чтения данных
function GetChanges: DataTable;
Возвращает изменения в таблице
function GetErrors: array of DacaRow;
Возвращает массив записей с ошибками
procedure Import Row (Row: DataRow);
Включает н таблицу запись Row
function LoadDataRow(Values: array of Object; isAcceptChanges: Boolean): DataRow;
Обновляет указанную запись. Если такой записи ист, создает ее
function NewRow: DataRow;
Создает новую пустую запись, но нс присоединяет ее к таблице
function NewRowArray(Size:
Ibteger): array of DataRow;
Создает указанное количество пустых записей
fubction NewRowFromBuilder
(Bulder: DataRowBuilder): DataRow;
Создаст новую запись на основе существующей
procedure Rej ectChanges;
Откатывает все изменения таблицы
procedure Reset;
Устанавливает таблицу в исходное состояние
fxmction Select: array of DataRow;
Возвращает массив записей (см. nejwrpyxcH- пые методы)
Для иллюстрации приемов использования некоторых нз описанных методов рассмотрим следующий пример (проект ChO2\Create Table\CreateTable.dpr). Создадим таблицу с двумя полями и несколькими записями (рис. 2.16).
Для этого на пустую форму поместите две панели со свойствами Dock Bottom и Fill. На верхнюю панель поместите компонент DataGrid (категория Data Controls) и установите в его свойство Dock значение Fill. На нижнюю панель
поместите кнопку Button (категория Windows Forms). Напишите такой обработчик щелчка на кнопке:
procedure TWinForm.ButtonljClick(sender: Systran»Obj ect; e: System.EventArgs); var
DS: DataSet.;
Table ; DataTable;.
Column: DataCplumn;
Row: DataRow;
k: Integer;
begin with DS do begin
// Создаем набор данных
DS := DataSet.Create(•DataSet11); 〃 Создаем таблицу
Table : = DataTable.Create( *Па<;аТаЬ1е1');
// Добавляем таблиц/ в ВД DS. Tables. Add (Table);
// Создаем первое поле с именем ID
Column := DataColumn.Create('ID1); // Устанавливаем тал поля
Column. DataType := System. Type .Get Type (1 System. Int32 •);
// Добавляем к таблице
Table. Columns. Add (Column); // Создаем второе поле Column := DataGolumn.Create; // Устаяавлиза ем имй поля Column. ColumnNaxne :二 * Текст * ; Н и его тип
Column.DataType := System-Type.GetType( • System.String*);
// Добавляем к таблице
Table.Columns.Add(Column); // Создаем 5 записей for k := 1 to 5 do begin
〃 Создаем пустую запись Row := Table.NewRow;
// Наполняем ее Row[lID*] := k; Row['Текст"] := 1 Строка ' + k.ToString; H и добавляем к таблице
Table.Rows,Add(Row);
end;
end;
DataGridl.DataSource := DS; // Связываем сетку c 耿 end;
Рис. 2.16. Создание таблицы в работающей программе
:Nt накладной
三
Кол-во книг 斤"
:QComputeJ
Рис. 2.17. Использованиеметода Compute
С помощью метода Compute можно получить агрегатное значение полей в диапазоне записей, выбираемых параметром Filter. Следующая программа (проект Ch02\Compute\ ComputeDemo.dpr) подсчитывает общее количество книг, проданных или купленных по заданной накладной (рис. 2.17).
Создайте новое приложение и поместите на пустую форму компоненты Numeri cUpDown, TextBox и Button (категория Windows Forms). Свяжите с формой также компоненты BdpConnection, BdpDa t a Adapt er (категория Borland Data Provider) и DataSet (категория Data Controls). Настройте их на отображение всех полей таблицы MOVES учебной БД. Напишите такой обработчик щелчка на кнопке:
procedure TWinForml.Buttonl_Click(sender: System.Object;
e: System.EventArgs);
begin
TextBoxl.Text := DataSet 1.Tables[0].Compute('SUM(MQUAN) 1 (
'NAKLID='+NumericUpDownl.Value.ToString).ToString; end;
DataColumn — поля таблиц
Свойство Columns таблицы DataTable содержит коллекцию полей. Набор полей определяет структуру таблицы. На допустимые значения полей могут
накладываться ограничения. Свойство Constraints таблицы DataTable содержит коллекцию ограничений.
В табл. 2.18 описаны свойства класса DataColumn.
Таблица 2.18. Свойства класха DataColumn
Свойство
Описание
property AllowDBNull: Boolean;
Если содержит True, поле может содержать пустое значение
property AutoXncrement: Boolean;
Если содержит True, поле может автомат»。 чески наращивать значения, то есть быть автоинкрементным
property AutoIncrementSeed:
Содержит начальное значение автоинкрсмент-
Integer;
ного поля
property AutoIncrementStep:
Содержит шаг наращивания автоинкремент-
Integer;
ного поля
property Caption: String;
Определяет заголовок поля в DataGrid
property ColumnMapping:
Определяет, как будет представлено поле при
MappingType;
сохранении DataSet в формате XML
property ColumnName: String;
Позволяет получить или установить имя поля в коллекции Columns таблицы DataTable
property DataType: &Type;
Определяет тип содержащихся в поле данных
property Defaultvalue: Object;
Определяет умалчиваемое значение, которое помещается в запись, если для поля нс установлено значение
property Expression: String;
Определяет выражение для нычислеиия значения поля
property ExtendedProperties:
Определяет дополнительную информацию.
Propertycollection;
связанную с полем
property MaxLength: Integer;
Устанавливает максимальную длину строкового поля
property Ordinal: Integer;
Возвращает положение поля в коллекции
Columns
property Readonly: Boolean;
Если содержит True, значения поля можно только читать
property Unique: Boolean;
Содержит True, если поле состоит из уникальных значений
Свойство Caption, как сказано в документации, содержит заголовок поля, показываемый в визуализирующих компонентах, таких как DataGrid, например. Несложный опыт показывает, что на самом деле это не так: ни в редакторе полей, ни в работающей программе изменение этого свойства никак не влияет на заголовки полей. Как реально изменить название поля, описано далее в разделе ^Изменение названия и скрытие полей>>
Свойство ColumnMapping управляет отображением поля в XML-документе и может иметь одно из следующих значений:
Attribute — атрибут документа;
Element — элемент документа;
Hidden — внутренняя структура документа;
simpleContent — узел документа.
Обычно это свойство имеет значение Element. Если поместить в свойство значение Hidden, поле не будет передаваться визуализирующим компонентам.
Свойство Expression предназначено для создания так называемых вычисляемых поле», то есть полей, значения которых вычисляются на основе значений других полей той же записи. Создание вычисляемых полей рассматривается далее в разделе «Вычисляемые поля».
Свойство ExtendedProperties представляет собой коллекцию объектов, в которые программист может поместить некоторую дополнительную информацию, связанную с текущим полем, например время последнего обновления значения поля. Это свойство недоступно на этапе создания формы. Для добавления значения в коллекцию ExtendedProperties на этапе прогона программы используется метод Add, который определен следующим образом:
procedure Add(Key# Value: Oblect);
Здесь Key — строка» задающая название свойства; Value — значение свойства. Например:
procedure TWinForml.ExtPropDemo;
var
ExtProp: Propertycollection; // Для сокращения длины операторов begin
ExtProp := DataSetl.Tables[0].Coluinns[0].ExtendedProperties;
// Создаем дополнительное свойство:
ExtProp.Add('Timestamp', DateTime.Now);
/ / Используем его :
Console.WriteLine(ExtProp['Timestamp1].ToString);
end;
Вычисляемые поля
Как уже говорилось, вычисляемые поля содержат значения, полученные путем вычисления некоторого выражения из содержимого других полей той же записи. Такие поля нельзя изменять в работающей программе. Есть два способа создания вычисляемого поля: с помощью свойства Expression или формированием сложного запроса в предложении select. Далее рассматриваются оба способа. Свойство Expression определяет выражение, по которому вычисляется значение поля. В выражении указываются поля и знаки математических опера-
ции. Например, в таблице BOOKS есть поля BQUAN л BPRICE. Первое определяет количество экземпляров книги, второе — цену одного экземпляра. Перемножив поля, нолуннм стоимость всех экземпляров каждой из книг, как показано на рис. 2.18 (проект Ch02\Expression\ExpressionDemo.dpr).
鏡解图離
$^г **"*心人1№мат поля
=В00КЮ
f 9PRICE
BQUAN
;BNAME
SUMM
28,44
6
10 минут на урок MS Word 2000
170,64
2
14.189
17
10 мин夕 на урок Windows 98
241,213
28,44
27
1。мин" на деок.Освой самостоятельно MS
767,08
;4
40
1
100 компонентов общего назначения библи
40
'45
35,011
35
1001 секрет реестра Windows NT
1225.3В5
10
6
12 уроков тенниса. Самый Аоступнь1й самоуч
60
7
4
39
13 шагов к успеху или практические советы
156
8
131,25
23
1 С:Бухгалгерия.Самоучитель Версии 7 5 и 7
3010.75
9
44,117
8
3D Sludk) МАХ 2.5 справочник
352,9 芻
10
7875
5
3D Studio МАХ З.Учебный курс + CD-ROM
472,5
也11
113,37
30
3D Studio MAX R3.СпецэФфекты и дизайн +
3401,1
—12
105
£
3D Studio МАХ.Внутренний мир.Том 2 + CD-
£30
74.25
8
3D Stud。Max 3.0 от объекта до анимации +
594
.14
56,25
5
600 звуковых и м^зькальных программ
281,25
15
52.5
11
98 вопросов по Windows 90 с ответами
577,5
16
63.75
20
Access 2000 для пользоватвля.РусиФициро
1275
17
121.5
5
Access 37 Руководство по макроязыку и VB
607.5
175
18
Access 97 Энциклопедия пользователя ♦ CD
3150
'J19
48,75
20
Admimsbering SQL Server 7 Сертификацией
975
20
43,342
16
Adobe Illustrator 8 0 в подлижике
780,156
21
5Б.25
7
Adobe INusliator 8:учебный курс
393,75
22
70.5
36
Adobe InDejgn в подлиннее
2538
一承3
22.393
28
Adobe Photoshop 5 для начинающих и не тол
627,172
Рис. 2.18. Демонстрация свойства Expression
При использовании свойства мне пришлось изрядно помучиться. Дело в том, что в редакторе полей перед присваиванием значения свойству Expression нужно предварительно установить для него подходящий тип (в нашем случае — Double), однако редактор пе допускает изменения типа поля! В результате в режиме конструирования формы пиле нормально отображается в сетке, но в режиме прогона становится неопределенным. Пришлось вставлять вычисляемое поле на этапе прогона программы:
constructor TWinForm. Сге-зсе;
begin
inherited Create;
//
// Required for Windorvs 尸。上川 Designer support:
//
IninializeCompone^r;
// TODO: Add any constructor code after InitializeComponent: call //
// Добавляем новое поле с нужным именем. нужным типом
//л значением свойства Expression:
DacaSetl.Tables[0].Columns.Add('SUMM',
System.&Type.GetType(* System.Double1), ,BQUAN*BPRICE,); end;
Для вставки использовался один из перегруженных методов DataColumn- Collection. Add, позволяющий одновременно указывать имя поля, его тип н значение свойства Expression.
При формировании выражений допускается использование имен полей и знаков математических операций, как в рассмотренном вьппе примере. Допускается также операция получения модуля (%).
Помимо математических операций, в выражениях можно использовать логические операции NOT, AND и OR, а также операции сравнения: =, о, >, v, >=, <=. Логические операций и операции сравнения имеют такой же смысл, как в Delphi. В выражения может включаться любая агрегатная функция (8UM, AVG, м工N, МЛХ, COUNT). Операндами агрегатных функций не могут быть выражения. Например, нельзя использовать такое выражение:
AVQ(MQUAN *MPRIСЕ)
Проделать такое вычисление можно в два приема: сначала вычислить произведение, затем — его среднее значение:
DataSet 1.Tables[0].Columns.Add('Сумма I
System.&Туре.GetType{•System.Double'), ,MQUAN*MPRICE,); DataSet 1.Tables[0].Columns.Add(* Средняя сумма,)
System.&Type.GetType(* System.Double•), * AVG(Сумма)*);
Таким образом, в выражении можно использовать вычисляемые поля. Разумеется, недопустима прямая или косвенная циклическая ссылка вычисляемого поля на само себя.
Следующие пары символов имеют специальное значение и не могут использоваться в именах полей:
/п (перевод строки);
/t (символ табуляции);
/г (возврат каретки).
Помимо лих пар символов в именах полей нельзя использовать следующие сне- цих^ьпыс символы:
()#/\ = >< + *%л|&,и[]
Если все же указанные символы входят в имя поля, такое имя нужно заключать в квадратные скобки, например:
[Field#l]
Если квадратные скобки сами по себе являются частью имени поля, им должен предшествовать символ обратного слеша (\):
[Number\[1\]}
Язык SQL позволяет создавать довольно сложные выражения. Так как адаптеры используют SQL-запросы, программист может отредактировать предложение SELECT так, чтобы вычислить некоторое выражение. Например:
SELECT
BOOKID, BNAME, BQUAN, BPRICE, BQUAN*BPRICE AS SUMM
FROM
BOOKS
ORDER BY
BOOKID
Этот запрос создаст точно такой же НД, как и созданный ранее с помощью свойства Expression (см. рис. 2,18).
Подстановочные поля
Подстановочными (lookup) полями являются такие поля, содержимое которых не предназначено для демонстрации в визуальных компонентах; в то же время подстановочное поле содержит ссылку на некоторое поле другой таблицы, выводимое вместо подстановочного. В отличие от вычисляемых полей, значение подстановочного поля можно менять, так как оно является реальным полем реальной таблицы НД. Однако на это значение накладывается ограничение внешнего ключа: значение поля должно совпадать с единственным значением подстановочной таблицы.
Рассмотрим такой запрос.
SELECT
MOVEID, BNAME, MPRICE, MQUAN, MPRICE * MQUAN AS SUMM
FROM
MOVES, BOOKS
WHERE
BOOKID = MBOOK
В этом запросе помимо полей таблицы MOVES и вычисляемого поля SUMM выбирается также поле из подстановочной таблицы BOOKS на основании критерия МВООК = BOOKID. В данном случае поле МВООК — подстановочное. Оно не может меняться произвольным образом и должно удовлетворять такому ограничению:
MIN(BOOKID) <= МВООК <= MAX(BOOKID)
Чтобы гарантировать выполнение указанного ограничения при вводе новой записи или редактировании существующей, обычно создается список выбора, составленный из нужных полей подстановочной таблицы.
Изменение названия и скрытие полей
В ряде случаев имена полей желательно заменить более осмысленными и не отображать ненужные поля. Существует несколько вариантов решения этой проблемы. Наилучшнй, очевидно, использование так называемых стилевых объектов сетки DataGrid (см. далее раздел «Использование стилевых объектов»). Однако здесь мы рассмотрим два друпгх варианта: применение свойств TableMappings и Tables объектов BdpDataAdapter и DataSet, а также фор- мированме специального запроса в BdpDataAdapter.
Рассмотрим» как менять названия полей и скрывать их на примере создания краткого справочника книг из таблицы BOOKS (проект ChO2\Mappings\ Mepp.dpr):
Начните новое приложение WinForms.
Выберите в меню команду View ► Data Explorer и в дереве данных последовательно раскройте узлы InterBase, IBConn2 и Tables (рис. 2Л9).
Перетащите (Drag&Drop) таблицу BOOKS на форму. В результате в нижней области невизуальных компонентов появятся компоненты BdpCormectionl и BdpDataAdapterl, причем они уже будут настроены на связь с нужной БД и выборку всех полей из таблицы BOOKS.
Добавьте к ним компонент DataSet (категория Data Components).
В свойство DataSet компонента BdpData- Adapter поместите ссылку на ИД DataSetl.
'用 Data Explorer4^ X ;干® DB2飞I子秒 Interb&se5畢‘所 ISConnlg心的 l8Conn2”& ⑥ TablesJI啰 q§ BOOKS亨 i…q§ CREDIT?'^ q§ DEBITT生贈DETi'您静 FIRMS|$]禽静MASJ?'Ш MOVEBOOKI 里® NAKLS ”葡 PAYMENTS ? ^ ^ TYPENAKL圈S3 握W甌РгЗе…I 替 Model…I冷E^ta:*”「'用 Data Explorer4^ X ;干® DB2飞I子秒 Interb&se5畢‘所 ISConnlg心的 l8Conn2”& ⑥ TablesJI啰 q§ BOOKS亨 i…q§ CREDIT?'^ q§ DEBITT生贈DETi'您静 FIRMS|$]禽静MASJ?'Ш MOVEBOOKI 里® NAKLS ”葡 PAYMENTS ? ^ ^ TYPENAKL圈S3 握W甌РгЗе…I 替 Model…I冷E^ta:*”「Рис. 2.19. Настройкакомпонента Data Explorerна работу с таблицей BOOKSРис. 2.19. Настройкакомпонента Data Explorerна работу с таблицей BOOKSЩелчком на кнопке в строке свойства TableMappings компонента Bdp— DataAdapterl раскройте редактор этого свойства (рис. 2.20).
'用 Data Explorer4^ X ;
干® DB2飞
I子秒 Interb&se5
畢‘所 ISConnlg
心的 l8Conn2”
& ⑥ TablesJI
啰 q§ BOOKS亨 i
…q§ CREDIT?
'^ q§ DEBITT
生贈DETi
'您静 FIRMS|$]
禽静MASJ?
'Ш MOVEBOOK
I 里® NAKLS ”葡 PAYMENTS ? ^ ^ TYPENAKL圈
S3 握W
甌РгЗе…I 替 Model…I冷E^ta:*”「
'用 Data Explorer4^ X ;
干® DB2飞
I子秒 Interb&se5
畢‘所 ISConnlg
心的 l8Conn2”
& ⑥ TablesJI
啰 q§ BOOKS亨 i
…q§ CREDIT?
'^ q§ DEBITT
生贈DETi
'您静 FIRMS|$]
禽静MASJ?
'Ш MOVEBOOK
I 里® NAKLS ”葡 PAYMENTS ? ^ ^ TYPENAKL圈
S3 握W
甌РгЗе…I 替 Model…I冷E^ta:*”「
Рис. 2.19. Настройкакомпонента Data Explorerна работу с таблицей BOOKS
Рис. 2.19. Настройкакомпонента Data Explorerна работу с таблицей BOOKS
Установите флажок Use a dataset to suggest table and column names. Это заставит хранить новые имена полей в НД.
Измените названия полей так, как показано на рис. 2.21, и закройте редактор.
Поместите в свойство Active компонента значение True, чтобы перенести новые имена полей и данные в НД.
Раскройте редактор свойства Tables компонента DataSetl. Он уже будет содержать таблицу BOOKS н все ее поля.
Для поля BISBN раскройте список свойства ColилшМаррing, как показано на рис. 2.22, и выберите значение Hidden. Поля, помеченные как скрытые (то есть свойство ColumnMapping которых равно HiddenHidden), не будут демонстрироваться в сетке DataGrid.
For each 7Uff#i ffi the sourc? tehei, speedy the name tf the ■.cwresponding cdumn'in the dataset ^«Ые.
厂 5 a dataset to suggest teMe and column рвт^、
Dataset JJL
蝕58 table:
QiStasBt table:
Table
卜able
Qjlumn fMWJings:
"i Source СоМпг»
;DaitasM CoMnns.二
>:BOOKID
BOODD
6WAME
:BAUTHOR
BALTTHOR
BPU6LI5H
BPUBLI5H
:BYEAR
BYEAR
ifiPAGES
BP AGES
81淞
KT AMD
BSTAND
!bquan
BQUAN
■БРР.1СЕ
6PRICE
РСЙй»
:毁沔;]、.
Рис. 2.20. Редактор свойства TableMappings
* *e5衿《林< %,**■-■、誉找存* 密长飞/^^
For each column in the source tdb4 specify the name of the corresponding coJumn m the dataset table.
■., {* 呼户呦^eVo ^West t&e end column nam^,
:t>^^ ■: ;l . j (no datasetTin рго]к0
Spurs ПЫе: райе
Q^tasetUble:
3
■ Source Columns
:Dateset Cbhmns
:BOOKID
№
;B№ME
Название
沿 AUTHOR
Автор
;BPUBLI5H
Изд-во
•BYEAR
г од
■8PAGE5
Страниц
;BISflN
6158M
fBSTAWO
BSTAMU
'BQUAN
Кол-во
'BPPICE
曰[books'
^piumn(Wpb9S:
仁
:.u»”:n“”./ . -= m!?a-.,-E,.*,' ":.unwn.;
Рис 2.21. Изменение названий полей
Membeis;Membeis;AddAddBISBN Properties:^?:/AutoInciementSe. 0,,:..? AuloIncrernentSt 18ISBN8IS8NBISBN Properties:^?:/AutoInciementSe. 0,,:..? AuloIncrernentSt 18ISBN8IS8N
Membeis;
Membeis;
Add
Add
BISBN Properties:
^?:/AutoInciementSe. 0
,,:..? AuloIncrernentSt 1
8ISBN
8IS8N
BISBN Properties:
^?:/AutoInciementSe. 0
,,:..? AuloIncrernentSt 1
8ISBN
8IS8N
*;;:・• Caption
=<:< ColumnName ,Dafalype f Defaultvalue |й:: Expression 广七:MaxLenglh <<'.■■ Namespace ;,Prefix :&經 ReadOrrfy < Unique 冲导炉*嗦* ■^ (Name) ^^ Mothers
SystemString
<DBNul»
26
False
Fal$o
DataColumn7
Private
Attribute SimpleConlert Htdden
Рис. 2.22. Скрытие поля BISBN
Повторите му пр()цед)фу для ncmcii BSTAND, ВОРТ и BROZN, после чего за- кроете редактор полей и редактор таблиц.
Поместите на форму сетку DataGrid (категория Data Controls).
/[ял cBoiicTBa Datasource сетки задайте значение Dat^Tablel н запустите программу (рис. 2.23).
<■*_, ч >*2、•屮〉L«<#'4»<^W^*X + V'-*-'•吟 У
Яь- №»^ ие ние наэмннл и сокрытм» noh
;萨吟窖联網轡И憑婢鹘寰
\ ;
親:總
‘經聘?耳
№
■ Название
;Автор
i Иаа-90
Сгрвниц) Кол^о
:Цена
上1
*-1
10 емнут на доок MS Word 2000
Эйгкен
Вильямс
208
е
26.44
2
10 минут на урок Windows 9Э
Фултон
Диалектика
256
17
14.199
3
10 минут на урок Освой самостоягес
Фултон
Вильямс
224
27
2В.44
4
100 ког-шонвнтм общего назначения
Архангельск
Бином
272
1
40
5
1001 секрет реестра WirKiows NT
Дэниелс
Русская Ред
320
35
35,011
&
12 уроков тенниса.Самый доступный
Ннч於
Т ерра-Спорт
30
Б
10
13 шйгов к успеху или практические
Полигбхш«а
91
33
4
…泠
1С Е|ухгаптерилСамоучигель.Версии
Комягин
Триумф
400
23
131.25
3
3D Studio МАХ 2.5 справочник
Маров
Питер
672
8
44,117
w
3D Studio МАХ Э.ичеб(-ый курс + CD-
Маров
Питер
640
6
78.75
11
3D 5 2小。MAX R3.Спецэффекты и а
Белл
ДиАлект^а
400
30
113,37
• 2
30 Stucbo МЛХ Внутренний мир. Том
Зспином-Зг
ДивСоФг
432
6
105
30 Sludio Мах ЗОот объекта до ани
Кулагин
BHV-Санкт-
480
8
74,25
Рис. 2.23. Окно работающей программы
CuoiicrBo ТAbleMappings адаптера не может построить схему полей для сложных запросов, объединяющих поля нескольких таблиц.
Еще один способ изменения названий — формирование запросов SELECT в компоненте BdpDataAdapter с использованием псевдонимов полей. Для создания псевдонима сразу за названием выбираемого поля ставятся зарезервированное слово AS и собственно псевдоним. С помощью показанного ниже запроса создается окно краткого справочника книг (рмс. 2.24):
既«,嚟綴胱更g>「j^» ; " 二二「
• Нд»вАкие
10 минут на урок MS Word 2000
i Автор Зйгкен
$и赧*
Вильямс
Год 1999
$ Стран 工而…
Кол-во Г"…“
Цена
3林“
;2
10 минут на урок Windows 98
Фу/тгон
Диалектика
1999
256
17
14,189
10 мин^г на урок.Осеой самостоятел
Фултон
Вильямс
1999
224
27
28,44
-4
100 компонентов обшего назначения
Архангельск
Бином
1999
272
1
40
j5
1001 секрет реестра Windows NT
Дэниелс
Русская Рад
1999
320
35
35.011
「'后
12 уроков тенниса. Самый доступный
Янч^
Терра-Спорт
1999
30
6
10
】7
13 шагов к успеху или практические с
(не определе
Политехника
1998
91
39
4
JS
1С:Е 加 алте^мя Самоучитель В^сии
Комягин
Триумф
1999
400
23
131.25
3D Studio МАХ 2.5 справочник
Маров
Питер
1999
Б72
е
44.117
JO
3D Studio МАХ З.Учебный курс + CD-
Маров
Питер
1999
Б40
6
78,75
11
3D Studio МАХ АЗ.СлецэФФемы иди
Белл
Диалектика
2000
400
30
113.37
—-J12
融 Studio МАХ.8ндтремний мир.Том 2
3 спиноза-3 г
ДиаСоФт
1997
432
6
105
<1
J
Рис. 2.24. Изменение названий полей с помощью запроса
SELECT
BOOKID AS "№" , BNAME AS "Название" , BAUTHOR AS иАвтор", BPUBL工SH AS "Изд-во", BYEAR AS "Год", BPAGES AS "Стран”, BQUAN AS "Кол-во", BPRICE AS "Цена"
FROM
BOOKS
ORDER BY
BOOKID
Если псевдоним поля содержит символы К1гриллш[ы, ок должен обрамляться двойными кавычками.
Обратите внимание на раздел ORDER BY. Если его убрать из запроса, ключевое поле BOOKID окажется «закрыто» псевдонимом № и не сможет участвовать в сортировке записей (в этом случае сортировка идет по первому слева строковому столбцу BNAME).
Data Row — записи
В таблице DataTable определено свойство Rows, открывающее доступ к коллекции записей таблицы (объектов класса DataRow). Эти объекты вместе с объектами DataColumn и составляют таблицу.
В табл. 2.19 описаны некоторые свойства записей.
Таблица 2.19. Свойства класса DataRow
Свойство
Описание
property HasError: Boolean;
Содержит True, если в записи есть ошибки
property Item (Field: String): Object;
Открывает доступ к содержимому поля Field записи (см. перегруженные свойства)
property ItemArray: array of Obj ect;
Представляет все поля записи в виде массива
property RowState: DataRowState; Определяет состояние записи
Свойство item открывает доступ к нужному полю текущей записи для получения или установки его значемия. Если вы взглянете на рис. 2.23, то увидите, что цифры в колонке Цена не соответствуют денежному представлению. Чтобы округлить цену до не более чем двух цифр после запятой, измените программу следующим образом:
inplenientation uses
Borland,VCL.SysUtils;
constructor TWinForml.Create;
var
k: DataRow;
begin
inherited Create;
// Reguired for Windows Foe Designer support
InitializeComponent;
П
// TODO: Add any constructor code after InicializeComponent call //
for k in DataSetl.Tables[0].Rows do
k.Item['Цена'1 := FloatToStrF(k.Item['Цена'] as Double,
ffNumber, 10, 2); end;
На рис. 2.25 показано окно программы.
Обратите внимание на оператор присваивания:
k.Item['Цена'] := FloatToStrF(к.Item[*Цена*] as Doublе,
ffNumber, 10, 2);
В нем левая часть имеет тип Double (значение в колонке), а правая — тип String. Тем не менее компилятор не сообщит о несовместимости типов, а обратится к методу Double.Parse для преобразования строки к типу Double.
ПРИМЕЧАНИЕ
При отображетг» данных путем привязки можно использовать события Format и Parse класса Binding для придания данным желаемого вкда. Подробнее об этом ckl далее разде;1 4 Использование свойства DataBindings визуальных компонентов».
'甯福認牆;в^^₽ 廟 2』田E<,・e®^丽7嚇七痘凿
?^ Название
:Автор
Изд-во
;Стран
:Кол-ва
;Цена
10 мин/г на
Зйгкен
Вильямс
1399
2DS
6
20.44
10 минут на
Фултон
Диалектика
1999
256
17
14.19
4
10 минут на
Фултон
Вильямс
1999
224
27
28.44
4
100 помпоне
Арханге/шск
Б word
1ЭЭ9
272
1
40
•汚
1001 секрет
ХЬниелс
Русская Ред
1999
320
35
35,01
;6
12 уроков те
Янчук
Терра-Спорт
1399
30
6
10
::7
13 шаг8 K у
(не олределв
Политехника
1ЭЭ8
91
зэ
4
1С.Бухгалте
Комягин
Триумф
1993
400
23
131.25
■ ;9
簿 Studio МА
Маров
Питер
1999
672
8
44,12
10
3D Studio МА
Маров
Питер
19Э9
Б40
6
78.75
3D Studio МА
Белл
Диалектика
2000
400
30
113J7
,12
X)Studio МА
Зспиноза-Эг
ДиаСскрт
1Э97
432
е
Ю5
簿 Studio Ma
Кулагин
BHV-Санкт-
1999
480
8
74,25
Рис. 2.25. Округление поля «Цена»
Перечисление DataRowState представлено в табл. 2.20.
Таблица 2.20« Перечисление DataRowState
Элемент перечисления
Описание
A'dded
Запись присоединена к таблице, но метод AcceptChanges нс вмзнвался
Deleted
Запись удалена, но метод AcceptCh^nges нс вызывался
Detached
Запись только что создана, но пс является еще частью таблицы
Modified
Запись изменена, по мсто;( AcceptChanges не вызывался
Unchanged
Запись нс изменялась с момента последнего вызова метода
AcceptChanges
В табл. 2.21 представлены методы класса Dat a Row.
Таблица 2.21. Методы класса DataRow
Метод
Описание
procedure AcceptChanges;
Подтверждает все сделанные в записи изме- ЛСШ1Я
procedure BeginEdit:;
Переводит запись в режим редактирования
procedure Cancel Edit.;
Запершаег режим редактирования записи и откатывает все сделанные в записи изменения
procedure ClearErrors;
Удаляет ошибки из полей записи
procedure Delete;
Удаляет текущую запись
procedure EndEdi匸;
Завершает режим редактирования записи
4 Зак 449
Таблица 2.21 (продолжение)
Метод
Описание
function GetChildRows(DR:
DataRelation): array of DataRow;
Возвращает все детальные записи по реляционной связи DR (см. перегруженные методы)
function GetColumnError: String;
Возвращает строку описания ошибки
function GetColumnsInError: array of DataColumn;
Возвращает массив полей с ошибками
function GetParentRow(DR: DataRelation): DataRow;
Возвращает главную запись по реляционной связи DR (см. перегруженные методы)
function GetParentRows(DR:
DataRelation): array o£ DataRow;
Возвращает массив главных записей по реля* ционной связи DR (см. перегруженные методы)
function HasVersion(Version:
DataRowVersion): Boolean;
Возвращает True, если для записи есть указанная версия
function IsNull(Column:
DataColumn): Boolean
Возвращает True, если указанное поле пустое (см. перегруженные методы)
procedure Rej ectChanges;
Откатывает все изменения, сделанные в записи после последнего вызова AcceptChanges
procedure SetColumnError(Column:
DataColumn; Error: String);
Устанавливает для поля Column описание ошибки Error (см. перегруженные методы)
procedure SetNull(Column:
DataColumn);
Устанавливает в поле Column пустое значение
procedure SetParentRow(Parent:
DataRow);
Назначает запись Parent в качестве главной записи
Метод BeginEdit вызывается неявно, когда пользователь начинает изменять величину какого-либо поля записи в визуализирующем компоненте. Также неявно вызывается метод EndEdit при обращении к методу AcceptChanges. Между этими обращениями создаются две версии записи: DataRowVersion. Original и DataRowVers ion • Proposed. Наличие той или иной версии можно проверить методом HasVersion. При обращении к нему используется такое перечисление DataRowVersion:
Current — запись содержит текущие значения;
Default — запись содержит значения, зависящие от значения свойства DataRowState (если оно имеет значение Added, Modified или Current, запись содержит версию Current, если Deleted — версию Original, если Detached — версию Proposed);
Original — запись содержит исходные значения;
Proposed — запись содержит измененные значения.
После выполнения метода BeginEdit становятся доступны версии Current и Proposed. После вызова метода CancelEdit версия Proposed уничтожается. После вызова EndEdit версия Proposed становится версией Current. После вызова AcceptChanges версия Original становится идентичной версии Current.
Наконец, после обращения к методу Rejectchanges версия Proposed уничтожается, а запись получает версию Current.
Визуализация данных
Для визуализации данных в ADO.NET используется сетка DataGrid (категория Data Controls палитры компонентов) и свойства DataBindings всех остальных визуальных компонентов.
DataGrid — сетка данных
Сетка DataGrid (категория Data Controls) позволяет визуализировать сразу множество записей, представляя их в табличной форме. В ней предусмотрен специальный механизм одновременной демонстрации главной записи и всех связанных с ней детальных записей. Данные, представленные в строковой форме, можно редактировать непосредственно в сетке.
Для редактирования щелкните на нужной ячейке и введите новый текст. Для удаления записи щелчком мыши на служебном столбце выделите ее и нажмите клавишу Delete. Для ввода новой записи переместите указатель текущей записи к самой последней (пустой) строке и начните заполнение полей.
Помните, что все изменения происходят с данными, хранящимися в DataSet. Чтобы откатить сделанные изменения, используйте метод Rej ectChanges нужной таблицы компонента DataSet. Например:
DataSet1.Tables[0].Rejectchanges;
Чтобы подтвердить изменения и зафиксировать их в БД, используйте метод Update компонента BdpDataAdapter. Например:
BdpDa匸aAdapUerl.Update(Da匸aSet工);
ПРИМЕЧАНИЕ
При разработке приложений ASP.NET используется одноименный компонент DataGrid, но из пространства имен system.Web.Ul. WebControls. Описываемый в этом разде* ле класс DataGrid принадлежит пространству имен Sys Cem. Windows. Forms. Не= смотря на сходство названий, эти классы имеют разные свойства, методы и события.
Свойства компонента
В табл, 2.22. представлены свойства компонента.
Таблица 2.22. Свойства класса DataGrid
СвойствоОписав ие
property AllowNavigation: Boolean; Разрешает или запрещает навигацию по сетке
property AllowSorting: Boolean; Разрешает или запрещает сортировку данных по выбранному полю
100 Глава 2 • Технология ADO.NET
Таблица 2,22 (продолжение)
Свойство
Описание
property AlternatingBackColor:
Определяет цвет фона всех четных записей
Color;
(если считать записи, начиная с 1)
property BackColor: Color;
Определяет цвет фона всех нечетных записей (если считать записи, начиная с 1)
property Backgroundcolor: Color;
Определяет цвет той части компонента, которая не занята записями
property Background工mage: Image;
Определяет фоновый рисунок
property Borderstyle: Borderstyle;
Определяет стиль рамки
property CaptionBackColor: Color;
Определяет фоновый цвет заголовка сетки
property CaptionFont: Font;
Определяет шрифт заголовка сетки
property CaptionForeColor: Color;
Определяет цвет шрифта заголовка сетки
property CaptionText: String;
Текст заголовка
property CaptionVisible: Boolean;
Разрешает или запрещает показ заголовка
property ColuinnHeadersVisible:
Разрешает или запрещает показ названий
Boolean;
полей
property Currentcell: DataGridCell;
Возвращает ячейку с фокусом ввода
property CurrentRowIndex: Integer;
Возвращает индекс записи с фокусом ввода
property Datasource: Object;
Содержит ссылку на источник данных
property FirstVisibleColumn:
Возвращает индекс первого видимого в сет-
Integer;
ке поля
property GridLineColor: Color;
Определяет цвет линий сетки
property GridLineStyle:
DataGridLineStyle;
Определяет стиль линий
property HeaderBackColor: Color;
Определяет фоновый цвет строки с названиями полей и столбца с указателем текущей записи
property HeaderFont: Font;
Определяет шрифт строк с названиями полей
property HeaderForeColor: Color;
Определяет цвет названий полей
property Item(CataGridCell):
Открывает доступ к содержимому указанной
Object;
ячейки (см. перегруженные свойства)
property Linkcolor: Color;
Определяет цвет надписи с названием реляционной связи, щелчок на которой показывает детальную таблицу
property ParentRowsBackColor:
Определяет фоновый цвет записей главной
Color;
таблицы
property ParentRowsForeColor: Color;
Определяет цвет записей главной таблицы
Визуализация данных 101
Свойство
Описание
property ParentRowsLabelStyle:
Определяет способ показа названий главной
DataGridParentRowsLabelStyle;
таблицы м ее поля
property ParentRowsVisible:
Разрешает или запрещает показ главной за-
Boolean;
писи
property Readonly: Boolean;
Разрешает или запрещает редактирование ячеек сетки
property RowsHeaderVisible:
Разрешает или запреидает показ столбца с ука-
Boolean;
зателем текущей записи
property RowsHeaderWidth: Integer;
Определяет ширину столбца с указателем текущей записи
property SelectionBackColor:
Определяет фоновый цвет ячейки с фоку-
Color;
сом ввода
property SelectionForeColor:
Определяет цвет текста ячейки с фокусом
Color;
ввода
property Tablestyles:
Содержит коллекцию объектов DataGrid-
GridTableStyleCollection;
Tablestyle, определяющих стили отображения таблиц
Свойство AllowNavigation, как сказано в документации, должно разрешать или запрещать перемещение по записям в сетке. Однако на практике мне не удалось добиться запрета навигации.
Свойство AllowSorting по умолчанию имеет значение True. В этом случае щелчок на заголовке любого поля приводит к сортировке записей по значениям этого поля.
Свойство Borderstyle может принимать одно из следующих значений:
Fixed 3D — трехмерная рамка;
FixedSingle — рамка из одной линии;
None — нет рамки.
По умолчанию оно имеет значение Fixed3D.
Свойство GridLineStyle может иметь значение Solid (по умолчанию) или None.
Свойство ParentRowsLabelStyle определяет вид главной записи в режиме демонстрации связанных с ней детальных записей. Оно может иметь одно из следующих значений:
Both — показываются имя таблицы н все поля главной записи (по умолча- Ш!Ю);
ColumnName — показываются только поля главной записи;
None — ничего не показывается;
Та bl eName — показывается только имя главной таблицы.
Главная запись выводится над детальными записями (см., например, рис. 2.8).
Использование стилевых объектов
Наиболее интересным является свойство Tablestyles, определяющее особенности отрисовки таблицы данных в компоненте. С помощью этого свойства создаются стилевые объекты, содержащие индивидуальные параметры отрисовки каждой таблицы и каждого поля. Компонент может показывать множество таблиц из связанного с ним набора данных, например главную и детальную. Для каждой из них в коллекции Tablestyles можно предусмотреть свой объект DataGridTableStyle, который перекрывает следующие свойства сетки:
AllowSorting;
AlternatingBackColor;
BackColor;
ColumnHeadersVisible;
ForeColor;
GridLineColor;
GridLineStyle;
HeaderBackColor;
HeaderFont;
HeaderForeColor;
LinkColor;
PreferredColumnWidth;
PreferredRowHeight;
Readonly;
RowHeadersVisible;
RowHeaderWidth;
SelectionBackColor;
SelectionForeColor.
Объект DataGridTableStyle имеет свойство GridColximnStyles, открывающее доступ к объектам DataGridColumnStyle. Каждый из этих объектов создается для одного из полей таблицы и содержит свойства, управляющие отображением поля в сетке, в том числе:
Alignment;
HeaderText;
MappingName;
Width.•
Последовательность работы с объектами стилей такова:
Создается объект DataGridTableStyle.
В его свойство MappingName помещается имя таблицы и нужным образом настраиваются другие его свойства.
Создается объект DataGridColuinnStyle. Поскольку этот класс — абстрактный, для его создания используются конструкторы классов DataGridBoolColumn (для логических полей) или DataGridTextBoxColumn (для остальных полей).
В объекте DataGridColiimnStyle в свойство MappingName помещается имя отображаемого поля и при необходимости изменяются другие его свойства, после чего объект вставляется в коллекцию GridColumnStyles объекта DataGridTableStyle.
Шаги 3 и 4 повторяются для всех полей, которые следует отобразить в сетке. Порядок размещения объектов DataGidColwnnStyle в коллекции GridColumns- Styles определяет порядок их отображения (слева направо) в сетке. Поля, для которых не созданы стилевые объекты, отображаться в сетке не будут.
После того как объект DataGridTableStyle полностью подготовлен, он вставляется в коллекцию Tablestyles сетки DataGrid.
Все описанные действия должны выполняться на этапе прогона программы. В то же время свойство Tablestyles объекта DataGrid имеет редактор, позволяющий создавать стили таблиц и полей на этапе конструирования. Однако факти* чески с его помощью можно создавать лишь стили таблиц: после вставки объекта DataGridTableStyle и привязки его к нужной таблвде все стилевые объекты для полей таблицы создаются автоматически. Дальнейшие изменения этих объектов в редакторе на стилях полей никак не отражаются.
Для иллюстрации изложенного начните новое приложение WinForms (проект ChO2\Styles\Styles.dpr), на пустую форму поместите компонент DataGrid и его свойству Dock присвойте значение Fill. Выберите в меню команду View » DataExplorer и перетащите таблицу Types на компонент DataGrid. Добавьте к форме компонент DataSet, в свойстве DataSource компонента BdpData- Adapter сошлитесь на этот набор данных и откройте адаптер (поместите True в его свойство Active). В свойство DataSource сетки поместите ссылку на таблицу DataTablel. Подготовьте указанный ниже обработчик события Load формы:
procedure TWinForml.TWinForml_Load(sender: System.Object; e: System.EventArgs);
var
TabStyle: DataGridTableStyle;
ColStyle: DataGridColuinnStyle;
begin
// Создаем объект DataGridTableStyle:
TabStyle := DataGridTableStyle.Create;
// Связываем его с таблицей TYPENAKL:
TabStyle.MappingName := DataSetl.Tables[0].TableName;
/ / Другой вариант: TabStyle.MappingName ; = *TYPENAKL *
/ / Выделяем цветом нечетные ячейки:
TabStyle.AlternatingBackColor := System.Drawing.Color.Yellow;
104 Глава 2 • Технология ADO.NET
// Создаем 1-й объект DataGridCoJwnnSty2e:
ColStyle := DataGridTextBoxColumn.Create;
// Связываем его с полем TypelP:
ColStyle.MappingName :- 'TypelD';
/ / Задаем название колонки:
ColStyle.HeaderText :=
// Текст - прижать вправо:
ColStyle.Alignment := HorizontalAlignment.Right;
/ / Ус та на влив а ем ширину колонки:
ColStyle.Width := 25;
// Помещаем стиль в коллекцию:
TabStyle.GridColmnnStyles.Add(ColStyle);
// Создаем 2-ю колонку:
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := 'TName';
ColStyle.HeaderText := 'Тип накладной';
ColStyle.Alignment := HorizontalAlignment.Center;
ColStyle.Width := 150;
TabStyle.GridColumnStyles.Add(ColStyle);
// Объект Da t aGridTab1eSty1e готов. Добавляем его в коллекцию: DataGridl.TableStyles.Add(TabStyle);
end;
Вид окна работающей программы показан на рис. 2.26.
Методы компонента
В табл. 2.23 перечислены методы компонента.
Использование свойства DataBindings визуальных компонентов
При первом знакомстве с ADO.NET поражает отсутствие каких бы то ни было компонентов для визуализации отдель- Риа 2.26. Демонстрация стилевых объектов ных 口。"ей записи. В то же время в практике работы с БД помимо сеточного представления множества записей широко используются так называемые формы. служащие для редактирования отдельной записи. Такого рода формы представляют собой контейнер (панель, форма м т. п.) с визуальными компонентами, каждый из которых связан с отдельным полем редактируемой записи.
В классе Control определено такое свойство:
property DataBindings: ControlBindingsCollection;
1Г^
1
2
3
4
5
6
7
8
Поставка не реализациюПрэдажа не реализациюВозврат поставкиВозврат лроаажиПрихсйпо.оСй*^
Уход по обме^Поставка с предоплатойПродажа с предоплатойБрак
吗
Таблица 2.23. Методы класса DataGrid
Метод
Описание
function BeginEdit(GridColumn: DataGridColumnStyle; RowNumber: Integer): Boolean;
Переводит ячейку в режим редактирования и возвращает True в случае успешной операции
procedure CancelEditing;
Прекращает редактирование и откатывает все изменения
function CreateDataGridColumn (ColProp: PropertyDescriptor): DataGridColumnStyle;
Создает новую колонку с заданными свойствами
function EndEdit (GridColunin: DataGridColumnStyle; RowNumber: Integer; ShouldAbort: Boolean): Boolean;
Требует завершения редактирования указанной ячейки и возвращает True и случае успешного завершения. Параметр Should- Abort должен иметь значение True, если требуется прервать текущий процесс
procedure Expand(Row: Integer);
Показывает детальные записи для указанной главной
function GetCellBounds (Row, Column: Возвращает границы заданной ячейки (см. Integer): Rectangle;перекрытые методы)
finction GetCurrentCellBounds: Rectangle;
Возвращает границы ячейки с фокусом ввода
function HetTest(P: Point): HitTestlnfo;
Возвращает объект HitTestlnfо, содержащий информацию 0 свойствах DataGrid в заданной точке р
function IsExpanded (RowNuinber: Integer): Boolean;
Возвращает True, если плавная запись RowNumber сопровождается показом связанных с ней детальных записей
function IsSelectedfRow: Integer):
Boolean;
Возвращает True, если запись Row имеет фокус ввода
procedure NavigateBack;
Сворачивает детальные записи и показывает главную таблицу
procedure NavigateTo(Row: Integer;
RelationName: String);
Показывает детальные записи для записи Row и реляционной связи RelationName
procedure Select(Row: Integer);
Передает фокус ввода указанной записи
procedure SetDataBinding(DS:
DataSet; Tabi: String);
Связывает компонент с нужным набором данных и его таблицей
procerure UnSelect(Row: Integer);
Удаляет фокус ввода из указанной записи
Поскольку класс Control является родоначальником всех визумьных компонентов, свойство DataBinding получают все его потомки.
Это свойство открывает доступ к коллекции ControlBindingsCol lection, содержащей объекты Binding. Каждый объект коллекции устанавливает связь между
каким-либо свойством визуального компонента и полем БД. В результате любоИ визуальный компонент библиотеки WinFornis может отображать данные из БД. Свойство DataBindings — сложное, н обычно оно свернуто, о чем сигнализирует значок слева от него. Щелчок на значке разворачивает два или три подсвойства, в том числе Advanced и Тад. Именно эти подсвойства визуального компонента могут отображать данные. Если среди них нет нужного, следует щелкнуть на кнопке в строке подсвойства Advanced. В результате раскрывается окно расширенной привязки, показанное на рис. 2.27.
ForeColofImage:ImageAtign:Imagelndex:*lrr^#b 就Location:HightToLeH,TaUndex-TebStqp4 Тад:箱喇縫:>展年,孤咏、,麻ForeColofImage:ImageAtign:Imagelndex:*lrr^#b 就Location:HightToLeH,TaUndex-TebStqp4 Тад:箱喇縫:>展年,孤咏、,麻","","6T,⑴"^^ ^ ^ ^^ w.^-нw","","6T,⑴"^^ ^ ^ ^^ w.^-нwРис. 2.27. Расширенная привязкаРис. 2.27. Расширенная привязка
ForeColof
Image:
ImageAtign:
Imagelndex:
*lrr^#b 就
Location:
HightToLeH
,TaUndex
-TebStqp
4 Тад
:箱喇縫:>展年,孤咏、,麻
ForeColof
Image:
ImageAtign:
Imagelndex:
*lrr^#b 就
Location:
HightToLeH
,TaUndex
-TebStqp
4 Тад
:箱喇縫:>展年,孤咏、,麻
","","6T,⑴"^^ ^ ^ ^^ w.^-нw
","","6T,⑴"^^ ^ ^ ^^ w.^-нw
Рис. 2.27. Расширенная привязка
Рис. 2.27. Расширенная привязка
■□^DataBindin; l(Advance(Тз;(Нет):»iTextЧНет)■□^DataBindin; l(Advance(Тз;(Нет):»iTextЧНет)鋁 О Da*aTabte1 図 800KI0 (Vj 6NAMEi ⑶ BAUTHOfl;□ BPUBUSH ГЛ 9YEAR鋁 О Da*aTabte1 図 800KI0 (Vj 6NAMEi ⑶ BAUTHOfl;□ BPUBUSH ГЛ 9YEARРис. 2.28. Связываниесвойства визуальногокомпонента с полемтаблицы БДРис. 2.28. Связываниесвойства визуальногокомпонента с полемтаблицы БДВ этом окис представлены все свойства компонента. Выберите нужное (обычно — Text ил» Value) и закройте окно. После этого список свойств дополнится нужным. Чтобы указать поле БД, которое будет отображать это свойство» щелкните на кнопке в строке свойства (рис, 2.28). В раскрывшемся списке щелкните па нужном поле. В реВ этом окис представлены все свойства компонента. Выберите нужное (обычно — Text ил» Value) и закройте окно. После этого список свойств дополнится нужным. Чтобы указать поле БД, которое будет отображать это свойство» щелкните на кнопке в строке свойства (рис, 2.28). В раскрывшемся списке щелкните па нужном поле. В результате свойство визуального компонента в работающей программе будет отображать значение поля в текущей записи таблицы БД, и изменение отображаемого значения визуального компонента приведет к изменению значения поля в таблице.зультате свойство визуального компонента в работающей программе будет отображать значение поля в текущей записи таблицы БД, и изменение отображаемого значения визуального компонента приведет к изменению значения поля в таблице.
■□^DataBindin; l(Advance(
Тз;(Нет)
:»iTextЧНет)
■□^DataBindin; l(Advance(
Тз;(Нет)
:»iTextЧНет)
鋁 О Da*aTabte1 図 800KI0 (Vj 6NAME
i ⑶ BAUTHOfl
;□ BPUBUSH ГЛ 9YEAR
鋁 О Da*aTabte1 図 800KI0 (Vj 6NAME
i ⑶ BAUTHOfl
;□ BPUBUSH ГЛ 9YEAR
Рис. 2.28. Связываниесвойства визуальногокомпонента с полемтаблицы БД
Рис. 2.28. Связываниесвойства визуальногокомпонента с полемтаблицы БД
В этом окис представлены все свойства компонента. Выберите нужное (обычно — Text ил» Value) и закройте окно. После этого список свойств дополнится нужным. Чтобы указать поле БД, которое будет отображать это свойство» щелкните на кнопке в строке свойства (рис, 2.28). В раскрывшемся списке щелкните па нужном поле. В ре
В этом окис представлены все свойства компонента. Выберите нужное (обычно — Text ил» Value) и закройте окно. После этого список свойств дополнится нужным. Чтобы указать поле БД, которое будет отображать это свойство» щелкните на кнопке в строке свойства (рис, 2.28). В раскрывшемся списке щелкните па нужном поле. В ре
зультате свойство визуального компонента в работающей программе будет отображать значение поля в текущей записи таблицы БД, и изменение отображаемого значения визуального компонента приведет к изменению значения поля в таблице.
зультате свойство визуального компонента в работающей программе будет отображать значение поля в текущей записи таблицы БД, и изменение отображаемого значения визуального компонента приведет к изменению значения поля в таблице.
Пример создания формы
Для иллюстрации сказанного служит программа (проект Ch02\Form\Form.dpr)T окно которой показано на рис. 2.29.
iCWH^lRr [ —r「,iCWH^lRr [ —r「,1 10 г^««р н# фс*< MS Woid 200021#О0«Г M я»жW*OB3 10 *««1ут нл уро ОсжзА САгоетепгелып MS Ек«120004 (ф'4«йпт^«Й^^,5 1001 секрет рмспм Wrdowt МТ7〔Зшагсв к.产п^нлилр«ктнч*с,и*«*еп||Аая бып^одо^м*к«шюВ i^^^iiif^l^^^?.)' н 7-^ # «*ЦЖ«К. к .««егмj .由第枷修:й^1Шый®к£・ан»мП X> Shudo MM< Q3 匸пашфмкт м дим^н ♦ 8 ROM%..仪房.*|》0ХР 而方f«JiM•“ CWWM;13 3D Shdo Ma 3 Осп р*вк"at>»мчи~ * 820мj,*3ййй^*^й^йд^пйм«15 98 вопросе» пс Wndowt 90 с отмт»«4Л RaH 加隸麻Тй爾Цсктшму:17 Accetx 97 Р^мжстк по ь^мхмм(у и VBA • CD RDM. .14Акмс^^М>*и«П*Й»ПМ«4Й^^]§ AdMratrems SQL Sie 7. Сергифжмю*» jк ммнокстrework70-021 10 г^««р н# фс*< MS Woid 200021#О0«Г M я»жW*OB3 10 *««1ут нл уро ОсжзА САгоетепгелып MS Ек«120004 (ф'4«йпт^«Й^^,5 1001 секрет рмспм Wrdowt МТ7〔Зшагсв к.产п^нлилр«ктнч*с,и*«*еп||Аая бып^одо^м*к«шюВ i^^^iiif^l^^^?.)' н 7-^ # «*ЦЖ«К. к .««егмj .由第枷修:й^1Шый®к£・ан»мП X> Shudo MM< Q3 匸пашфмкт м дим^н ♦ 8 ROM%..仪房.*|》0ХР 而方f«JiM•“ CWWM;13 3D Shdo Ma 3 Осп р*вк"at>»мчи~ * 820мj,*3ййй^*^й^йд^пйм«15 98 вопросе» пс Wndowt 90 с отмт»«4Л RaH 加隸麻Тй爾Цсктшму:17 Accetx 97 Р^мжстк по ь^мхмм(у и VBA • CD RDM. .14Акмс^^М>*и«П*Й»ПМ«4Й^^]§ AdMratrems SQL Sie 7. Сергифжмю*» jк ммнокстrework70-02^^^^35 35.D1135 35.D11・«89飞.%:&В1细.*^8"" •&'.2.・«89飞.%:&В1细.*^8"" •&'.2.гИм^ГМ»СЖ1:6fРуссам Ршаг.з 1AИ模版*w举;:Попит м«».аДи&|МК,4,>.АйСйт;.:、• gHVCfr Ямервирг::25向《*гПОРИ二加唸";..:三:гИм^ГМ»СЖ1:6fРуссам Ршаг.з 1AИ模版*w举;:Попит м«».аДи&|МК,4,>.АйСйт;.:、• gHVCfr Ямервирг::25向《*гПОРИ二加唸";..:三:1999 200 5&N001網尋М«»вО 1 然9 224 5-845900Г 较9JS 亨 Е®:”:%:19 99 ЭЛ 5 7502-00121999 200 5&N001網尋М«»вО 1 然9 224 5-845900Г 较9JS 亨 Е®:”:%:19 99 ЭЛ 5 7502-001219»91 59*№«50.;Wl-*XtW9W: ;> &19» 672 MM&g 6/1W: W:$W<tt:守 血 saUg.g 1019»91 59*№«50.;Wl-*XtW9W: ;> &19» 672 MM&g 6/1W: W:$W<tt:守 血 saUg.g 10В 423 J 丸350 44 117:”мл・В 423 J 丸350 44 117:”мл・•taw,.4打岷2,二:&二7 ■ 储• 1ЭТ9a7y酶「3;⑤^晔••$•• 5 9.1999 欣 5 93«硝В & 11525•俏;班■wwb•三g :-加■: гал:':•taw,.4打岷2,二:&二7 ■ 储• 1ЭТ9a7y酶「3;⑤^晔••$•• 5 9.1999 欣 5 93«硝В & 11525•俏;班■wwb•三g :-加■: гал:':1®е 590 54SG41®е 590 54SG45121.55121.5.■: ■?. .;. I^'i^;#*'!^?:-':^^//;ЛЙ'^/^l?S :"1939 480 5 3?? 000 Ю 204 8K.■: ■?. .;. I^'i^;#*'!^?:-':^^//;ЛЙ'^/^l?S :"1939 480 5 3?? 000 Ю 204 8KНжоател^тв •;——|Вильямс:Год .用^Стрлммц 质Нжоател^тв •;——|Вильямс:Год .用^Стрлммц 质®®.. [5-8^9-0051-V•瓦吧包挺®®.. [5-8^9-0051-V•瓦吧包挺Ценз слоеная оеок .Ценз слоеная оеок .КОЛНЧ«€ТЮ' j^™Цвмалокцпн&я 卜8】КОЛНЧ«€ТЮ' j^™Цвмалокцпн&я 卜8】Цвмббтл^окмв* а розницуЦвмббтл^окмв* а розницу一叫噁.JnafiTBcpjBMTbJ.一叫噁.JnafiTBcpjBMTbJ.
iCWH^lRr [ —r「,
iCWH^lRr [ —r「,
1 10 г^««р н# фс*< MS Woid 2000
21#О0«Г M я»жW*OB
3 10 *««1ут нл уро ОсжзА САгоетепгелып MS Ек«12000
4 (ф'4«йпт^«Й^^,
5 1001 секрет рмспм Wrdowt МТ
7〔Зшагсв к.产п^нлилр«ктнч*с,и*«*еп||Аая бып^одо^м*к«шю
В i^^^iiif^l^^^?.)' н 7-^ # «*ЦЖ«К. к .««егм
j .由第枷修:й^1Шый®к£・ан»м
П X> Shudo MM< Q3 匸пашфмкт м дим^н ♦ 8 ROM
%..仪房.*|》0ХР 而方f«JiM•“ CWWM
;13 3D Shdo Ma 3 Осп р*вк"at>»мчи~ * 820м
j,*3ййй^*^й^йд^пйм«
15 98 вопросе» пс Wndowt 90 с отмт»«4
Л RaH 加隸麻Тй爾Цсктшму
:17 Accetx 97 Р^мжстк по ь^мхмм(у и VBA • CD RDM
. .14Акмс^^М>*и«П*Й»ПМ«4Й^^
]§ AdMratrems SQL Sie 7. Сергифжмю*» jк ммнокстrework70-02
1 10 г^««р н# фс*< MS Woid 2000
21#О0«Г M я»жW*OB
3 10 *««1ут нл уро ОсжзА САгоетепгелып MS Ек«12000
4 (ф'4«йпт^«Й^^,
5 1001 секрет рмспм Wrdowt МТ
7〔Зшагсв к.产п^нлилр«ктнч*с,и*«*еп||Аая бып^одо^м*к«шю
В i^^^iiif^l^^^?.)' н 7-^ # «*ЦЖ«К. к .««егм
j .由第枷修:й^1Шый®к£・ан»м
П X> Shudo MM< Q3 匸пашфмкт м дим^н ♦ 8 ROM
%..仪房.*|》0ХР 而方f«JiM•“ CWWM
;13 3D Shdo Ma 3 Осп р*вк"at>»мчи~ * 820м
j,*3ййй^*^й^йд^пйм«
15 98 вопросе» пс Wndowt 90 с отмт»«4
Л RaH 加隸麻Тй爾Цсктшму
:17 Accetx 97 Р^мжстк по ь^мхмм(у и VBA • CD RDM
. .14Акмс^^М>*и«П*Й»ПМ«4Й^^
]§ AdMratrems SQL Sie 7. Сергифжмю*» jк ммнокстrework70-02
^^
^^
35 35.D11
35 35.D11
・«89飞.%:&В1细.*^8"" •&'.2.
・«89飞.%:&В1细.*^8"" •&'.2.
гИм^ГМ»СЖ1
:6f
Руссам Ршаг.з 1AИ模版*w举;:
Попит м«».а
Ди&|МК,4,
>.АйСйт;.:、• gHVCfr Ямервирг
::25向《*г
ПОРИ
二加唸";..:三:
гИм^ГМ»СЖ1
:6f
Руссам Ршаг.з 1AИ模版*w举;:
Попит м«».а
Ди&|МК,4,
>.АйСйт;.:、• gHVCfr Ямервирг
::25向《*г
ПОРИ
二加唸";..:三:
1999 200 5&N00
1網尋М«»вО 1 然9 224 5-845900
Г 较9JS 亨 Е®:”:%:19 99 ЭЛ 5 7502-0012
1999 200 5&N00
1網尋М«»вО 1 然9 224 5-845900
Г 较9JS 亨 Е®:”:%:19 99 ЭЛ 5 7502-0012
19»91 59*№«50
.;Wl-*XtW9W: ;> &19» 672 MM&g 6
/1W: W:$W<tt:守 血 saUg.g 10
19»91 59*№«50
.;Wl-*XtW9W: ;> &19» 672 MM&g 6
/1W: W:$W<tt:守 血 saUg.g 10
В 423 J 丸350 44 117:”мл・
В 423 J 丸350 44 117:”мл・
•taw,.4打岷2,二:&二7 ■ 储• 1ЭТ9a7y
酶「3;⑤^晔••$•• 5 9.
1999 欣 5 93«硝В & 11525
•俏;班■wwb•三g :-加■: гал:':
•taw,.4打岷2,二:&二7 ■ 储• 1ЭТ9a7y
酶「3;⑤^晔••$•• 5 9.
1999 欣 5 93«硝В & 11525
•俏;班■wwb•三g :-加■: гал:':
1®е 590 54SG4
1®е 590 54SG4
5121.5
5121.5
.■: ■?. .;. I^'i^;#*'!^?:-':^^//;ЛЙ'^/^l?S :"1939 480 5 3?? 000 Ю 204 8K
.■: ■?. .;. I^'i^;#*'!^?:-':^^//;ЛЙ'^/^l?S :"1939 480 5 3?? 000 Ю 204 8K
Нжоател^тв •;——
|Вильямс
:Год .用^
Стрлммц 质
Нжоател^тв •;——
|Вильямс
:Год .用^
Стрлммц 质
®®.. [5-8^9-0051-V
•瓦吧包挺
®®.. [5-8^9-0051-V
•瓦吧包挺
Ценз слоеная оеок .
Ценз слоеная оеок .
КОЛНЧ«€ТЮ' j^™
Цвмалокцпн&я 卜8】
КОЛНЧ«€ТЮ' j^™
Цвмалокцпн&я 卜8】
Цвмббтл^окмв* а розницу
Цвмббтл^окмв* а розницу
一叫噁.JnafiTBcpjBMTbJ.
一叫噁.JnafiTBcpjBMTbJ.
Рис. 2.29. Форма для ввода/редактирования данных о книге
С помощью этой программы можно вводить данные о новой книге в список уже зарегистрированных книг в таблице BOOKS БД «Книголюб», удалять из списка данные о книге и редактировать данные уже существующей в списке книги.
Верхнюю часть окна занимает сетка, отображающая данные сразу для множества книг, нижняя часть представляет собой форму для ввода/ре/шктирования данных о текущей книге — той, на которую указывает значок в служебном столбце сетки. При перемещении этого указателя по записям сетки автоматически меняется информация в компонентах формы.
Для удаления данных о ненужной книге выделите се в сетке щелчком на служебном столбце и нажмите клавишу Delete. Для вставки данных о новой книге переведите указатель записи на самую нижнюю (пустую) запись п начните вводить информацию в поля записи с помощью сетки или компонентов формы. Учтите, что таблица BOOKS содержит данные о более чем 2000 книг, а в сетке отображается лишь га их часть, которая выбрана значениями свойств StarcRecord и MaxRecords адаптера. По умолчанию эти свойства имеют значения 0 и 100 соответственно, то есть в сетке отображается лишь первая сотня книг. Новая запись вставляется в самьпг конец таблицы. Учтите также, что ноле BooklD — автоинкрементное и оно не должно быть пустым. Позтому перед подтверждением ввода новой записи введите в :)то поле любое число — при вставке записи в таблицу БД сработает так называемый триггер, связанный с событием INSERT, и заменит это значение нужным. Подробнее о триггерах см. главы 1 и 7. Ниже прслставлен текст триггера BEF_INS_BOOK:
CREATE TRIGGER BEF_INS„BOOK FOR BOOKS BEFORE INSERT POSITION 0 AS BEGIN
NEW. BOOKID = GEN_工D(GEN_B8KS,i);
END
В следующем листинге представлены обработчики щелчков на кнопках и собы тия Load формы:
procedure TWinForm.btSubmit_Click(sender: System.Object; e: System.EventArgs);
// Подтверждение изменений
begin
BdpDataAdapter1.Update(DataSet1);
end;
procedure TWinForm.btRollBack_Click{sender: System.Object;
e: System.EventArgs);
// Откат изменений
begin
DataSetl.Tables[0].RejectChanges
end;
procedure TWinForm.TWinForm_Load(sender: System.Object;
e: System.EventArgs);
// Создание стилевых объектов сетки
var
Tabstyle: DataGridTableStyle;
ColStyle: DataGridColumnStyle;
begin
Tabstyle := DataGridTableStyle.Create;
Tabstyle.MappingName := * BOOKS';
TabStyle.AlternatingBackColor := System.Drawing.Color.LightGray;
DataGridl.CaptionText := * Список книг';
ColStyle :二 DataGridTextBoxColumn.Create;
ColStyle.MappingNaiiie : = *BookID* ;
ColStyle.HeaderText := *№*;
ColStyle.Alignment := HorizontalAlignment•Right;
ColStyle.V^idth := 30;
TabStyle.GridColumnStyles.Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := *BNAME';
ColStyle.HeaderText := Название1;
ColStyle・Alignment := HorizontalAlignment.Left;
ColStyle.Width := 400;
TabStyle.GridColumnStyles-Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
Col Style. MappingName := ' BAUTHOR1 ;
ColStyle.HeaderText := •Автор *;
ColStyle.Alignment := HorizontalAlignment.Left;
ColStyle.Width := 100;
Tabstyle.GridColuxnnStyles.Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := 'BPUBLISH';
ColStyle.HeaderText := 'Издательство1;
ColStyle.Alignment :二 HorizontalAlignment.Left;
ColStyle.Width := 150;
TabStyle・GridColumnStyles.Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := * BYEAR *;
ColStyle.HeaderText := 'Год1;
ColStyle. Alignment : = HorizontalAlignment * Right ;
ColStyle.Width := 35;
TabStyle.GridColumnStyles-Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := 'BPAGES';
ColStyle.HeaderText := 'Страниц';
ColStyle.Alignment := HorizontalAlignment.Right;
ColStyle.Width := 35;
TabStyle.GridColumnStyles.Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := 'BISBN';
ColStyle.HeaderText := 'ISBN1;
ColStyle.Alignment := HorizontalAlignment•Center;
ColStyle.Width := 60;
TabStyle.GridColumnStyles.Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := 1BSTAND•;
ColStyle-HeaderText := 'В пачке *;
ColStyle.Alignment := HorizontalAlignment.Right;
ColStyle-Width := 30;
TabStyle-GridColuntnStyles .Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle•MappingName := 'SQUAN';
ColStyle.HeaderText := 1 Количество';
ColStyle.Alignment := HorizontalAlignment.Right;
ColStyle.Width := 30;
TabStyle•GridColumnStyles.Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := 'BPRICE *;
ColStyle.HeaderText := 'Цена*;
ColStyle.Aligiiment :二 Horizonta 1A1 ignment.Right;
ColStyle.Width := 50;
TabStyle.GridColumnStyles.Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := 1BOPT1;
ColStyle.HeaderText := 'Оптом';
ColStyle.Alignment := HorizontalAlignment.Right;
ColStyle.Width := 50;
TabStyle.GridColumnStyles. Add(ColStyle);
ColStyle := DataGridTextBoxColumn.Create;
ColStyle.MappingName := ’BROZN';
ColStyle. HeaderText := *B розниц * ;
ColStyle,Alignment := HorizontalAlignment.Right;
ColStyle.Width := 50;
TabStyle.GridColumnStyles.Add(ColStyle); DataGridl.Tablestyles.Add(TabStyle);
end;
Класс Binding
Класс Binding содержит свойства, методы н события, обеспечивающие однозначную привязку визуального элемента к столбцу таблицы DataTable. Свойства класса Binding перечислены в табл. 2.24.
Таблица 2.24. Свойства класса Binding
Свойство
Описание
property BindingManagerBase:
BindigMariagerBase ;
property В i ndingMemberlnf о:
Управляет текущей записью в отображаемых данных
Содержит информацию об отображаемом эле-
BindingMemberlnfо;
property Control: Control;
менте данных
Содержит ссылку на визуальный компонент, отображающий данные
property DataSourse: Object ;
property 工^Binding: Bolean;
property PropertyName: String;
Содержит ссылку на источник данных Содержит True, если объект класса активен Содержит имя свойства визуального компонента, с помощью которого отображаются данные
Объект класса Binding создается таким конструктором:
constructor Create(PropName: String; DataSet: Object; Field: String);
Здесь PropName — имя свойства, в котором будут отображаться данные; DataSet — набор данных; Field — привязываемый элемент данных.
С классом связаны два события: Format и Parse. Первое возникает при передаче данных в элемент отображекия, второе — при обратной передаче. В этих обработчиках можно применять нужные методы форматирования для придания данным желаемого вида.
Использование событий рассмотрим на примере проекта Ch02\FormBindFormat\ FormBindFormat.dpr (рис. 2.30).
BNAMEBNAME'BPRI'BPRI:10 мин” на урок MS Wad 2 28,4410 MMMijr на урок Windows 9 14.1 S3 :10 минут на урок. 0 свой сам 28.44.:1001 с®срет реестра Window 35.011;12 урокое тенниса. Самый до 10П 3 шагов к успеху или практ 4 *j:10 мин” на урок MS Wad 2 28,4410 MMMijr на урок Windows 9 14.1 S3 :10 минут на урок. 0 свой сам 28.44.:1001 с®срет реестра Window 35.011;12 урокое тенниса. Самый до 10П 3 шагов к успеху или практ 4 *j(40.000(40.000ОткатитьОткатить;По!^'П?|Ф^4£:;По!^'П?|Ф^4£:
BNAME
BNAME
'BPRI
'BPRI
:10 мин” на урок MS Wad 2 28,44
10 MMMijr на урок Windows 9 14.1 S3 :10 минут на урок. 0 свой сам 28.44
.:1001 с®срет реестра Window 35.011
;12 урокое тенниса. Самый до 10
П 3 шагов к успеху или практ 4 *j
:10 мин” на урок MS Wad 2 28,44
10 MMMijr на урок Windows 9 14.1 S3 :10 минут на урок. 0 свой сам 28.44
.:1001 с®срет реестра Window 35.011
;12 урокое тенниса. Самый до 10
П 3 шагов к успеху или практ 4 *j
(40.000
(40.000
Откатить
Откатить
;По!^'П?|Ф^4£:
;По!^'П?|Ф^4£:
Рис. 2.30. Демонстрация событий Format и Parse
Рядом с таблицей элемент txbPrice класса TextBox отображает цену покупки книги. В таблице BOOKS поле BPrice имеет тип Double. В обработчике Format этот тип представляется как денежный, а в обработчике Parse происходит обратное преобразование:
implementation
uses Borland.VCL.SysUtils;
constructor TWinFonti. Crea te ; var
bdnPrice: Binding;
begin
ixiherited Create;
InitializeComponent;
// Наполняем НД даннымиz
BdpDataAdapterl.Fill(DataSet1);
// Создаем экземпляр Binding для связи свойства Text с полем BPriceг bdnPrice := Binding.Create('Text'f DataSetl.Tables[0], 'BPrice');
// Присоединяем к нему два обработчика событий г
Include(bdnPrice.Format, DoubleFormat);
include(bdnPrice.Parse, DoubleParse);
// Очищаем свойство D送匕aBindings поля:
TextBoxl.DataBindings.Clear;
// Добавляем созданный объект bdnPrice:
TextBoxl.DataBindings.Add(bdnPrice); end;
procedure TWinForm.Button2_Click(sender: System.Object;
e: System.EventArgs);
// Щелчок на кнопке яОткатить" begin
DataSetl.Rejectchanges end;
procedure TWinForm.Buttonl—Click(sender: System.Object;
e: System.EventArgs);
// Щелчок на кнопке "Подтвердитьм begin
BdpDataAdapterl.Update(DataSetl} end;
procedure TWinForm.DoubleFormat(Sender: TObject; e: ConvertEventArgs);
// Обработчик события Format begin
e.Value := FloatToStrF(Double(e.Value), ffNumber, 10,2) + 'p'; end;
procedure TWinForm.DoubleParse(Sender: TObject;
e: ConvertEventArgs);
// Обработчик события Parse
var
S: String; begin
S := e.Value.ToString;
if pos ('p\ S) <> 0 then
Delete(S # pos('p'r S), 1);
e.Value := StrToFloat(S1; end;
Обратите внимание: аргумент e.Value в обработчиках Format и Parse имеет тип Obj ect и, следовательно, способен принимать любые данные. В обработчике Format он вначале имеет данные типа Double, ио принимает String, в обработчике Parse — наоборот.
Программный доступ к значениям таблиц
Рассмотренные в предыдущих разделах средства визуализации открывают доступ к табличным данным для пользователя, работающего с программой. Однако часто возникает необходимость программного управления данными. Типичным примером является использование транзакций, в рамках которых осуществляется группа действий по изменению состояния БД. Эти действия должны выполняться по принципу «либо все, либо ни одного*. Например, перевод денег с одного счета на другой. Для реализации этой операции сначала нужно изменить данные в одной таблице (уменьшить дебиторский счет на заданную сумму), затем в другой (увеличить кредиторский счет на ту же сумму). Если между этими операциями произойдет случайный сбой, кредиторский счет останется без изменения, а деньги с дебиторского счета бесследно исчезнут. Чтобы исключить подобную ситуацию, оба действия выполняются в рамках одной транзакции. Сетка DataGrid автоматически стартует новую транзакцию при редактировании данных в записи. Но эта транзакция также автоматически заканчивается (подтверждается), когда курсор данных переходит к другой записи или сетка теряет фокус ввода.
Для старта транзакции методом BeginTransaction связного компонента BdpConnecti on создается объект класса BdpTransaction, имеющий методы Commit (подтвердить транзакцию) и Rollback (откатить транзакцию). В промежутке между стартом и завершением транзакции программа (а не пользователь!) должна изменить данные в обеих таблицах.
Общая схема получения данных такова. Объявляется переменная класса BindingManagerBase, и ей присваивается ссылка на объект Bindingcontext таблицы. Класс BindingManagerBase — абстрактный, а класс Bindingcontext — его потомок, перекрывающий абстрактные свойства своего родителя. В классе BindingManagerBase есть два свойства тапа Integer: Count и Position. Первое определяет общее количество записей в НД, второе — положение курсора данных. Свойство Position доступно как для чтения, так и для записи, что по-
зволяет выбирать нужную запись в НД. Затем в массиве Rows таблицы DataTable выбирается запись и поле в Heii:
/ / Связываем переменную Binding класса BindingManagerBase // с контекстом таблицы:
Binding :- BindingContext|DataSet 1.Tables[0]];
// Получаем текущую запись:
CurRow := DataSet 1.Tables[0] .Rows[Binding.Position];
// Получаем значение N-го поля:
Text := CurRowlN, DataRowVersion.Current].ToString;
Значение поля возвращается в объекте класса Objесс. Его явное приведение к нужному типу разрешается компилятором Delphi, но блокируется CLR. При выполнении следующего оператора J IT-компилятор сообщит о недопустимом приведении типов:
■^Count :二 CurRow [ ' MCount' ] as Integer ;
Налицо ошибка разработчиков Delphi, Приходится использовать метод ToString об1>екта данных:
laCount. Parse (CurRow [ ' NCount * j . ToString);
Изменить значение поля можно только с помощью SQL-оператора UPDATE, который формируется пр0rРаммой и передается серверу в объекте класса BdpCommand. Для илпюстрапин вышесказанного рассмогр1ш пример перевода денег с дебиторского счета на кредиторский (рис. 2.31).
Таблице DE0Таблица CRED
[эз^Перевдстм I
Рис. 2.31. Окно демонстрационной программы
В БД IB_BIBL.GDB есть две небольише таблицы: DEE и CRED. Начните новое приложение WinForms и поместите на форму компонент BdpConnection, два компонента BdpDataAdapter и компонент DataSet. Настройте компонент BdpConnection на связь с БД IB_BIBL,GDB. Настройте один компонент BdpDataAdapter на отображение всех полей таблицы DEB, а второй — таблицы
CRED. Введите в их свойства DataSet ссылки на компонент DataSetl и откройте их (задайте True для свойства Active). Поместите на форму две сетки DataGrid и с помощью их свойств DataSet свяжите левую с таблицей DataTablel, а правую — с таблицей DataTable2. Сетки должны наполниться данными.
Поместите на форму поле ввода TextBox и кнопку Button. Напишите следующие обработчики событий: TWinFomuActivated, TextBoxl_TextChanged и TBu11 onl_C 1 i ck:
procedure TWinForm.TWinForm_Activated(sender: System.Object;
e: System.EventArgs);
// Передает фокус ввода полю TextBoxl в момент активизации формы begin
TextBoxl・ Focus; 强d;
var
Txt : String 二 * ';// Глобальная переменная Txt сохраняет
/ / последний правильный ввод в поле TextBoxl procedure TWinForm・TextBoxl_TextChanged(sender: System.Object;
e: System.EventArgs);
// Проверяет ввод в поле TextBoxl и отвергает символы, не // соответствующие правильному текстовому представлению // велгеств енных чисел
var
D: Double;
begin
if TextBoxl.Text <> 1' then try
〃 Нет ошибок?
D := StrToFloat(TextBoxl.Text);
// -Нет. Запоминаем ввод
Txt := TextBoxl.Text;
except
// Ошибка J Восстанавливаем текст
TextBoxl.Text := Txt;
end; end;
procedure TWinForm.Buttonl_Click(sender: System.Object; e: System.EventArgs);
// Переводит деньги с текущего счёта таблицы DEB на текущий
// счет таблицы CRED под защитой транзакции var
Comm: BdpCommand;
Sum, Count: Double;
Binding: BindingManagerBase;
Trans: BdpTransact ion;
CommStr: String;
NCount: Integer;
CurRow: DataRow;
begin
if TextBoxl.Text = '* then
Exit; // Яе введена сумма перевода
// Проверяем соединение и открываем его, если оно еще не открыто :
if BdpConnectionl«State <> ConnectionState.Open then BdpConnectionl.Open;
〃 Получаем сумму перевода :
Зшп := StrToFloat(TextBoxl,Text);
// Связываем переменяю Binding с контекстом таблицы DEB:
Binding :二 Bindingcontext[DataSetl.Tables[* DEB *]1;
// Получаем текущую запись таблицы D£S:
CurRow := DataSetl.Tables('DEB'].Rows[Binding.Position];
// Получаем текущую сумму на счете:
Count := StrToFloat(CurRow[1, DataRowVersion.Current].ToString);
// Получаем номер счета :
NCount := StrToInt(CurRow[0f DataRowVersion.Current].ToString);
// Проверяем затребованную сумму\
if Count < sum then
begin // Сумма превышает остаток на счете
TextBoxl.Text := Count«ToString; // Указываем остаток
TextBoxl.Focus;// Фокусируем поле ввода
Exit;// Завершаем работу
end;
// Определяем новую сумму на счете:
Count := Count - Sum?
〃 Создаем объект для SQL-команда:
Соггап := BdpCommand.Create;
// Указываем ему соединение:
Comm.Connection := BdpCoimectionl;
// Стартуем транзакцию
Trans := BdpCormeccionl.BeginTransaction();
// Указываем объекту СОпт транзакцию г
Comm.Transaction := Trans;
Comm.CommandType := CommandType.Text;
// Формируем текст команды:
ConunStr := * UPDATE DEB SET SUMM= * + Count.ToString +
'WHERE NCOUNT='+ NCount.ToString;
// Помещаем команду 日 свойство CommandText:
Сопоп.CommandText := CommStr;
// Получаем контекст таблицы CRED:
Binding := Bindingcontext[DataSetl.Tables['CRED']];
/ / Текущая запись таблицы:
CurRow := DataSetl.Tables[ТСЕЕП*].Rows[Binding.Pcsition];
// Сумма на стете:
Count := StrToFloat(CurRow[l, DataRowVersion.Current].ToString);
// номер стета:
NCount := StrToInt(CurRow[0, DataRowVersion.Current].ToString);
Count := Count + Sum;
CommStr := 'UPDATE CRED SET SUMM=' + Count.ToString + 'WHERE NC0UNT='+ NCount.ToString;
tryComm.ExecuteNonQuery;//Comm.ConnnandText := CommStr? //Comm.ExecuteNonQuery;//Trans.Commit;//except//Trans.Rollback;//end;tryComm.ExecuteNonQuery;//Comm.ConnnandText := CommStr? //Comm.ExecuteNonQuery;//Trans.Commit;//except//Trans.Rollback;//end;// BdpDataAdapterl.Active := False; BdpDataAdapterl.Active := True; BdpDataAdapter2.Active := False; BdpDataAdapter2-Active := True;//TextBoxl.Text := * *;TextBoxl.Focus;//end;// BdpDataAdapterl.Active := False; BdpDataAdapterl.Active := True; BdpDataAdapter2.Active := False; BdpDataAdapter2-Active := True;//TextBoxl.Text := * *;TextBoxl.Focus;//end;Снимаем с дебиторского счета Новая командаНачисляем на кредиторский счетПодтверждаем транзакцию Ошибка!Откатываем транзакциюОбновляем данные в сетках :Снимаем с дебиторского счета Новая командаНачисляем на кредиторский счетПодтверждаем транзакцию Ошибка!Откатываем транзакциюОбновляем данные в сетках :Очищаем поле ввода :Передаем ему фокус вводаОчищаем поле ввода :Передаем ему фокус ввода
try
Comm.ExecuteNonQuery;//
Comm.ConnnandText := CommStr? //
Comm.ExecuteNonQuery;//
Trans.Commit;//
except//
Trans.Rollback;//
end;
try
Comm.ExecuteNonQuery;//
Comm.ConnnandText := CommStr? //
Comm.ExecuteNonQuery;//
Trans.Commit;//
except//
Trans.Rollback;//
end;
// BdpDataAdapterl.Active := False; BdpDataAdapterl.Active := True; BdpDataAdapter2.Active := False; BdpDataAdapter2-Active := True;
//
TextBoxl.Text := * *;
TextBoxl.Focus;//
end;
// BdpDataAdapterl.Active := False; BdpDataAdapterl.Active := True; BdpDataAdapter2.Active := False; BdpDataAdapter2-Active := True;
//
TextBoxl.Text := * *;
TextBoxl.Focus;//
end;
Снимаем с дебиторского счета Новая команда
Начисляем на кредиторский счет
Подтверждаем транзакцию Ошибка!
Откатываем транзакцию
Обновляем данные в сетках :
Снимаем с дебиторского счета Новая команда
Начисляем на кредиторский счет
Подтверждаем транзакцию Ошибка!
Откатываем транзакцию
Обновляем данные в сетках :
Очищаем поле ввода :
Передаем ему фокус ввода
Очищаем поле ввода :
Передаем ему фокус ввода
При подготовке примера я не смог получить нужный результат с помощью такого преобразования:
Count.Parse(CurRow[1> DataRowVersion.Current].ToString);
В моем случае переменная Count всегда получала нулевое значение, хотя строковое представление суммы было правильным. Пришлось воспользоваться функциями StrToFloat и StrToInt, которые определены в модуле Borland. VCL. SysUtils. Не забудьте вставить ссылку на этот модуль в начале исполняемой части: inqplementation
uses Bor1and.VCL.SysUt ils;
Технология BDE.NET
В этой и последующих главах описываются технологии работы с БД, которые поддерживались в предыдущих версиях Delphi и перенесены в версию 2005. Все они называются XXX.NET, что говорит об их способности работать на платформе .NET. Доступ к технологиям возможен только в режиме создания VCL-приложенкй.
Суть технологии
Технология получила свое название по первым буквам словосочетания Borland Database Engine — машина баз данных корпорации Borland. BDE представляет собой набор библиотек DLL, реализующих различные службы, связанные с обслуживанием БД.
Рисунок 3.1 иллюстрирует связь составных частей технологии BDE.NET.
К компонентам связи относятся компоненты TSession и TDatabase, Первый создает канал связи, второй передает серверу дополнительные параметры (имя пользователя и пароль), а также обеспечивает функционирование механизма транзакций. Любая программа, использующая технологию BDE.NET, автоматически (по умолчанию) получает один канал связи TSession, что вполне достаточно для большинства типичных приложений.
К наборам данных относятся компоненты TTable, TQuery и TStoredProc. Первый открывает доступ к одной из таблиц БД или к виртуальной таблице — представлению (view). Второй создает набор данных за счет SQL-занроса, а третий — за счет обращения к хранимой процедуре. Замечу, что BDE имеет собственный интерпретатор SQL, что позволяет использовать TQuery не только для обращения к серверным БД, но и для работы с таблицами файл-серверных баз данных. Источником данных является компонент TDataSourse. Он необходим только для связи НД с компонентами визуализации. Фактически он является
TSesslon TDatabase
Компоненты связи
八
V
ТТаЫе
Наборы данных
八
v
TDataSource
Источники данных
八
v
TDBGrid
Компоненты визуализации
Рис. 3.1. Иллюстрация технологии BDE.NET
управляемым переключателем, подключающим визуальные компоненты к НД или отключающим их от него.
В технологии BDE.NET используется множество специальных компонентов для визуализации данных^ в том числе сетка TDBGrid.
Поля
Каждый набор данных в таблице базы данных (ТБД) состоит из записей, а те, в свою очередь, состоят из полей. Таким образом, в структуре таблицы имеется минимум одно поле. Обращаться к полям таблиц баз данных позволяет класс TField» работа с которым и является темой этого раздела.
Обзор свойств, методов и событий
В этом разделе рассматриваются некоторые наиболее важные свойства, методы и события класса TField.
Свойства
Важнейшие свойства класса TField представлены в табл. 3.1.
Таблица 3.1. Некоторые свойства класса TReld
Свойство
Описание
property Alignment: TAlignment;
Определяет выравнивание значения поля при его отображении: taLeftJustify — выровнять влево; taRightJustify — выровнять вправо; taCenter — выровнять по центру
property AsXXXX: HXXXX;
Группа свойств этого вида приводит значение поля к нужному типу. Вместо символов ХХХХ в названии свойства и типа могут использоваться: BCD — приведение к типу двоично-десятичных данных; Boolean — к логическому типу; Currency — к денежному типу; DataTime — к типу дата-время; Float — к типу Double; Ineteger — к типу Integer; String — к типу String; Variant — к типу Variant
Поля 119
Свойство
Описание
property AttributSet: String;
Содержит имя набора атрибутов поля в словаре данных (см. далее примечание)
property Calculated: Boolean;
Содержит True, если значение пол兄 вычисляется в обработчике события OnCalcFields
property CanModify: Boolean;
Содержит True» если значение ноля можно изменять
property CurValue: Variant ;
Содержит текущее значение с учетом возможных изменений, внесенных другими пользователями
property DataSet: TDataSet;
Связанный с полем набор данных (]|аследлик класса TDataSet типа TDBDataSet)
property DataSize: Word;
Содержит размер данных
property DataType: TFieldType;
Тип TFi&ldType представляет собой неречме- ление, определяющее тип данных (см. далее)
property Default Express ion: String;
Содержит SQL-выраяссние, определяющее значение по умолчанию (то есть значение, которое оказывается в поле, если пользователь не вводит никакого значения)
property DisplayLcibel: String;
Содержит заголовок поля в сетке TDBGrid
property DisplayText: String;
Содержит строковое представление значения поля. Это свойство только для чтения. В обработчике события OnGetText программист может изменить его
property Displaywidth: Integer;
Определяет ширину поля в символах
property EditMask: String;
Определяет маску, которая будет использоваться для фильтрации и форматирования вводимого значения (см. далее)
type TFieldKind = (fkData, fkCalculated, fkLookup, fklntemalCalc, fkAggregate);
property FieldKind: TFieldKind;
Определяет тип поля: fkData — обычное поле; fkCalculated — вычисляемое поле; fkLookup — подстановочное (lookup) поле; fklnternalCalc — внешнее вычисляемое поле (см. далее); fkAggregate — агрегатное поле
property FieldName: String;
Имя поля в соответствующем НД
property FieldNo: Integer;
Номер поля в соответствующем НД. Нумерация полей начинается с 1 (только для чтения)
property HasConstraints: Boolean;
Содержит True, если на значение поля наложены офаничения. Не учитывает ограничения, вводимые маской Edit-Mask
property Index : integer;
Индекс поля. Изменение индекса приводит к изменению порядка отображешш ноля в сетке, но не в НД
продолжение 少
Таблица 3.1 (продолжение)
Свойство
Охшсание
property TslndexField: Boolean;
Содержит True, если поле — индексное
property isNull : Boolean;
Возвращает True, если значение поля есть
Null
property KeyFielde: String;
Список индексных полей текущего НД для связи с подстановочным НД
property Lookup: Boolean;
Содержит True, если тип поля — ft Lookup
property LookupCashe: Boolean;
Разрешает/за11решает кэширование значений подстановочных полей
property LookupDataSet: TDataSet;
Определяет НД, в котором ищутся значения полей LookupKeyFields
property LookupKeyFields :
String;
Список полей в подстановочном НД, которые должны соответствовать полям KeyFields
property LookupList :
TLookupList;
Список всех допустимых значений подстановочного поля
property LookupResultFild: String;
Текущее значение подстановочного поля
property NewValue: Variant ;
Новое значение поля (до завершения трак- закции)
property OldValue: Variant;
Старое значение поля
property Origin: String;
Содержит имя поля в физической ТБД
property ParentField: TObjectField;
Указывает родительское поле во вложенном поле. Содержит NIL, если текущее поле не является частью сложного поля
type TProviderF1 ag = (pflnUpdate, pfInWhere, pfInKey, pfHidden);
TProviderFlags = set
of TProviderFlag;
property ProviderFlags:
TProviderFlags;
Указывает, как использовать это поле при пересылке серверу пакета записей для обновления: pf InUpdate — поле появляется в предложении UPDATE и, следовательно, может обновляться; pflnWhere — поле появляется в предложении WHERE и, следовательно, используется для поиска обновленных записей; pf InKey — поле используется для поиска записей в случае возникновения ошибки обновления; pfHidden — поле включено в пакет для обеспечения уникальности записей и не показывается пользователю
property Readonly: Boolean;
Содержит True, если поле нрепназнанено только для чтения
property Required: Boolean;
Еслн содержит True, значение каждой записи поля не может быть пустым
property Size: Word;
Текущая длина записи в полях с переменной длиной записи
Поля 121
Свойство
Описание
property Text: String;
Текст, которым отображается значение записи в режиме редактирования. В остальных режимах запись отображается содержимым DisplayText
property Value: Variant;
Содержит текущее значение поля
property Visible: Boolean;
Разрешает/запрешает показ поля в визуаль- ных компонентах
ПРИМЕЧАНИЕ
Набор атрибутов поля в словаре данных определяет вид, в котором данные отображаются в визуальных компонентах на этапе разработки программы, а также ограничения и значения по умолчанию. Каждый набор имеет имя, определяемое свойством AttributeSet, что позволяет использовать его в других полях.
ПРИМЕЧАНИЕ
Ограничения, определяемые свойством CustomConstraint, записываются строками вида HX>0 and Х<100\
Параметром свойства DataType является следующее перечисление:
type TFieldType = (ftUnknown, ftString, ftSmallint, ftlnteger, ftWord, ftBoolean, ftFloatf ftCurrency, ftBCD, ftDate, ftTime, ftDateTime, ftBytes, ftVarBytes, ftAvtolnc, ftBlob, ftMemo, ftGraphic, ftFmtMemo, ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftFixedChar, ftWideString, ftLargeint, ftADT, ftArray t ftReference» ftDataSet t ftOraBlob» ftOraClob, ftVariant, ftlnterface, ftIDispatch, ftGuid, ftTimeStamp, ftFMTBcd);
Значения перечисления TFieldType описаны ниже:
ft Unknown — неизвестный тип;
ftstring — строковый тип;
ftSmallint — тип Smalllnt;
ftlnteger — тип Integer;
ftWord — тип Word;
f tBoolean — логический тип;
ftFloat — вещественный тип;
ftCurrency — денежный тип;
ft BCD — двоично-десятичные данные;
ftDate — дата;
ft Time — время;
ft Dat eTime — дата-время;
ftBytes — строка байтов фиксированной длины;
ftVarBytes — строка байтов переменной длины;
ftAutolnc — автоинкрементное поле;
f tBlob — двоичное поле переменной длины;
ftMemo — многострочный текст;
ftGraphic — графическое изображение;
ftFmtMemo — форматированный текст;
ftParadoxOle — поле ParadoxOie;
f tDBaseOle — поле DBaseOle;
f tTypedBinary — типизированное двоичное поле;
f tCursor — состояние курсора НД для сохраняемой процедуры Oracle;
f tFixedChar — строка символов фиксированной длины;
f tWideString — строка двухбайтных символов;
ftLargelnt — длинное целое значение;
f tADT — данные абстрактного типа;
ft Array — массив;
f tReference — ссылочный тип;
f tDataSet — набор данных;
f tOraBlob — поле BLOB в таблице Oracle 8;
f tOraClob — поле CLOB в таблице Oracle 8;
ftVariant — поле содержит значение типа вариант;
ftlnterf асе — ссылка на интерфейс IUnknown;
f tIDispatch — ссылка на интерфейс IDispatch;
f tGuid — глобально-уникальный идентификатор;
ftTimeStamp — дата и время, достухшые в технологии dbExpess;
ftFMiTBcd — двоично-десятичные данные, которые слишком велики для 11BCD.
ПРИМЕЧАНИЕ
Тины полей ftCursor, ftFixedChar, ftWideChar, ftLargelnt, ftADT, ftArray, ftReEerence, EtOraBlob и ftOraClob введены для поддержки промышленного сервера 5Д Oracle версии 8 н выше.
Маски, юиорую определяет свойство EditMask, состоит из трех частей, отделенных друг (и- друга символом точки с запятой (;). Первая часть задает собственно маску ввода, вторая — это символ 0 или 1, определяющий, включается ли в форматируемое значение результа г наложения маски на исходный текст или только исходный текст (0 — исходный текст). В третьей части указывается символ, который должен присутствовать в местах ввода символов в поле.
Таким образом, текст в поле может содержать символы маски; например, для ввода семизначного номера телефона текст перед началом ввода может выглядеть
так (доступные для ввода пользователя места обозначены символом X — последним символом в шаблоне):
(095IXXX-XX-XX
Маска состоит из описателей мест ввода, специальных символов и литералов. Описатель указывает, какой именно символ может ввести пользователь в данном месте (табл. 3.2). Литерал вставляется в текст, отображаемый в поле ввода, ио при вводе курсор «перескакивает» через литерал и не дает пользователю возможности изменить его. Литералом считается любой символ, если ему не предшествует символ обратной косой черты (\), если он не является описателем места ввода или специальным символом. С помощью специальных символов формируются дополнительные указания по обработке вводимых данных (табл. 3.3).
Таблица 3.2. Описатели мест ввода
Символ Описание места ввода
LДолжно содержать букву
IМожет содержать букву
АДолжно содержать букву или цифру
аМожет содержать букву илицифру
СДолжно содержать любой символ
сМожет содержать любой символ
ОДолжно содержать цифру
9Может содержать цифру
Может содержать цифру, а также знаки плюс (+) и минус (-)
Таблица 3.3. Специальные символы
Символ Описание
\Следующий символ — литерал. Позволяет вставлять в маску лтералы из чис
ла символов, относящихся к описателям мест ввода и специальным символам
:На это место вставляется символ -разделитель Windows для часов, минут, се
кунд
/На это место вставляется символ-разделитель Windows для полей даты
;Разделитель частей шаблона
【Подавляет вывод всех начальных пробелов
Во всех следующих за этим символом местах ввода буквы преобразуются в прописные
Во всех следующих за этим символом местах ввода буквы преобразуются в строчные
о Отменяет преобразование регистра букв
Примеры использования маски ввода представлены в табл. 3.4.
Таблица 3.4. Использование маски ввода
Маска
Вид в поле ввода
Ввод пользователя
Результат
(095)000-0000;0;х
(095)ххх-хххх
1234567
1234567
(095)000-0000;1;х
(095)ххх-хххх
1234567
(095)123-4567
(095)\0\00-0000?1;
(095)00,-
12345
(095)001-2345
Методы
Наиболее важные методы класса TField перечислены в табл. 3.5.
Таблица 3.5. Некоторые методы класса TReld
Метод
Описание
procedure Assign (Source:
Копирует значение поля из параметра Source
MarshalByRefObject);
в собственное свойство Value. Типы полей должны быть совместимы
procedure Assignvalue (const
Преобразует вариант Value с помощью ме-
Value: TVarRec);
тода АзЛХХХ и помещает результат в собственное свойство value
procedure Clear;
Очищает значение поля и помещает в него Null (в терминологии SQL)
constructor Create (AOwner:
Component);
Создает н инициализирует объект-поле
destructor Destroy;
Удаляет объект-поле
function HasParent ;
Возвращает True, если поле — вложенное
function IsValidChar (InputChar:
Возвращает True, если символ InputChar
Char): Boolean; virtual;
может присутствовать в текстовом представлении значения поля
proxedure RefreshLookupList ;
Заново создает список значений подстановочного поля
События
События класса TField представлены в табл. 3.6.
Таблицы 3.6. События класса TField
Событие
Описание
property OnChange:
Возникает после изменения данных л успешной
TFieldNotifyEvent;
записи их в буфер
Событие
Описание
type TFieldGetTextEvent 二 procedure(Sender: TField; var Text: String; DisplayText: Boolean) of object;
property OnGetText: TFieldGetTextEvent;
property OnSetText:
TFieldSetTextEvent;
property OnValidate: TFieldNotifyEvent;
Обработчик этого события готовит текст для свойств DisplayText и Text. Обработчик по умолчанию помещает в переменную Text значение Value. AsString. Параметр DisplayText имеет значение True, если текст предназначен для свойства DisplayText
Возникает при записи данных из параметра Text в свойство Text
Возникает после изменения значения до записи в буфер. Обработчик этого события должен про* верить правильность введенных данных
Использование объектов-полей
Объекты для реальных полей
Для удобства работы с конкретным полем можно создать объект-поле класса TField или одного из его специализированных потомков — TStringField, TIntegerField, TBlobField и т. д. Объект-поле создается ыа этапе разработки программы с помощью редактора полей. Если определен объект-поле, получить доступ к полю можно по имени этого объекта. Редактор полей присваивает объектам-полям имена путем сцепления имени источника данных и имени поля. Если, например, источник Firms связан с НД, у которого определен объект для поля City, объекту будет присвоено имя FirmsCity, после чего к нему можно обращаться напрямую. Например:
FirmsCity.AsString := * Москва *;
СОВЕТ
Поскольку на практике создавать объекты-поля приходится довольно часто, имеет смысл называть компоненты-наборы именами связанных с ними таблиц. Например, назвав объект TTable именем связанной с ним таблицы Books, автоматически получим имена типа BooksAuthor, BooksYear, BooksPages и т. п. Если к одной физической таблице обращаются разные компоненты-наборы, их имена можно дополнять префиксами; tbBooks, quBooks, spBooks — для таблицы, запроса и хранимой процедуры соответственно.
Определить во время выполнения приложения, используются ли для набора данных все умалчиваемые поля или только их часть, можно при помощи следующего свойства НД:
property DefaultFields: Boolean;
Значение True указывает, что используются поля, заданные по умолчанию;
False — поля, определенные при помощи редактора полей.
Если хотя бы для одного поля НД создан объект-поле, все поля НД, для которых такие объекты не определены, становятся недоступными. К «несуществующим» полям обратиться из данного НД нельзя. Вновь вернуться к использованию всех полс11 НД можно только на этапе разработки программы, удалив в редакторе полей все определенные ранее объекты или добавив с его помощью объекты для недостающих полей.
ПРИМЕЧАНИЕ
Если нужно иметь доступ к полю, но не показывать его значений в компонентах, визуа- лизир57к)!1шх данные (например, в компоненте TDBGrid), н свойство visible этого объекта-ilоля следует поместить значение False.
Для вызова редактора полей нужно дважды щелкнуть на компоненте-наборе или щелкнуть на нем пралой кнопкой мыши и выбрать в контекстном меню команду Fields Editor. Предварительно НД должен быть связан с нужной таблицей БД: в ТТаЫе должны быть определены свойства DatabaseName и TableName, в TQuery — DatabaseName и SQL (то есть это свойство должно содержать текст SQL-запроса, который создаст НД), в TStoredProc — DatadaseName и StoredProcName. Чтобы добавить объекты-поля, щелкните в окне редактора правой кнопкой мыши и выберите в контекстном меню команду Add Fields. В списке открышиегося окна Add Fields будут указаны поля, для которых еще не созданы объекты (рис. 3.2, слева). Вы можете выбрать любую комбинацию полей в списке и щелкнуть па кнопке ОК — для выделенных полей будут созданы объекты, а окно редактора будет содержать список этих полей. Если нужно создать объекты-поля для всех полей НД, выберите команду Add All Fields в контекстном меню редактора. Чтобы удалить определение какого-либо объекта, нужно выделить соответствующее поле в окне редактора и нажать клавишу Delete. Если нужно удалить объявления всех объектов-полей, выберите команду Select АН в контекстном меню и после этого нажмите клавишу Delete*
Рис. 3.2. Работа с редактором полей: слева — добавление полей; справа ——список полей, для которых созданы объекты
Поля 127
Чтобы изменить свойства конкретного объекта-поля или напнсать обработчик для какого-либо связанного с ним события, необходимо в редакторе полей выделить нужное поле и, используя инспектор объектов, установить значение в свойство или определить обработчик события.
Объекты для подстановочных полей
Подстановочное (lookup) поле отличается от обычного объекта-поля тем, что содержит данные из другого НД. Непременным условием создания подстановочного поля является выполнение требования реляционной связи главного НД с таблицей подстановки: в главном НД каждое значение какого-либо поля должно ссылаться на одну из записей в таблице подстановки, причем по полю связи в этой таблице должен быть создан уннкальны" индекс или первичный ключ.
Для создания подстановочного поля нужно вызвать контекстное меню редактора полей (щелкнув в его окне правой кнопкой мыши) и выбрать в нем команду New Field. В появляющемся после этого окне добавления нового поля (рис. 3.3) нужно ввести имя поля в строке Name и выбрать в списке Туре его тип. Строка Size заполняется только для текстовых полей и полей типа набора байтов. В первом случае оно показывает максимальную длину в символах строки, которую будет содержать поле (по умолчанию этот размер равен 20 символам» что может быть недостаточным во многих практических случаях, поэтому следует проанализировать структуру таблицы подстановки и уточнить размер того поля, которое и будет содержать информацию для создаваемого объекта), во втором —длину поля в байтах. Для всех других типов значение в строке Size игнорируется. Строка Component в момент ввода имени заполняется автоматически (она содержит имя объекта-поля). Delphi игнорирует «чужой?* ввод в строку Component.
IVPCJ
L lookup de^ntor— з2I-
Cg^onent: j
m эхе:
ffiekl рто^Й坦^ i уапю: J
Рис. 3.3. Окно создания нового поля
▼1 Di^aset;
В группе Field type следует установить переключатель Lookup, затем раскрыть список нолей главной таблицы Key Fields и выбрать в нем ссылочное поле. В списке Dataset выбирается подстановочный НД, в списке Lookup Keys — индексное поле подстановочного НД, а в списке Result Field — результирующее поле (именно его значения присоединятся к полям главно!! таблицы).
Достаточно подробный пример создания подстановочных полей вы найдеге в главе 1.
Объекты для вычисляемых полей
Вычисляемые поля не входят в состав конкретной таблицы БД, ио могут быть нрисоед1П1ены к НД( связанному с этой таблице!!. Они предназначены для отображения данных, которые вычисляются в ходе выполнения программы обычно с помощью значений из друптх полей той же записи. После присоединения вычисляемого поля к НД оно становится во всем подобно обычным объектам-полям, связанным с реальными полями таблицы БД, за одним исключением: такие поля нельзя редактировать, а при вводе новой записи — помещать в них какое-либо значение.
Для создания вычисляемого поля нужно открыть окно New Field (см. рис. 3.3) редактора полей и, заполнив строки Name, Type и Size, установить переключатель Calculated и закрыть окно щелчком на кнопке ОК. Заполнение вычисляемых полей осуществляется в обработчике события OnCalcFields набора данных.
Проиллюстрируем создание вычисляемого поля на примере программы, описанной в главе 1. В ней используется таблица MOVES (НД Move) для отображения списка книг, связанных с накладной. В этой таблице есть поля, в которых указываются количество экземпляров книги (объект MoveMQuan) и ее цена (MoveMPrice). Создадим для НД Move вычисляемое поле Summa, в котором укажем сумму покупки (продажи) каждой книги (рис 3.4).
編
гк
ом
г
1Дйт«
InepTW":
• 1 Тип накладнойкужв
Опле«та |Вомр*т |крэф-犬麻У 丛 i
1
1 01,03.2000
2 01,03.2000
3 01.03.2000 ^01,03,2000
5 01,03.2000 $ 01.03.2000 7 01,03.2000 В 01,03.2000
9 01.03.2000
10 01.03,2000
:Точка. Социальный ужверснПродажа на реалихиию 550,00р, Яновер Продажа с предоллвтои 335,92р. ЖС ООО Продажа на реализаф«о 45 ЗЭ7,50р, :ДЕСС-Пабгииерэ Приход по обмену б 7睨 ООр. Роз>«чная продажа Продажа с предопмтон 234,ООр, Точка. МГИЭМ Продажа на реатзацмю 2 328"0р, ООО Издательство "Нопидж1 Поставка на рваг»ваш«о55 610,00р. ПродалитЪ Продажа на реагмицмю 2 767,50р. Илита Продажа на реалюацию 655,00р. ООО Издательство "Нолид*’ Поставка на реалиэвцню55 610,00р.
0,00р.550,00р..13Q.04.20M‘…“
335,92р.0,00р.;1,0431,03.2000
o.oop.q,oop.07si0.D4.2000
0t00p.0,00р.:1O1.03.20D0
234,00p.0,00р.L(H.02,03.2000
0,00р.2 328,欣.1Д30,04.2000
зО2О1.в5р. Й4 08л35р. 13 0,04,2000
0,00р.0,00р.:0<75:Э1.03.2000
0,00р,0»00р.:0,75 .31.03.2000
0,00р.0,00р,1.30,04,2000
Название кий»/Автср./Ихд-ел :.
.|Кал-во|Цема Цма |%
►
Новейший едмоучитет работы на компьютера/ Оюномч/Десс Програиж^юванме на языке QBastc для школь никое и студентов/ Боброве км/Десс
Ехсв1;праттическое руководство/ Попов/Десс
30 更-ООр: 1 950,00р.
;56 40,00р. 2 240,00р.;":;;
48 久 00р. 2 592,00р.
_獨
jh.g«H「
Рис. 3.4. Столбец «Сумма» в нижней сетке отображает вычисляемое поле
Вызовите редактор полей двойным щелчком на НД Move и затем в контекстном меню редактора выберите команду New Field. Введите в строку Name окна New Held название поля Summa, в списке Туре выберите денежный тип (Currency), установите переключатель Calculated и закройте окно щелчком на кнопке ОК. Если сейчас вызвать инспектор объектов, он будет отображать свойства и события вновь созданного объекта-поля MoveSumma, поэтому щелкните один раз на НД Move, чтобы инспектор объектов показал свойства этого НД. Напишите такой обработчик события OnCalcFields (проект ChO3\CalcHeld\CalcFieId.dpr):
procedure TDM.MoveCalcFields(DataSet: TDataSet);
begin
Move Summa.Value := MoveMQuan.Value * MoveMPrice.Value end;
Напомню, что для сетки DBGrid2 были созданы объекты -столбцы. Чтобы увидеть в сетке столбец со значениями нового поля, создайте для него новый объект-столбец.
Объекты для пустых полей
Если в окне New Held (см. рис. 3.3) установить переключатель Data, будет создан объект-поле, не содержащий никаких данных (пустое поле). Как правило, такое поле создается для того, чтобы в сетке DBGrid появился дополнительный пустой столбец, в котором программа сможет отображать произвольные значения (для этого обычно используется обработчик события OnGetText объекта-поля или события OnDrawColurnnCell сетки). Замечу, что на практике удобнее вместо пустых полей использовать пустые объекты-столбцы, создаваемые непосредственно в сетке DBGrid.
Обращение к значению поля
К значению поля можно обратиться при помощи свойств Value и AsXXXXкласса TField или его потомков. В табл. 3.7 перечислены типы значений, возвращаемых следующим свойством:
property Value: Variant
Таблица 3.7. Типы значений, возвращаемых компонентами в свойстве Value
Тип
Компонент
Variant
Все компоненты
String
TStringField, TBlobField
Longlnt
TAutoIncField, TIntegerField, TSmallintField, TWardField
Double
TBCDField, TCurrencyField, TFloatField
Boolean
TBooleanField
TDateTime
TDateField, TDateTimeField, TTimeField
5 Зах. 449
В классе TField (и во всех специализированных классах TXXXXField) для приведения типов полей определены следующие свойства AsXXXX:
property AsBCD: TBcd;
property AsBoolean: Boolean;
property AsCurrency: Currency;
property AsDateTime: TDateTime;
property AsFloat: Double;
property Aslnteger: Integer;
property AsString: String;
property AsVariant: Variant;
property AsSQLTimeStamp: TSQLTimeStamp;
Каждое из этих свойств приводит значение поля к соответствующему типу данных, указанному в названии свойства. Например, если BooksBookID — поле TAutolncField, для приведения его к типу string нужно воспользоваться свойством AsString:
EdiC.Text := BooksBookID,AsString;
Разумеется, тип поля должен быть совместимым с типом данных, к которому ггриво- дится значение поля. Например, если MoveSumma — поле типа TCurrencyField, попытка привести его к несовместимому типу Boolean ггриведет к ошибке.
Таблица 3.8 иллюстрирует совместимость значений полей разных типов, при этом используются следующие обозначения:
= — типы равнозначны;
+ — преобразование возможно;
+ RI — преобразование возможно, при этом выполняется округление до ближайшего целого;
? — преобразование происходит, если оно возможно, и часто зависит от формата отображения (свойство DisplayFormat);
х — преобразование не разрешено;
memo — имеет значение для мемо-поля;
п. 1 — преобразование даты к числу дней, прошедших с 01.01,0001;
п. 2 — преобразование времени делением на 24 часа;
п. 3 — преобразование в строку True или False.
Таблица 3.8. Совместимость значений полей разных типов
Тип поля
AsString
Aslnteger
AsFloat
AaDateTime
AsBoolean
TStringField
=
?
?
?
?
TintegerField
+
H
+
X
X
TSmallinTField
+
-
+
X
X
TWordField
+
-
+
X
X
TFloatField
+
+ RI
-
X
X
TCurrencyField
+
+ RI
-
X
X
Поля 131
Тип поля
AsString Aslnteger AsFloat AsDateTine AsBoolean
TBGDField
TDateTimeField
十+ RI-xx
+XП. 1*X
TDateField TTimeField TBooleemField TBytesField TVarBytesField TBlobField TMemoField TGraphicField
? X П. 1 X ? x n. 2 * x n. 3 x x x * + X XX X + X X X X memo x x x x memo x x x x memo x x x x
Если для НД не создано ни одного объекта-поля, получить доступ к значению поля этого НД можно с помощью его метода FieldByName:
function FieldByNeune(const FieldName: String): TField
Кроме того, получить доступ к значению поля НД можно через его свойства Fields и Fieldvalues:
property Fields(Index]: TField property Fieldvalues[1Имя_поля1]: Variant
Обратите внимание: нумерация полей в свойстве Fields начинается с 0, а свойство Fieldvalues является умалчиваемым свойством для НД, поэтому следующие обращения идентичны (предполагается, что поле 1 Year * является 5-м по счету в НД Books):
Books.FieldByName(*Year').Aslnteger := 2000;
Books['Year*] := 2000;
Books.Fieldvalues[1 Year1] := 2000; Books.Fields[4].Aslnteger := 2000;
Свойство Fieldvalues НД обладает двумя особенностями: во-первых, оно имеет значение вариантного типа, во-вторых, допускает обращение со списком полей. Это позволяет единственным оператором обращения к этому свойству прочитать или записать сразу несколько полей текущей записи. Такую возможность иллюстрирует листинг 3.1.
Листинг 3.1. Чтение и запись сразу нескольких полей procedure TForml.ButtonlClick(Sender: TObject); var N: Integer; Price: Currency; V: Variant; begin // Читаем попя 1-й записи НД Books: V := VarArrayCreate([0, 2】,varVariant);*
Листинг 3.1 (продолжение)
V := Books['EQu&n;BN&me;BOpt'];
N := V[0];
Price := V[2];
ShowMessage(Format(
'В продаже имеется %d экз. книги ***s" по цене %fp. * , [N, V[l]# Price]));
// Изменяем поля:
V[0] := 5;
V[1] := * Моя книга';
V[2] := 40.0;
Books.Edit;
Books['BQuan;BName;BOpt'] := V;
Books.Post end;
Проверка правильности введенного в поле значения
Для контроля правильности вводимых в поле значений можно использовать событие OnValidate или OnSetText объекта-поля. Оба события наступают после изменения значения поля, но до его запоминания в таблице.
В обработчике OnValidate в случае обнаружения неверного значения программа должна предотвратить его запоминание, создав исключительную ситуацию или обратившись к глобальной процедуре Abort. Например, поле NaklsNPayedSum в учебной БД содержит данные по оплате накладной и, естественно, не может иметь отрицательных значений. Для контроля над этим можно написать такой обработчик:
procedure TDM.NaklsNPayedSumValidate(Sender: TField); begin
if NaklsNPayedSum.Value<0 then
begin
ShowMessage(1 Сумма не может быть отрицательной!*);
Abort
end end;
Однако следует учесть, что, отказавшись от запоминания неверного значения в таблице, программа тем не менее оставляет НД в ссктоянии редактирования. Это означает, что пользователь не сможет убрать курсор из этого поля до тех пор, пока не введет в него правильное значение. Если бы мы решили защитить поле от любого изменения с помощью показанного ниже обработчика, то обнаружили бы, что при попытке изменить значение поля программа попросту «зацикливается> t не давая пользователю убрать курсор из редактируемого поля:
procedure TDM.NaklsNPayedSuiriValidatе(Sender: TField); begin
ShowMessage('Сумма не должна изменяться!1);
Abort
end;
В данном случае использовать событие OnSetText значительно разумнее, так как в нем можно просто игнорировать неверные значения и не создавать исключительную ситуацию. Дело в том, что в этом обработчике программа должна присвоить полю новое значение или оставить поле без изменения:
procedure TDM.NaklsNPayedSumSetText(Sender: TField;
const Text: String);
begin
if StrToFloat(Text)<0 then
Shov^4essage(* Сумма не может быть отрицательной!') else
NaklsNPayedSum.Value := StrToFloat(Text) end;
Обратите внимание: можно не бояться того, что при преобразовании текста в значение с плавающей запятой может возникнуть исключение. При вводе значения в поле какого-то типа, кроме символьного, программа автоматически отвергает любые символы, не соответствующие символьному представлению этого типа.
Формирование текстового представления поля
Часто требуется некоторое дополнительное преобразование для более точного или более правильного представления хранящегося в поле значения. Для этих целей служит обработчик события OnGetText объекта-поля.
Например, пусть все денежные данные в БД хранятся в «старом» масштабе цен (с тремя лишними нулями). После деноминации нужно либо пересчитать все денежные поля во всех таблицах (это не всегда возможно, так как на практике при создании СУБД в 90-х годах таким полям часто присваивался целочисленный тип), либо — что значительно проще — изменить представление значения в обработчике события OnGetText. В следующем обработчике не только устраняются лшпние нули, но и вставляются разделители тысяч для удобства чтения длинных сумм:
procedure TForml.BooksPriceGetText(Sender: TField;
var Text: String;
DisplayText: Boolean);
begin
Text := FloatToStrF(tbBooksPrice.AsFloat/1000, ffNumber, 10, 2) end;
Другой пример. Поле Sex в таблице Cl ient s имеет логический тип. Обработчик выводит текст Муж или Жен в зависимости от значения поля:
procedure TForml.tbClientsSexGetText(Sender: TField;
var Text: String;
DisplayText: Boolean);
begin
if tbClientsSex.Value then
Text := 'Муж' else
Text := * Жен*
end;
Замечу, что обработчики выполняются только в работающей программе, поэтому на этапе разработки вы не сможете увидеть результат их работы.
Обзор полей TxxxField
Строковые поля
Поле TStringField предназначено для хранения строк длиной до 255 символов. Следующее его свойство указывает, следует ли производить преобразование символов в кодировку ANSI при чтении строк из таблицы и записи их в нее в том случае, когда кодировка строк в таблице отличается от кодировки ANSI:
property Transliterate: Boolean
Когда в свойство установлено значение True, для преобразования автоматически используются функщ-ш AnsiToNative при записи строк в таблицу и NativeToAnsi при чтении из нее. Для русифицированной версии Windows эти функции позволяют работать с таблицей, в строковых полях которой применяется так называемая альтернативная кодировка символов (кодовая страница 866).
Для работы с полем TStringField предназначены компоненты TDBLabel и TDBEdit.
Поле TMemoField позволяет хранить множество строк неопределенной длины. Оно имеет следующее свойство, которое содержит размер поля в байтах:
property BlobSize: Integer;
Специфические методы поля TMemoField перечислены в табл. 3.9.
Таблица 3.9. Методы поля TMemoField
МетодОписание
procedure Clear;Очищает поле
procedure LoadFromFile (constЗагружает содержимое поляиз файла
FileName: String);
procedure LoadFromStream(Stream:Загружает содержимое поляиз потока
TStream);
procedure SaveToFile (const FileName:Сохраняет содержимое поля в файле
String);
procedure SaveToStream (Stream: TStream) ; Сохраняет содержимое поля в потоке
Для работы с мемо-полями используются компоненты TDBMeino и TDBRichEdit.
Целочисленные поля
Целочисленные поля применяются для хранения целых чисел различной длины:
TIntegerField — от -2 147 483 648 до +2 147 483 647;
TSmal lint Field — от -32 768 до +32 767;
TWordField — от 0 до 65 535.
Следующие два свойства определяют максимальное и минимальное значения поля: property MaxValue: Integer property MinValue: Integer
По умолчанию оба свойства содержат 0, что означает отсутствие ограничении. Если MaxValue > MinValue и вводимое в поле значение вышло из указанного диапазона, возникает исключительная ситуация.
Следующее свойство осуществляет форматирование данных перед их показом во всех режимах, кроме режима редактирования:
property DisplayFormat: String
Форматирование для режима редактирования реализует другое свойство:
property EditFormat: String
Оба свойства унаследованы полями от общего родителя TNumericField. Для описания формата в них могут использоваться символы^спе!|ификаторы, перечисленные в табл. 3.10.
Таблица 3.10. Символы-спецификаторы
Спецификатор
Описание
с
Отображает сначала дату в формате дц.мм.гг, затем пробел и время в формате чч.мм.сс: 20.07.03 19:45:00
d
Отображает день месяца без ведущего нуля: 20
dd
Отображает день с ведущим нулем: 02
dddd
Отображает день недели суббота (для нерусифицированной версии Windows — Saturday)
ddddd
Отобраисает дату в формате дд.мм.гг: 20.07.03
dddddd
Отображает дату в формате день Месяц год: 20 Июль 2003 (для неру- снфицированной версии Windows — 20 Jule 2003)
m
Отображает месяц без ведущего нуля: 7
mm
Отображает месяц с ведущим нулем: 07
mmm
Отображает сокращенное название месяца: июл
mmmm
Отображает полное название месяца: Июль
уилиуу
Отображает две последние цифры года: 03
yyy или yyyy
Отображает все цифры года: 2003
b
Отображает час без ведущего нуля: 19
hh
Отображает час с ведущим нулем: 09
n
Отображает минуты без ведущего нуля: 45
nn
Отображает минуты с ведущим нулем: 05
s
Отображает секунды без ведущего нуля: 0
ss
Отображает секунды с ведущим нулем: 00
Таблица 3.10 (продолжение)
Спецификатор
Описание
t
Отображает время в формате чч:мм: 19:45
tt
Отображает время в формате чч:мм:сс: 19:45:00
am/pm
Отображает время в 12-часовом формате (атп — до полудня, pm — после полудня). Для спецификаторов hh:mm am/pm получим 07:45 pm
ampm
Отображает время в 12-часовом формате, но без указания до/после полудня. Для спецификаторов hh:mm ampm получим 07:45
а/p
Отображает время в 12-часовом формате (а — до полудня, р — после полудня). Для спецификаторов hh:mm а/p получим 07:45 р
/
Отображает используемый в Windows разделитель даты. Для спецификаторов d/m/y получим 20,7.03
Отображает используемый в Windows разделитель времени. Для спецификаторов h:m:s получим 19:45:0
Вещественные поля
Вещественные поля используются для хранения вещественных чисел:
TFloatField — числа от 5,0 • 10~324 до 1,7 • 10+30в с точностью 15-16 цифр;
TCurrencyField — аналогично TFloatField, но в денежном формате;
TBCDField — вещественные десятичные числа в двоично-десятичном виде с фиксированным количеством разрядов после запятой (Delphi не поддерживает тип BCD, поэтому при работе с полем используется тип Currency, что определяет до 20 значащих цифр и до 4 цифр после запятой; применяется только в таблицах Paradox).
Следующее свойство определяет количество знаков после десятичной запятой (по умолчанию — 15):
property Precision: Integer
Это свойство не может иметь значение меньше 3.
Свойства Maxvalue, MinValue, DisplayFormat и EditFormat аналогичны по назначению одноименным свойствам целочисленных полей.
Логические поля
Поля TBooleanField предназначены для хранения логических значений. Их следующее свойство определяет формат отображения данных, например в виде строк True или False, Да или Нет и т. п.:
property Displayvalues: String
Если свойство не определено, значения отображаются как True и False, в противном случае часть строки до первого символа точки с запятой (;) используется для представления истинного значения, а остальная часть — для представления ложного значения (например, Да; Нет).
Поля даты и времени
Поля даты и времени перечислены в табл. 3.11.
Таблица 3.11. Поля даты и времени
Поле
Описание
TDateTimeField
Содержит значения даты и времени в формате TDateTime
TDateField
Содержит значения даты в формате TDate
TTimeField
Содержит значения времени в формате TTime
TSQLTimeStamp
Содержит значение даты и времени в формате TSQLTimeStanip
Следующее свойство перечисленных в таблице полей предназначено для форматирования значений, отображаемых в визуальных компонентах:
property DisplayValues: String
Строка Displayvalues может содержать символы-спецификаторы, перечисленные в табл. 3.10.
Тип TSQLTimeStamp введен для максимально точного отображения даты-времени в технологии dbExpress.NET. Он представляет собой запись следующего вида:
type TSQLTimeStamp = packed record
Year : Smalllnt;
Month : Word;
Day : Word;
Hour : Word;
Minute : Word;
Second : Word;
Fractions : LongWord;
end;
Здесь Year определяет год в диапазоне от 0 до 9999; Month — месяц от 1 до 12; Day — день месяца от 1 до 28-31; Hour — час от 0 до 23; Minute — минуты от 0 до 59; Second — секунды от 0 до 59; Fractions — миллисекунды от 0 до 999.
Поля для хранения значений произвольных форматов
Поле TBlobField предназначено для хранения больших двоичных объектов (Binary Large Object, BLOB), то есть неформатированных значений произвольной длины.
Специфические свойства поля TBlobField перечислены в табл. 3.12.
Таблица 3.12. Свойства поля TBlobField
Свойство
Описание
property ВlobSize: Integer;
Содержит текущее значение длины буфера в байтах, необходимого для размещения поля
Таблица 3.12 (продолжение)
Свойство
Описание
type TBlobType = (ftBlob,
Определяет содержимое поля: ftBlob — не-
ftMenio, f tGraphic, f tFintMemo,
форматированные данные; ftMemo — много-
ftParadoxOle, ftDBaseOle,
строчный текст; ftGraphic — графическое
ftTypedBinary);
изображение; ftFmtMemo — многострочный
property BlobType: TBlobType;
текст в формате RTF; ftParadoxOle — OLE- объект таблиц Paradox; ftDBaseOle — OLE- объект таблиц dBASE; ftTypedBinary — типизированные двоичные данные
property IsNull: Boolean;
Содержит True, если поле пустое
property Modified: Boolean;
Содержит True, если изменилось значение поля
property Transliterate: Boolean;
Указывает, следует ли производить преобразование символов в кодировку ANSI при чтении строк из реальной ТБД и при записи строк обратно в ТБД в том случае, если строки в ТБД хранятся не в кодировке ANSI или содержат расширенные А8С1Ьсимволы
property Value: String;
Используется для чтения/записи данных
Специфические методы поля TBlobField перечислены в табл. 3.13.
Таблица 3.13. Методы поля TBlobField
Метод
Описание
procedure Assign (Source: TPersistent);
Запухает в поле значение поля Source другого НД
procedure Clear;
Очищает поле
procedure LoadFromFile (const
FileName: String);
Загружает содержимое поля из файла
procedure LoadFromStream (Stream: TStream);
Загружает содержимое поля из потока
procedure SaveToFile(const
FileName: String);
Сохраняет содержимое поля в файле
procedure SaveToStream (Stream: TStream);
Сохраняет содержимое поля в потоке
Поле TVarBytesField содержит произвольное значение длиной до 65 535 байт. Текущая длина хранится в первых двух байтах и может быть получена с помощью свойства DataSize.
Поле TGraphicField является частным случаем поля TBlobField и предназначено для хранения изображений.
Компоненты TSession и TDatabase. Транзакции
Описываемые в этом разделе компоненты TSession и TDatabase используются как в клиент-серверных, так и в файл-серверных БД. Однако их роль в файл-сер- верных БД невелика. В условиях многопользовательской работы с данными часто возникают ситуации, когда два и более пользователя пытаются изменить одни и те же (или связанные друг с другом) данные. В файл-серверных БД нет надежных способов обеспечения ссылочной целостности и непротиворечивости данных. В клиент-серверных БД для этого активно применяется механизм транзакций. Замечу» что реализация транзакций с помощью методов компонента TDatabase типична лишь для файл-серверных БД и БД, обслуживаемых сервером InterBase. В других серверах есть собственные эффективные средства реализации транзакций.
Компонент TSession
Компонент TSession реализует так называемый сеанс связи с базами данных, в рамках которого обеспечивается управление соединениями программы с базами данных. Каждая программа, работающая с БД любой архитектуры, автоматически получает в свое распоряжение глобальный объект Session, поэтому явное размещение на форме дополнительных компонентов TSession требуется только в том случае, если программист хочет использовать несколько независимых каналов (потоков команд) для связи с данными (один компонент создает один поток).
ПРИМЕЧАНИЕ
Каждый дополнительный сеанс, связанный с клиент-серверной БД, увеличивает на единицу счетчик подключений сервера.
Свойства, методы и события
Наиболее важные свойства компонента TSession перечислены в табл. 3.14.
Таблица 3.14. Свойства компонента TSession
Свойство
Описание
property AutoSessionName: Boolean;
Если содержит True, Delphi автоматически создает таранти ро ван но уникальное имя сеанса. Такая необходимость вози икает при разработке трехзвенных приложений
TConfigModes = (cfmVirtual, cfmPersistent, cfmSession);
TConfigMode = set of TConfigModes;
property ConfigMode: TConfigMode;
Определяет доступность псевдонимов BDE для сеанса: cfmVirtual — доступны все псевдонимы; cfmPersistent — доступны только постоянные псевдонимы; cfmSession —доступны только те псевдонимы, которые созданы в рамках дшшого сеанса
property Databasecount: Integer;
Содержит количество активных компонентов TDatabase, обслуживаемых в рамках данного сеанса
Таблица 3.14 (продолжение)
Свойство
Описание
property Databases [Index: Integer]:
Открывает индексированный доступ к лю-
TDatabase;
бому активному компоненту TDatabase, который обслуживается данным сеансом
property KeepConnections: Boolean;
Если содержит True, временно созданные в рамках сеанса компоненты TDatabase будут сохранять соединение с сервером БД, даже если нет ни одного связанного с иими активного НД
property SessionName: String;
Уникальное имя сеанса. Это свойство игнорируется, если свойство AutoSessionName содержит значение True
property SQLHourGlass: Boolean;
Если содержит True, указатель мыши изменяет форму при операциях в рамках данного сеанса
Наиболее важные методы компонента TSession перечислены в табл. 3.15.
Таблица 3.15. Методы компонента TSession
Метод
Описание
procedure AddAlias(const Name,
Driver: String; List: TStrings);
Создает новый временный псевдоним для связи с SQL-сервером: Name — имя псевдонима; Driver — имя обслуживающего драйвера; List — список параметров. Для сохранения временного псевдонима используйте метод SaveConfigFile
procedure AddPassword (const Password: String);
Добавляет к сеансу пароль для доступа к защищенным таблицам Paradox
procedure AddStandardAlias (const
Name, Path. Defau 1 tDriver: String);
Создает новый временный псевдоним для связи с таблицами Paradox, dBase или ASCII: Name — имя псевдонима; Path — путь доступа к таблицам; DefaultDriver — имя обслуживающего драйвера (может быть одним из трех: Paradox, DBASE или ASCIIDRV). Для сохранения временного псевдонима используйте метод SaveConf igFile
procedure Close;
Закрывает сеанс и все обслуживаемые им соединения с БД
procedure DeleteAlias (const
Name: String);
Удаляет псевдоним из сеанса
procedure Dropconnections;
Освобождает все неактивные соединения
function FindDatabase (const
DatabaseName: String): TDatabase;
Возвращает NTLt если БД DatabaseName недоступна в текущем сеансе
Компоненты TSession и TDatabase. Транзакции 141
Метод
Описание
procedure GetAliasNames (List: TStrings);
Наполняет список List именами доступных для сеанса псевдонимов с учетом свойства ConfigMode
procedure GetDatabaseNames (List: TStrings);
Наполняет список List именами всех доступных для сеанса псевдонимов
function Get Pas sword: Boolean;
Создает и показывает стандартное диалоговое окно для доступа к защищенным таблицам Paradox
procedure
GetStoredProcNames(const DatabaseName: String; List: TStrings);
Наполняет список List именами хранимых процедур из БД DatabaseName
procedure GetTableNames (const
DatabaseName, Pattern: String; Extensions, SystemTables: Boolean; List: TStrings);
Наполняет список List именами таблиц из БД DatabaseName: Pattern — шаблон выбора; Extensions = True> SystemTables = True, если должны отображаться, соответственно, расширения табличных файлов и системные таблицы
function IsAlias (const Name: String): Boolean;
Возвращает True, если сеанс обслуживает БД с псевдонимом Name
procedure SaveConf igFile;
Сохраняет временные псевдонимы, созданные методами AddAlias и AddStandardAlias в конфигурационном файле BDE
События компонента TSession перечислены в табл. 3.16.
Таблица 3.16. События компонента TSession
Событие
Описание
type Т Ра s swo г dEven t =
procedure(Sender: TObject; var
Continue: Boolean) of object;
Возникает при открытии защищенных таблиц Paradox
property OnPassword : TPasswordEvent;
property OnStartup: TNotifyEvent;
Возникает при активизации сеанса
Использование
Как видно из приведенного обзора свойств, методов и событий компонента TSession, его основное назначение — управление псевдонимами, получение информации о базах данных и их таблицах, а также организация беспарольного доступа к защищенным таблицам Paradox.
С помощью методов AddAlias и Addst andardAl ias программа может создавать временные псевдонимы, которые обеспечивают доступ к данным только
внутри сеанса. Однако с помощью метода SaveConf igFile можно перенести временные псевдонимы в конфигурационный файл BDE и, таким образом, сделать их постоянными.
Методы GetAliasNames и GetDatabaseNames различаются тем, что первый учитывает значение свойства Conf igMode, а второй игнорирует его и показывает любые доступные сеансу псевдонимы, в том числе локальные, которые создают подключаемые к сеансу компоненты TDatabase (локальные псевдонимы не сохраняются методом SaveConf igFile).
Целая группа методов поддерживает доступ к защищенным таблицам. Если эти методы не используются, при попытке открыть таблицу появляется стандартное диалоговое окно запроса пароля.
Это же окно создается при обращении к методу GetPassword. Если с помощью метода AddPassword указать пароль до открытия таблицы и не предпринимать никаких других мер, таблица будет открыта без диалога с пользователем. Наконец, можно создать обработчик события OnPassword и в нем реализовать нестандартный диалог.
ВНИМАНИЕ
Если в обработчике вызвать метод GetPassword, программа «зациклится*.
Для демонстрации некоторых возможностей компонента TSession (рис. 3.5) В файлах к проекту вы найдете проект Gi03\Session\SessionDemo.dpr (листинг 3.2).
Листинг 3.2. Демонстрация некоторых возможностей компонента TSession
unit Unitl;
interface
uses
Windows, Messages, SysUtils, Variants, Classesr Graphics, Controls# Forms, Dialogs, Borland.Vcl.StdCtrls, System.ComponentModel, Borland,Vcl.Db, Borland.Vcl.DBTables; type
TForml 二 class(TForm)
Memol: TMemo;
Buttonl: TButton;
Button2: TButton;
Button4: TButton;
Buttons: TButton;
Databasel: TDatabase;
Database2: TDatabase;
procedure procedure procedure procedure procedureprivateprocedure procedure procedure procedure procedureprivateFormDestroy(Sender: TObject);
procedure procedure procedure procedure procedure
private
procedure procedure procedure procedure procedure
private
Button5Click(Sender: TObject);
Button4Click(Sender: TObject); Button2Click(Sender: TObject); ButtonlClick(Sender: TObject);
f Private declarations ,
NewAliasName: String; public
{ Public declarations ? end;
var Forml: TForml;
inqplementat ion f$R *.DFMJ
procedure TForml.ButtonlClick(Sender: TObject);
Показывает список постоянных псевдонимов var
List: TStringList;// Для сортировки псевдонимов
begin
List := TStringList.Create;
List«Sorted := True;
// Если убрать следующий оператор, список будет совпадать
// с тем, что возвращает Add^tandardA 1 ias
Session.ConfigMode := cmPersistent;
Session.GetAliasNames(List);
Memol.Lines.Assign(List); end;
procedure TForml.Button2Click(Sender: TObject); // Показывает список любых псевдонимов var List: TStringList; begin
List := TStringList.Create;
List.Sbrted := True;
Session.GetDatabas^ames (List);
Memo 1. Lines. Assign (List); end;
procedure TForml.Button4Click(Sender: TObj ect); // Вывод Списка таблиц var
List: TStringList;
begin List := TStringList<Create; List.Sorted := True;
Session.GetTableUamesf•BIBLDATA1,''#True,False,List);
Memo!.Lines.Assign(List) end;a
продолжение 步
Листинг 3.2 (продолжение)
procedure TForml.ButtonBClick(Sender: TObjecc);
// Создание нового псевдонима begin if NgwAIiasName = '' then begin
NewA.l iasblame :=
InputBox{'Создание нового псевдонима', 'Псевдоним:',1'); if NewAliasName 丁 '' then Exit; if Session.IsAlias(NewAliasName) then begin
ShowMussage(
Format('Псевдоним %s уже существует!', [NewAliasName])); NewAliasName :二''; Exit
end;
Sessi on.AddStandardAlias(NewAliasName('C:\','ASCIIDRV1); Session.SaveConfigFile end end;
procedure TForml.FormDescroy(Sender: TObject);
// Удаление ненужного псевдонима
begin
if Session.IsAlias(NewAliasName) then
Session.DeleteAlias(NewAliasName);
// В документации говорится, что вызов DeleLeAlias
// должен сопровождаться обращением к SaveConfigFi Je.
// Как зудите, это не так
end;
end.
АВBIBLDATADBDEMOSIBLocalIB_BIBLIB_BIBL1251LocalserverParadox fliesXtreme Sample Database 2GG3База данных MS AccessФайлы dBASEФайлы ExcelАВBIBLDATADBDEMOSIBLocalIB_BIBLIB_BIBL1251LocalserverParadox fliesXtreme Sample Database 2GG3База данных MS AccessФайлы dBASEФайлы ExcelСписок постоянных псевдонимовСписок постоянных псевдонимовСписок веек псевдонимов ::Список веек псевдонимов ::Список таблиц из БД BIBLDATAСписок таблиц из БД BIBLDATAСоздание ноеога псевдонимаСоздание ноеога псевдонима
А
В
BIBLDATA
DBDEMOS
IBLocal
IB_BIBL
IB_BIBL1251
Localserver
Paradox flies
Xtreme Sample Database 2GG3
База данных MS Access
Файлы dBASE
Файлы Excel
А
В
BIBLDATA
DBDEMOS
IBLocal
IB_BIBL
IB_BIBL1251
Localserver
Paradox flies
Xtreme Sample Database 2GG3
База данных MS Access
Файлы dBASE
Файлы Excel
Список постоянных псевдонимов
Список постоянных псевдонимов
Список веек псевдонимов ::
Список веек псевдонимов ::
Список таблиц из БД BIBLDATA
Список таблиц из БД BIBLDATA
Создание ноеога псевдонима
Создание ноеога псевдонима
Рис. 3.5. Окно 叩оектё! SessionDemo.dpr
Небольшие пояснения. Обработчики щелчков на кнопках Buttonl (Alias), Button2 (Database) и Button4 (Tables) помещают создаваемые методами GetAliasNamest GetDatabaseNames и GetTableNames списки в промежуточный компонент List, чтобы отсортировать списки по алфавиту (строки в TMemo. Lines сортировать значительно сложнее).
Компонент TDatabase
В отличие от компонента TSession, который управляет множеством БД, компонент TDatabase обслуживает единственную базу данных (как файловую, так и серверную). Он выполняет две основные функции: создает локальный псевдоним БД и управляет транзакциями.
Наиболее важные свойства компонента TDatabase перечислены в табл. 3.17.
Таблица 3.17. Свойства компонента TDatabase
Свойство
Описание
property AliasName: String;
Определяет имя псевдонима БД, которую обслуживает компонент
property Connected: Boolean;
Содержит True, если соединение компонента БД активно
property DatabaseName: String;
Определяет локальный псевдоним БД или путь доступа к таблицам Paradox или dBASE
property DataSetCount: Integer;
Указывает количество обслуживаемых компонентом наборов данных
property DataSets [Index: Integer]:
TDBDataSet;
Открывает индексированный доступ ко всем обслуживаемым компонентом наборам данных
property Directory: String;
Содержит папку размещения таблиц Paradox или dBASE
property DriverName: String;
Указывает имя драйвера, обслуживающего БД
property Exclusive: Boolean;
Если содержит True, блокирует доступ других пользователей к БД Paradox или dBASE
property InTransaction: Boolean
Содержит True, если в БД имеется незавершенная транзакция
property KeepConnection: Boolean;
Если содержит True, компонент будет сохранять связь с БД даже после закрытия всех обслуживаемых им НД
property LoginPrompt: Boolean;
Разрешает/запрещает диалог с пользователем при первом открытии серверной БД
property Params: TStrings;
Содержит список параметров, передаваемых BDE в момент открытия БД
Таблица 3.17 (продолжение)
Свойство
Описание
property Readonly: Boolean;
Если содержит True, компонент открывает БД только для чтения
TTransIsolation = (tiDirtyRead, tiReadCommitted, tiRepeatableRead); property Translsolation: TTransIsolation;
Определяет уровень изоляции транзакций (см. далее раздел «Транзакции»)
Наиболее важные методы компонента TDatabase перечислены в табл* ЗЛ8.
Таблица 3.18. Методы компонента TDatabase
Метод
Описание
procedure CloseDatasets;
procedure Commit;
Закрывает все связанные с компонентом НД Подтверждает все изменения, сделанные в текущей транзакции, и закрывает ее
procedure Rollback;
Отменяет все изменения, сделанные в текущей транзакции, и закрывает ее
procedure StartTransaction;
Открывает транзакцию
Транзакции
В технологии BDE.NET клиентская программа управляет транзакциями с помощью трех методов компонента TDatabase: StartTransact ion (начинает транзакцию), Commit (подтверждает транзакцию) и Rollback (отменяет все изменения, сделанные с момента старта транзакции):
Databasel.StartTransaction; 〃 Стартуем транзакцию
// Любые изменения в любых таблицах try
Databasel.Commit // Пытаемся подтвердить изменена
except
Databasel.Rollback // Откатг ест подтвердить не удалось end;
ПРИМЕЧАНИЕ
Откат транзакции ликвидирует также все последствия возможного срабатывания триггеров на сервере БД в рамках отмененной транзакции.
Изоляция транзакций
Компонент TDatabase с помощью своего свойства TransIsolatioin обеспечивает нужный уровень изоляции транзакций. Изолировать транзакции необходимо при одновременном доступе к одним и тем же данным нескольких пользователей.
При уровне изоляции Dirty Read любой пользователь видит любые изменения в данных, даже если они еще не подтверждены. В этой ситуации может нарушиться непротиворечивость данных: если пользователь, изменивший данные, по каким-либо причинам откатит сделанные им изменения, другой пользователь никак не узнает об этом в момент, когда он будет делать свои изменения. Уровень Duty Read фактически не изолирует транзакции. Только этот уровень возможен для файл-серверных БД, вот почему в СУБД этого типа транзакции используются крайне редко.
Уровень Read Committed разрешает транзакции видеть только подтвержденные изменения. Этот уровень рекомендуется для клиент-серверных БД (по умолчанию компонент TDatabase автоматически устанавливает уровень Dirty Read для файл -с ерверных и уровень Read Committed — для клиент-серверных БД).
Для клиент-серверных БД возможен также уровень Repeatable Read (повторяющееся чтение). На этом уровне изоляции также читаются только подтвержденные изменения, однако раз прочитанная запись помещается в локальный буфер и повторно читается из этого буфера, то есть повторное чтение не позволяет увидеть изменений, внесенных другим пользователем, даже если эти изменения подтверждены.
Свойство UpdateMode наборов данных
Успех или неуспех транзакции во многом зависит от свойства UpdateMode соответствующего НД. Это свойство определяет, по каким столбцам сервер ищет в таблице запись, чтобы внести в нее изменения. Если пользователь А первым подтвердит изменения, а свойство UpdateMode соответствующего НД у конкурирующего пользователя Б имеет заданное по умолчанию значение upWhereAll, его транзакция будет отвергнута, так как в этом случае сервер ищет запись, в которой все столбцы имеют те значения, которые были к моменту старта транзакции Б. Если свойство имеет значение upWhereChange, ищется запись, у которой ключевые столбцы и столбцы с изменениями остались прежними. В этом случае транзакция Б пройдет успешно, если оба пользователя изменяли разные столбцы, и может быть нарушена непротиворечивость данных. Еще хуже защищаются данные в случае, если свойство UpdateMode имеет значение upWhereKeyOnly, которое заставляет сервер искать запись только по ключевым столбцам.
Таким образом, значение t iReadCommi 11 ed (или t iRepeatableRead) свойства Translsolation компонента TDatabase в сочетании co значением upWhereAll свойства UpdateMode НД в максимальной степени защищают данные от искажения в условиях многопользовательской работы.
Далее описывается пример перевода денег с дебиторского счета на кредиторский под защитой транзакции. В БД IB_BIBLGDB есть две небольшие таблицы, DEB и CRED, имитирующие дебиторские и кредиторские счета. На рис. 3.6 показано окно работающей программы.
Рис. 3.6. Окно программы, иллюстрирующей использование транзакции
Ниже показан обработчик щелчка на кнопке Перевести: procedure TForm2.ButtonlClicktSender: TObject); / / Переводит деньги с дебиторского счета // на кредиторский под защитой транзакции var
Sum: Double; // Сумма перевода CmdStr: TStringList;
begin
/ / Проверяем сумму перевода
if SpinEditl.Text = '1 then Exit;
Sum := StrToFloat(SpinEditl.Text); if Sum > DEBSumm.Value then begin // Сумма слишком велика SpinEditl.Text :二 FloatToStr(DEBSumm.Value); SpinEditl.SetFocus; Exit;
end;
// Строка для снятия денег:
CmdStr := TStringList.Create;
CmdStr.Add(Format(* UPDATE DEB SET SUMM=%d WHERE NCOUNT=%d', [Round(DEBSumm.Value - Sum), DEBNCount.Value]));
// Добавляем ее в свойство SQL-запроса: Queryl.SQL := CmdStr;
CmdStr.Clear;
/ / Строка для на числения денег:
CmdStr.Add(Format{'UPDATE CRED SET SUMM=%d WHERE NCOUNT=%d', [Round (CREDSumm. Value + Sum), CP.EDNCount .Value] });
with DB do begin.
StartTransaction;// Стартуем транзакцию
try
Queryl.ExecSQL;// Снимаем деньги
Queryl.SQL :二 CmdStr;
Query1.ExecSQL; //Начисляем деньги
Commit;//Подтверждаем транзакцию
ShowMessage('ОК');
except//Ошибка/
Rollback;//Откатываем транзакцию
ShowMessage('NO');
end;
// Обновляем отображаемые данные:
DEB.Active := False;
DEB.Active := True;
CRED.Active := False;
Cred.Active := True;
SpinEdi11.Value := 0;
SpinEditl.SetFocus;
end; end;
procedure TForm2.FormActivate(Sender: TObject);
// Передает фокус ввода полю SpinEditl в момент актияизации формы begin
SpinEditl.SetFocus;
end;
Для ввода суммы перевода используется поле типа TSpeenEdit (категория Samples). Этот компонент рассчитан на ввод целых чисел и отвергает любой неправильный ввод. Обратите внимание: перед выполнением операторов UPDATE новые суммы счетов приводятся к целочисленному виду. Сделано это с тем, чтобы исключить влияние локализации на вид строкового представления вещественных чисел: если вм, как и я, работаете с русифицированной версией Windows, разлелителем целой и дробной частей вещественного числа является запятая, в то время как InterBase в типе Float использует для этого точку. Чтобы не усложнять программу, я решил отказаться от копеек. На практике это, разумеется, недопустимо.
Наборы данных
Под набором данных (НД) понимается группа записей из одной или нескольких таблиц БД, доступная для компонентов-наборов ТТаЫе, TQuery или TStoredProc. Эти компоненты порождены от общего родительского класса TDBDataSet, который и рассматривается в этом разделе. Таким образом, все излагаемые здесь сведения в равной степени относятся к любому компоненту-набору. Особенностям работы с компонентами ТТаЫе и TQuery посвящены два следующих раздела, а компонент TStoredProc рассматривается в главе 7.
Обзор свойств, методов и событий
Здесь рассматриваются наиболее важные свойства, методы и события класса TDBDataSet.
Свойства
Свойства компонента TDBDataSet перечислены в табл. 3.19.
Таблица 3.19. Свойства набора данных
Свойство
Описание
property Active: Boolean;
propertyActiveRecord: Integer;
property AggFields: TFields;
Открывает/закрывает НД
Указывает индекс активной записи
Содержит все агрегатные поля НД. В отличие от вычисляемых полей, которые оперируют полями одной записи, агрегатные поля оперируют значениями всех записей одного поля
property AutoCalcFields: Boolean;
Разрешает/запрещает возникновение события
OnCalcFields
property Bof: Boolean;
Содержит True, если курсор НД указывает на первую запись
type TBookmarkStr: String;
property Bookmark: TBookmarkStr;
Определяет закладку на текущей записи. К помеченной записи можно быстро перейти методом GotoBookmark
property Bookmarksize: Integer;
property BufferCount : Integer;
Определяет длину закладки в байтах
Указывает количество записей во внутреннем буфере (кэше)
property Buffers : IntPtr;
Открывает индексированный доступ к записям во внутреннем буфере
property CasheBlobs: Boolean;
Разрешает/запрещает кэширование BLOB- полей
property CaBhedUpdates: Boolean;
Разрешает/запрещает кэширование вносимых пользователем изменений
property CanModifу : Boolean;
Указывает, может ли пользователь изменять НД
property CurrentRecord: Integer;
Указывает индекс текущей записи во виут- реннем буфере
property Database: TDatabase;
Определяет компонент TDatabase, связанный с данным НД
property DatabaBeName: String;
Содержит псевдоним базы данных
property DataSetField:
Содерясит ссылку на владельца вложенного НД
TDataSetField;
property DataSource: TDataSource;
Используется в потомках для указания детального НД в связи один ко многим
property DBSession: TSession.;
Определяет связанный с НД компонент TSes- sion
property DefaultFields: Boolean;
Содержит True, если для НД не создано ни одного объекта-поля
СвойствоСвойствоОписание
Свойство
Свойство
property EOF: Boolean;property Fieldcount: Integer;property FieldList: TFieldList;property Fields: TFields;property Fieldvalues [const FieldName: String]: Variant;property Filter: String;property Filtered: Boolean;property Filteroptions: TFilterOptions;property Found: Boolean;property IsUnidirectional :Boolean;property EOF: Boolean;property Fieldcount: Integer;property FieldList: TFieldList;property Fields: TFields;property Fieldvalues [const FieldName: String]: Variant;property Filter: String;property Filtered: Boolean;property Filteroptions: TFilterOptions;property Found: Boolean;property IsUnidirectional :Boolean;property Modified: Boolean;property RecNo: Longlnt;property Recordcount: Longlnt;property Recordsize: Word;property SessionName: String;type TDataSetState = (dslnactive dsBrowse, dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter, dsNeWalue, dsOldValue, dsCurValue, dsBlockRead, dsInternalCalc);property State: TDataSetState;property Modified: Boolean;property RecNo: Longlnt;property Recordcount: Longlnt;property Recordsize: Word;property SessionName: String;type TDataSetState = (dslnactive dsBrowse, dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter, dsNeWalue, dsOldValue, dsCurValue, dsBlockRead, dsInternalCalc);property State: TDataSetState;Содержит True, если курсор НД сместился за последнюю записьСодержит количество полей в НДСодержит список имен всех полей со всеми вложенными полямиПозволяет обратиться к полям по их индексу (см. далее). Первое поле НД имеет индекс ОПозволяет обратиться к значениям полей по имени поля (см. далее)Задает фильтрующее выражениеРазрешает/запрещаег фильтрацию записей НД Определяет условия фильтрации в текстовых полях: foCaselnsensitive — учитывать регистр букв; foNoPart i alCompare — поиск на точное соответствие образцуСодержит True, если вызов одного из методов FindXXXX был успешнымЕсли содержит True, НД имеет однонаправленный курсор. В таких НД запрещета иная навигация, кроме как методами First и Next. Эти НД не поддерживают фильтрацию, закладки, не могут иметь подстановочных полей и отображаться в сеткахСодержит True, если текущая запись НД была измененаОпределяет номер текущей записиСодержит количество записей в текущем НДОпределяет размер в байтах буфера для размещения одной записи НДСодержит имя компонента TSessionУказывает состояние НД: dslnactive — закрыт; dsBrowse — просмотр; dsEdit — редактирование; dslnsert — вставка; dsSetKey — поиск записи; dsCalcFields — установка вычисляемых полей; dsFilter — фильтрация записей; dsNewValue — обновление свойства TField. NewValue: dsOldValue — обновление свойства TField.OlcIValue; dsCur- Value — обновление свойства TField.Cur- Value; dsBlockRead — чтение блока записей; dslnternalcalc — обновление полей TField, для которых FieldKind 二 fklnter- nalCalcСодержит True, если курсор НД сместился за последнюю записьСодержит количество полей в НДСодержит список имен всех полей со всеми вложенными полямиПозволяет обратиться к полям по их индексу (см. далее). Первое поле НД имеет индекс ОПозволяет обратиться к значениям полей по имени поля (см. далее)Задает фильтрующее выражениеРазрешает/запрещаег фильтрацию записей НД Определяет условия фильтрации в текстовых полях: foCaselnsensitive — учитывать регистр букв; foNoPart i alCompare — поиск на точное соответствие образцуСодержит True, если вызов одного из методов FindXXXX был успешнымЕсли содержит True, НД имеет однонаправленный курсор. В таких НД запрещета иная навигация, кроме как методами First и Next. Эти НД не поддерживают фильтрацию, закладки, не могут иметь подстановочных полей и отображаться в сеткахСодержит True, если текущая запись НД была измененаОпределяет номер текущей записиСодержит количество записей в текущем НДОпределяет размер в байтах буфера для размещения одной записи НДСодержит имя компонента TSessionУказывает состояние НД: dslnactive — закрыт; dsBrowse — просмотр; dsEdit — редактирование; dslnsert — вставка; dsSetKey — поиск записи; dsCalcFields — установка вычисляемых полей; dsFilter — фильтрация записей; dsNewValue — обновление свойства TField. NewValue: dsOldValue — обновление свойства TField.OlcIValue; dsCur- Value — обновление свойства TField.Cur- Value; dsBlockRead — чтение блока записей; dslnternalcalc — обновление полей TField, для которых FieldKind 二 fklnter- nalCalc
property EOF: Boolean;
property Fieldcount: Integer;
property FieldList: TFieldList;
property Fields: TFields;
property Fieldvalues [const FieldName: String]: Variant;
property Filter: String;
property Filtered: Boolean;
property Filteroptions: TFilterOptions;
property Found: Boolean;
property IsUnidirectional :
Boolean;
property EOF: Boolean;
property Fieldcount: Integer;
property FieldList: TFieldList;
property Fields: TFields;
property Fieldvalues [const FieldName: String]: Variant;
property Filter: String;
property Filtered: Boolean;
property Filteroptions: TFilterOptions;
property Found: Boolean;
property IsUnidirectional :
Boolean;
property Modified: Boolean;
property RecNo: Longlnt;
property Recordcount: Longlnt;
property Recordsize: Word;
property SessionName: String;
type TDataSetState = (dslnactive dsBrowse, dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter, dsNeWalue, dsOldValue, dsCurValue, dsBlockRead, dsInternalCalc);
property State: TDataSetState;
property Modified: Boolean;
property RecNo: Longlnt;
property Recordcount: Longlnt;
property Recordsize: Word;
property SessionName: String;
type TDataSetState = (dslnactive dsBrowse, dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter, dsNeWalue, dsOldValue, dsCurValue, dsBlockRead, dsInternalCalc);
property State: TDataSetState;
Содержит True, если курсор НД сместился за последнюю запись
Содержит количество полей в НД
Содержит список имен всех полей со всеми вложенными полями
Позволяет обратиться к полям по их индексу (см. далее). Первое поле НД имеет индекс О
Позволяет обратиться к значениям полей по имени поля (см. далее)
Задает фильтрующее выражение
Разрешает/запрещаег фильтрацию записей НД Определяет условия фильтрации в текстовых полях: foCaselnsensitive — учитывать регистр букв; foNoPart i alCompare — поиск на точное соответствие образцу
Содержит True, если вызов одного из методов FindXXXX был успешным
Если содержит True, НД имеет однонаправленный курсор. В таких НД запрещета иная навигация, кроме как методами First и Next. Эти НД не поддерживают фильтрацию, закладки, не могут иметь подстановочных полей и отображаться в сетках
Содержит True, если текущая запись НД была изменена
Определяет номер текущей записи
Содержит количество записей в текущем НД
Определяет размер в байтах буфера для размещения одной записи НД
Содержит имя компонента TSession
Указывает состояние НД: dslnactive — закрыт; dsBrowse — просмотр; dsEdit — редактирование; dslnsert — вставка; dsSetKey — поиск записи; dsCalcFields — установка вычисляемых полей; dsFilter — фильтрация записей; dsNewValue — обновление свойства TField. NewValue: dsOldValue — обновление свойства TField.OlcIValue; dsCur- Value — обновление свойства TField.Cur- Value; dsBlockRead — чтение блока записей; dslnternalcalc — обновление полей TField, для которых FieldKind 二 fklnter- nalCalc
Содержит True, если курсор НД сместился за последнюю запись
Содержит количество полей в НД
Содержит список имен всех полей со всеми вложенными полями
Позволяет обратиться к полям по их индексу (см. далее). Первое поле НД имеет индекс О
Позволяет обратиться к значениям полей по имени поля (см. далее)
Задает фильтрующее выражение
Разрешает/запрещаег фильтрацию записей НД Определяет условия фильтрации в текстовых полях: foCaselnsensitive — учитывать регистр букв; foNoPart i alCompare — поиск на точное соответствие образцу
Содержит True, если вызов одного из методов FindXXXX был успешным
Если содержит True, НД имеет однонаправленный курсор. В таких НД запрещета иная навигация, кроме как методами First и Next. Эти НД не поддерживают фильтрацию, закладки, не могут иметь подстановочных полей и отображаться в сетках
Содержит True, если текущая запись НД была изменена
Определяет номер текущей записи
Содержит количество записей в текущем НД
Определяет размер в байтах буфера для размещения одной записи НД
Содержит имя компонента TSession
Указывает состояние НД: dslnactive — закрыт; dsBrowse — просмотр; dsEdit — редактирование; dslnsert — вставка; dsSetKey — поиск записи; dsCalcFields — установка вычисляемых полей; dsFilter — фильтрация записей; dsNewValue — обновление свойства TField. NewValue: dsOldValue — обновление свойства TField.OlcIValue; dsCur- Value — обновление свойства TField.Cur- Value; dsBlockRead — чтение блока записей; dslnternalcalc — обновление полей TField, для которых FieldKind 二 fklnter- nalCalc
Таблица 3.19 (продолжение)
Свойство
Описание
type TUpdateMode = (upWhereAll,
Определяет способ использования полей при
upWhereChanged, upWhereKeyOnly);
поиске обновляемых записей: upWhereAll —
property UpdateMode: TUpdateMode;
все поля; upWhereChanged — только ключевые поля и значения обновленных полей; upWhereKeyOnly — только ключевые поля
В Delphi свойство Fields ссылается на объект класса TFields. Однако свойство Fields типа TField этого объекта является умалчиваемым свойством, поэтому два следующих оператора эквивалентны:
Caption := Tablet.Fields[0].Value;
Caption := Tablel.Fields.Fields[0].Value;
Свойство Fieldvalues является умалчиваемым свойством для НД, поэтому два следующих оператора эквивалентны:
caption := Tablel.FieldValues[* Name'];
Caption := Tablel['Name'];
Замечу, что параметром обращения к набору данных может быть список полей, в котором соседние поля разделяются точкой с запятой. Это позволяет единственным оператором обращения к свойству прочитать в вариантный массив сразу несколько полей текущей записи:'
var
V: Variant;
begin
V := CreateVarArray([0, 2], varVariant);
V := Books[* BQuan;BName;BOpt'];
end;
Методы
Наиболее важные методы класса TDBDataSet перечислены в табл. 3.20.
Таблица 3.20. Методы набора данных
Метод
Описание
function ActiveBuf fer: IntPtr;
Возвращает указатель на буфер текущей записи
procedure Append;
Добавляет пустую запись в конец НД
procedure AppendRecord (const Values: array of coast);
Создает новую запись, заполняет ее поля значениями Values и добавляет ее в НД
procedure ApplyUpdates;
Записывает кэш обновлений в БД
function BookmarkVal id (Bookmark:
TBookmark): Boolean; override;
Возвращает True, если с закладкой Bookmark связано правильное значение
МетодМетодОписание
Метод
Метод
procedure Cancel ;procediure CancelUpdaces;procedure CheckBrowseMode;procedure ClearFields;procedure Close;procedure Commitupdates ;function CompareBookmarks(Bookmarkl, Bookmark2:TBookmark): Integer;procedure Delete;procedure Edit;function FieldByName (constFieldName: String): TField;function FindField (const FieldName: String): TField;function FindFirst: Boolean;function FindLast: Boolean;function FindNext: Boolean;function FindPrior: Boolean;procedure First;procedure FreeBookmark(Bookmark:TBookmark) ; virtual;ftmction Get Bookmark: TBookmark;virtual;function GetCurrentRecord(Buffer: intPtr): Boolean;procedure GetFieldNames (List: TStrings);procedure GotoBookmark( Bookmark: TBookmark);procedure Insert ;procedure insertRecord (constValues: array of const);procedure Cancel ;procediure CancelUpdaces;procedure CheckBrowseMode;procedure ClearFields;procedure Close;procedure Commitupdates ;function CompareBookmarks(Bookmarkl, Bookmark2:TBookmark): Integer;procedure Delete;procedure Edit;function FieldByName (constFieldName: String): TField;function FindField (const FieldName: String): TField;function FindFirst: Boolean;function FindLast: Boolean;function FindNext: Boolean;function FindPrior: Boolean;procedure First;procedure FreeBookmark(Bookmark:TBookmark) ; virtual;ftmction Get Bookmark: TBookmark;virtual;function GetCurrentRecord(Buffer: intPtr): Boolean;procedure GetFieldNames (List: TStrings);procedure GotoBookmark( Bookmark: TBookmark);procedure Insert ;procedure insertRecord (constValues: array of const);Отменяет все изменения текущей записи, которые не были сохранены в БДОчищает кэш обновленийЕсли НД находился в состоянии редактирования или вставки, вызывает метод Post для записи изменений в БДОчищает все поля текущей записиЗакрывает НДОчищает кэш после успешного обновления НД Сравнивает две закладки и возвращает 1, если они различаются, и 0, если они идентичны или пустыУдаляет текущую записьПереводит НД в режим редактирования Обеспечивает доступ к полю по его имени FieldNameИщет поле FieldName в НД и возвращает ссылку на поле или NXL, если поле не найдено Пытается установить курсор на первую запись НД и возвращает True в случае успеха Пытается установить курсор на последнюю запись НД и возвращает True в случае успеха Пытается установить курсор на следующую запись НД и возвращает True в случае успеха Пытается установить курсор на предыдущую запись НД и возвращает True в случае успеха Устанавливает курсор на первую запись в НД Освобождает память, связанную с закладкой BookmarkСоздает закладку на текущей записи и возвращает указатель на нееКопирует текущую запись в буфер Buffer и возвращает True в случае успехаНаполняет список List именами всех полей НДОбеспечивает возврат к записи, связанной с закладкой BookmarkПереводит НД в режим вставки записейСоздает пустую запись, наполняет ее поля значениями Values и вставляет ее в НДОтменяет все изменения текущей записи, которые не были сохранены в БДОчищает кэш обновленийЕсли НД находился в состоянии редактирования или вставки, вызывает метод Post для записи изменений в БДОчищает все поля текущей записиЗакрывает НДОчищает кэш после успешного обновления НД Сравнивает две закладки и возвращает 1, если они различаются, и 0, если они идентичны или пустыУдаляет текущую записьПереводит НД в режим редактирования Обеспечивает доступ к полю по его имени FieldNameИщет поле FieldName в НД и возвращает ссылку на поле или NXL, если поле не найдено Пытается установить курсор на первую запись НД и возвращает True в случае успеха Пытается установить курсор на последнюю запись НД и возвращает True в случае успеха Пытается установить курсор на следующую запись НД и возвращает True в случае успеха Пытается установить курсор на предыдущую запись НД и возвращает True в случае успеха Устанавливает курсор на первую запись в НД Освобождает память, связанную с закладкой BookmarkСоздает закладку на текущей записи и возвращает указатель на нееКопирует текущую запись в буфер Buffer и возвращает True в случае успехаНаполняет список List именами всех полей НДОбеспечивает возврат к записи, связанной с закладкой BookmarkПереводит НД в режим вставки записейСоздает пустую запись, наполняет ее поля значениями Values и вставляет ее в НД
procedure Cancel ;
procediure CancelUpdaces;
procedure CheckBrowseMode;
procedure ClearFields;
procedure Close;
procedure Commitupdates ;
function CompareBookmarks
(Bookmarkl, Bookmark2:
TBookmark): Integer;
procedure Delete;
procedure Edit;
function FieldByName (const
FieldName: String): TField;
function FindField (const FieldName: String): TField;
function FindFirst: Boolean;
function FindLast: Boolean;
function FindNext: Boolean;
function FindPrior: Boolean;
procedure First;
procedure FreeBookmark(Bookmark:
TBookmark) ; virtual;
ftmction Get Bookmark: TBookmark;
virtual;
function GetCurrentRecord
(Buffer: intPtr): Boolean;
procedure GetFieldNames (List: TStrings);
procedure GotoBookmark( Bookmark: TBookmark);
procedure Insert ;
procedure insertRecord (const
Values: array of const);
procedure Cancel ;
procediure CancelUpdaces;
procedure CheckBrowseMode;
procedure ClearFields;
procedure Close;
procedure Commitupdates ;
function CompareBookmarks
(Bookmarkl, Bookmark2:
TBookmark): Integer;
procedure Delete;
procedure Edit;
function FieldByName (const
FieldName: String): TField;
function FindField (const FieldName: String): TField;
function FindFirst: Boolean;
function FindLast: Boolean;
function FindNext: Boolean;
function FindPrior: Boolean;
procedure First;
procedure FreeBookmark(Bookmark:
TBookmark) ; virtual;
ftmction Get Bookmark: TBookmark;
virtual;
function GetCurrentRecord
(Buffer: intPtr): Boolean;
procedure GetFieldNames (List: TStrings);
procedure GotoBookmark( Bookmark: TBookmark);
procedure Insert ;
procedure insertRecord (const
Values: array of const);
Отменяет все изменения текущей записи, которые не были сохранены в БД
Очищает кэш обновлений
Если НД находился в состоянии редактирования или вставки, вызывает метод Post для записи изменений в БД
Очищает все поля текущей записи
Закрывает НД
Очищает кэш после успешного обновления НД Сравнивает две закладки и возвращает 1, если они различаются, и 0, если они идентичны или пусты
Удаляет текущую запись
Переводит НД в режим редактирования Обеспечивает доступ к полю по его имени FieldName
Ищет поле FieldName в НД и возвращает ссылку на поле или NXL, если поле не найдено Пытается установить курсор на первую запись НД и возвращает True в случае успеха Пытается установить курсор на последнюю запись НД и возвращает True в случае успеха Пытается установить курсор на следующую запись НД и возвращает True в случае успеха Пытается установить курсор на предыдущую запись НД и возвращает True в случае успеха Устанавливает курсор на первую запись в НД Освобождает память, связанную с закладкой Bookmark
Создает закладку на текущей записи и возвращает указатель на нее
Копирует текущую запись в буфер Buffer и возвращает True в случае успеха
Наполняет список List именами всех полей НД
Обеспечивает возврат к записи, связанной с закладкой Bookmark
Переводит НД в режим вставки записей
Создает пустую запись, наполняет ее поля значениями Values и вставляет ее в НД
Отменяет все изменения текущей записи, которые не были сохранены в БД
Очищает кэш обновлений
Если НД находился в состоянии редактирования или вставки, вызывает метод Post для записи изменений в БД
Очищает все поля текущей записи
Закрывает НД
Очищает кэш после успешного обновления НД Сравнивает две закладки и возвращает 1, если они различаются, и 0, если они идентичны или пусты
Удаляет текущую запись
Переводит НД в режим редактирования Обеспечивает доступ к полю по его имени FieldName
Ищет поле FieldName в НД и возвращает ссылку на поле или NXL, если поле не найдено Пытается установить курсор на первую запись НД и возвращает True в случае успеха Пытается установить курсор на последнюю запись НД и возвращает True в случае успеха Пытается установить курсор на следующую запись НД и возвращает True в случае успеха Пытается установить курсор на предыдущую запись НД и возвращает True в случае успеха Устанавливает курсор на первую запись в НД Освобождает память, связанную с закладкой Bookmark
Создает закладку на текущей записи и возвращает указатель на нее
Копирует текущую запись в буфер Buffer и возвращает True в случае успеха
Наполняет список List именами всех полей НД
Обеспечивает возврат к записи, связанной с закладкой Bookmark
Переводит НД в режим вставки записей
Создает пустую запись, наполняет ее поля значениями Values и вставляет ее в НД
Таблица 3.20 (продолжение)
Метод
Описание
function IsEmpty: Boolean;
function IsSequenced: Boolean;
override;
procedure Last;
function Locate (const KeyFields:
String; const KeyValues: Variant;
Options: TLocateOptions): Boolean;
Возвращай丄 True, если в НД пет записей
Возвращает True, если к записям НД можно обращаться с помощью свойства RecNo
Устанавливает курсор на последнюю запись Ищет в полях, перечисленных в параметре KeyFields, значения, указанные в KeyValuee при условиях, заданных параметром Options. Если запись найдена, делает ее текущей и возвращает True
function Lookup (const KeyFields: String; const KeyValues: Variant; const ResultFields: String):
Используется в детальных НД для поиска в полях KeyFields значений Keyvalues. При успехе возвращает значения полей Re-
Variant;
sultFields
procedure Next;
procedure Open;
procedure Post; virtual ;
Перемещает курсор к следующей записи
Открывает НД
Сохраняет вставленную или отредактированную текущую запись в таблице БД
procedure Prior;
procedure Refresh;
procedure SetFields (const
Values: array of const);
Перемещает курсор к предыдущей записи
Обновляет НД данными из БД
Устанавливает значения values во все поля текущей записи
События
Все события определены в секции published класса TDBDataSet и поэтому доступны в инспекторе объектов для компонентов-наследников этого класса.
События компонента TDBDataSet перечислены в табл. 3.21.
Таблица 3.21. События набора данных
Событие
Описание
type TOataSetNotifyEvent = proceduze(DataSet: TDataSet)
of object;
Серия событий AfterXXXX возникает после изменения состояния НД. Вместо символов ХХХХ в названиях событиб должны указывать-
property Af terAXXX:
TDataSetNoti fyEvent;
ся следующие: Cancel — возникает после отмены изменений в текущей записи; Close — возникает после закрытия НД; Delete — возникает после уничтожения записи НД; Edit — возникает после перехода НД в режим ds Edit; Insert — возникает после вставки записи; Open — возникает после открытия НД; Post — возникает после выполнения метода Post: Scroll — возникает после перехода к следующей записи
Наборы данных 155
Событие
Описание
property BetoreXXXX:
TDataSetNotifyEvent;
Серия событий BeforeXXXY возникает непосредственно перед изменением состояния НД. Вместо символов ХХХХ в названиях событий должны указываться следующие: Cancel — возникает перед отменой изменений в текущей записи; Close — возникает перед закрытием НД; Delete — возникает перед уничтожением записи НД; Edit — возникает перед переходом НД в режим dsEdit; Insert — возникает перед вставкой записи; Open. — возни* кает перед открытием НД; Post — возникает перед выполнением метода Post; Scroll — возникает после перехода к следующей записи
property OnCalcFields: TDataSetNotifyEvent;
Возникает при необходимости переопределения вычисляемых полей
type TFi IterRecordEvent 二 procedure(DataSet: TDataSet; var Accept: Boolean) of object;
property OnFi IterRecord: TFilterRecordEvent;
Возникает при фильтрации записей (после установки значения True в свойство Filtered). Обработчик должен поместить True в переменную Accept, если текущая запись удовлетворяет критерию фильтрации
property OnNewRecord:
TDataSetNotifyEvent;
Возникает при вставке или добавлении новой записи. Обработчик может установить начальные значения в поля записи и/или произвести каскадные изменения в связанных НД
Открытие и закрытие набора данных
Состояние НД определяется его свойством State, доступным только для чтения на этапе прогона программы. Значения, которые может принимать свойство State, описаны ранее (см. описание свойства State в табл. 3.19).
Начальное состояние любого НД — dslnactive. Чтобы открыть НД, используется его метод Open или свойство Active, в которое нужно поместить значение True. После успехпного открытия НД переходит в состояние dsBrowse, а его курсор устанавливается на первую запись.
Чтобы закрыть НД, вызывается метод Close. Замечу, что, если НД закрывается, находясь в режимах dslnsert или dsEdit, изменения, сделанные в текущей записи, не запоминаются. Закрыть НД можно также, поместив значение False в его свойство Active.
Программный доступ к записям
Для просмотра, вставки, редактирования и удаления записей обычно используются соответствующие визуальные компоненты (TDBGrid, TDBEdit» TDBNavigator и т. д.), которые автоматически вызывают нужные методы НД. В некоторых случаях
(например, при обработке статистических данных или при реализации каскад* ных изменений) необходим программный доступ к информации без использования визуальных компонентов.
При программном доступе прежде всего нужно убедиться в томг что НД содержит записи. Для этого вызывается метод isEmpty, который возвращает False, если в НД есть хотя бы одна запись. После использования или редактирования текущей записи переход к следующей реализуется методом FindNext или Next. Таким образом, для программного доступа ко всем записям НД применяются такого рода операторы:
Tablel.Open;
if not Tablel. IsErapty then
repeat
// Используем информацию из текущей записи или редактируем ее until not Tablel.FindNext; // Переходим к следующей записи
Tablel.Close;
Другой вариант:
Tablel.Open;
while not Tablel.EOF do
begin
// Используем информацию из текущей записи или редактируем ее
Tablel .Next; // Переходим к следующей записи
end;
Tablel.Close;
Перед редактированием текущей записи набор данных необходимо перевести в состояние dsEdit методом Edit, а после редактирования сохранить сделанные изменения в соответствующей таблице БД, вызвав метод Post:
Tablel.Edit;
Tablel[* Number *] := 123456;
Tablel.Post;
По такой же схеме осуществляется вставка или добавление новой записи, при этом вместо Edit вызывается метод Insert (вставка записи) или Append (добавление записи). Если НД не индексирован, вставленная запись помещается на место текущей записи, а текущая запись становится следующей за ней; добавленная запись помещается в конец НД. Если НД индексирован, оба метода вставляют запись в позицию, определяемую текущим индексом. Рассмотрим следующие операторы:
Tablel. insert;/ / или Tablel .Append;
{Наполнение пустой записи нужными значениями:}
Tablel[* Number1] := 123456;
Tablel[*Name'] := 1Иванов И.И.';
Tablel[1 Children'] := False;
Tablel.Post; // Запоминание записи в ТБД
Вместо всех этих операторов можно использовать единственный оператор, вызвав метод InsertRecord или AppendRecord:
Tablel.InsertRecord([123456, 'Иванов И,И.', False]);
Элементы в конструкторе массива должны идти в строгом соответствии с порядком следования полей в НД и содержать допустимые для каждого поля выражения. Замечу, что вставленная запись становится текущей. Если НД индексирован, вставлять запись в цикле просмотра repeat ... until или while not EOF do нельзя, так как положение новой записи в НД будет соответствовать значению ее индексного поля и, следовательно, положение курсора НД может измениться. Точно так же в цикле нельзя изменять значения индексных полей.
Редактирование, удаление и вставка записей возможны только для НД, свойство CanModi fy которых содержит значение True. Для компонента ТТаЫе это условие выполняется, если свойство Readonly содержит заданное по умолчанию значение False, для двух других компонентов-наборов — лишь при выполнении определенных условий.
Навигация по набору данных
Под курсором набора данных понимается указатель текущей записи в конкретном НД. Текущая запись — это та запись, над которой в данный момент времени можно выполнять какие-либо операции (удаление» изменение, чтение значений, содержащихся в полях записи).
С помощью методов First, Last, Next, Prior, MoveBy, FindFirst, FindLast. FindNext, FindPrior можно изменять положение курсора и, следовательно, выбирать нужную запись.
Последовательная навигация по записям
Для выполнения действий по последовательному перебору записей, начиная от некоторой стартовой записи и до конца набора данных, используют цикл while...do или repeat...wtil:
with Tablel do
begin
First;
while not EOF do
begin
{Какие-либо действия над очередной записью}
Next;
end; {while} end; {with}
with Tablel do
begin
First;
repeat
{Какие-либо действия над очередной записью} until not FindNext;
end; {with}
Точно так же можно перемещаться от конца НД к его началу:
with Tablel do
begin
Last;
while not BOF do
begin
ГКакие-ли^о действия над очередной записью} Prior;
end; {while) end; fwi th}
with Tabiel do
begin
Last;
repeat
{Какие-либо действия над очередной записью]
until not FindPrior; end; {with}
Если НД допускает вызов записи по ее номеру (его свойство isSequenced в этом случае должно содержать значение True), можно использовать цикл for. Например, следующий обработчик события TForm. OnAct ivatе поместит все значения строкового поля BName НД Books в многострочное текстовое поле Memol:
procedure TForml.FormAc t i va t е(Sende r: TObj ect);
var
RecNo: Integer; begin
if Books.IsSequenced then
for RecNo := 1 to Books.RecordCount do
begin
Books.RecNo := RecNo;
Memol.Lines.Add(Tablel[•BName'])
end; end;
Замечу, что для компонентов TTable и TQuery, связанных с файл-серверными таблицами БД, свойство IsSequenced всегда содержит значение True. В клиент-серверной архитектуре оно зависит от используемого сервера БД. Свойство RecNo набора данных определяет порядковый номер обрабатываемой записи (нумерация начинается с i), а его свойство RecordCount — количество записей. Во всех случаях следует помнить, что, если в ходе выполнения цикла последовательного перебора записей изменится ключевое поле записи или в НД будет вставлена новая (удалена старая) запись, курсор НД может изменить свое положение и правильная работа цикла нарушится. Например, следующий фрагмент программы не обеспечит удаление всех записей из таблицы:
with Tablel do while not EOF do begin
Delete;
Next;
end;
После удаления очередной записи курсор НД перейдет на следующую, но вызов Next заставит его сместиться еще раз, и запись будет пропущена. Правильный вариант:
with Tablet do while not EOF do
Delete;
Использование закладок
Подобно тому, как в книге нужную страницу можно заложить закладкой и впоследствии быстро найти, в НД аналогичные действия можно осуществить для записи. Для этой цели НД обладает следующими методами: GetBookmark (создает закладку), GotoBookmark (перемещает курсор к закладке), FreeBookmark (удаляет закладку), BookmarkValid (проверяет закладку), CompareBookmarks (сравнивает две закладки). Закладки применяют в том случае, когда нужно временно покинуть текущую запись, а затем вновь к ней вернуться.
Использовать закладки предельно просто:
var
МуBookmark: TBookMark;
// Создаем закладку для текущей записи:
MyBookmark :二 Tablel.GetBookmark;
/ / Переходим к записи с закладкой:
if Tabiel.BookmarkValid. (MyBookmark) then
Tablel.GotoBookmark(MyBookmark!;
// Освобождаем выделенные для закладки ресурсы:
if Tablel.BookmarkValid{MyBookmark) then
Tablel.FreeBookmark(MyBookmark};
Поиск записей в наборах данных
В этом разделе рассматриваются методы Locate и Lookup, которые можно использовать при работе с любым компонентом-набором. Компонент ТТаЫе имеет дополнительную группу методов для поиска записей.
Метод Locate
Метод Locate ищет первую запись, удовлетворяющую критерию поиска, и, если такая запись найдена, делает ее текущей. В этом случае в качестве результата возвращается значение True. Если запись не найдена, возвращается значение False, и курсор не меняет своего положения:
function Locate(const KeyFields: String;
const KeyValues: Variant;
Options: TLocateOptions): Boolean;
Список KeyFields указывает поле или несколько полей, по которым ведется поиск. В случае нескольких поисковых полей их названия разделяются точкой
с запятой. Критерии поиска задаются в вариантном массиве KeyValues так, что i-e значение в KeyValues ставится в соответствие i-му нолю в KeyFields. Параметр Options указывает необязательные значения режимов поиска:
loCaselnsensitive — поиск ведется без учета возможной разницы регистра букв в текстовых полях и в критерии поиска;
loPartialKey — запись считается удовлетворяющей условию поиска, если она содержит часть поискового контекста; например, удовлетворяющими контексту «Дна» будут признаны записи со значениями в поле поиска «Диалект», «Диалог-МИФИ^, <ДиаСофт^ и т. д.
Метод Locate производит поиск по любому полю независимо от того, входит оно в состав какого-либо индекса или нет. Если поле (поля) поиска входит в какой-либо индекс, Locate автоматически использует его, что существенно ускоряет поиск.
Для иллюстрации использования метода Locate изменим пример, рассмотренный в главе 1: поместите на нижнюю панель компонент TDat eTime Pi скег (вкладка Win32 палитры компонентов) и напишите следующий обработчик его события OnChange (проект Ch03\Locate\Nakls.dpr):
procedure TfmNakls.DateTimePickerlChange(Sender: TObject);
begin
if Nakls.Locate('NDate',Variant(DateTimePickerl.Date),[]) then DBGridl.SetFocus
end;
Теперь при вводе в компонент нужной даты программа отыщет в наборе Nakls первую накладную с этой датой (рис. 3.7).
瑞
Niikild ? |д«га|ПартнерКипиакладной|Сукка . |опмт« |воз Aj
►
300.15.03.2000
301 Л5.03.2000 302Л5.03.2000 303^15.03.2000 繼麴嬲 16.03.2000
Розничная продажаjПродаже с предоплатой i 3 179‘ООр, 3 1 79,00р,:
И лита^Продажа на реализацию 2 589,60р. 6gр.;
Роэничная продажа^Продажа с предоплатой i 131*04?.131,口4冷:'
РадиоСофт 網^Поставка на реализацию!9 067^50р.0^00р.
Иифра-М;Приход по обмену11952;00р.0,00р.
4
305 4 6.03.2000
ЦСК Ридас; Поставка н« реализацию 528,00р.
耳口о Р. 5Q:
|Н930ание книги /Автор /И^дчм■ ■登、
KGH-Bo|UeHS
目IBM PC для пользователя. Краткий курс/ Фигурнов/ИнфраЧЧ:600 19,%
i| v| »IT + |T"T Л Ьб.оз.гооо二1量如 1
Рис. 3*7. Поиск накладных по дате
Метод Lookup
Метод Lookup находит запись, удовлетворяющую условию поиска, но не делает ее текущей, а возвращает значения некоторых ее полей. Независимо от результата поиска записи указатель текущей записи в НД не изменяется. В отличие от метода Locate, метод Lookup осуществляет поиск только на точное соответствие критерию поиска искомых значений поля записи:
function Lookup(const KeyFields: String;
const KeyValues: Variant;
const ResultFields: String): Variant;
В параметре KeyFields указывается список полей, по которым необходимо осуществить поиск (если задается поиск по нескольким полям, соседние поля в списке разделяются точкой с запятой). Параметр KeyValues определяет искомые значения полей, список которых содержится в параметре KeyFields. В параметре ResultFields перечисляются поля, значения которых требуется получить в случае успешного поиска. Тип результата — Variant или вариантный массив..
Если имеется несколько поисковых полей, каждому i-му полю в списке KeyFields ставится в соответствие i-e значение в списке Keyvalues. Если поиск ведется по одному полю, его поисковое значение можно указывать в качестве параметра KeyValues непосредственно; в случае нескольких полей их необходимо приводеть к типу вариантного массива при помощи функции преобразования VarArrayOf.
Как и в методе Locate, в качестве искомых полей можно указывать ноля как входящие в какой-либо индекс, так и не входящие в него. Если в результате поиска запись не найдена, метод Lookup возвращает Null» что можно проверить с помощью такого приема:
var
LookupResult: Variant;
LookupResult := Tablel.Lookup(...);
if VarType(LookupResult) = varNull then ...
Если поиск оказался успешным, Lookup возвращает из найденной записи значения полей, список которых содержит ResultFields. При этом размерность результата зависит от того, сколько результирующих полей указало в ResultFields.
Пусть, например, в НД Nakls ищется запись, ключевое поле NakllD которой имеет значение, задаваемое текстом в поле seNakllD; в качестве результирующих пусть будут поля NDate, Firm, NSum и NPayedSunu Чтобы получить результат, показанный на рис. 3.8, использовался обработчик щелчка на кнопке Искать, представленный в листинге 33 (проект Ch03\Lookup\Lookup.dpr).
6 Зак. 449
Рис. 3.8. Окно с отображением результата поиска методом Lookup
Листинг 3.3. Обработчики щелчка на кнопке Искать и изменения текста var NakllD: Integer 二 1 ;
procedure TForml.ButtonlClick(Sender: TObject); var LookupResult: Variant;
begin
LookupResult := Nakls.Lookup('NakllD', NakllD, 'NDate;Name;NSum;NPayedSum');
if VarType(LookupResulc)=varNull then ShowMessage('Нет накладной с номером '+ IntToStr(NakllD)}
else If VarType(LookupResult}=varEmpty then
ShowMessagef гЛоиск не проведен *) else if VarlsArray(LookupResult) then begin stDate.Caption :二 LookupResult[0]; stNaine . Caption :二 LookupResult [ 1]; stSum.Caption := FloatToStrF(LookupResult[2] as Double,
ffNumber, 10, 2);
stPayed.Caption :二 FloatToStrF(LookupResult[3] as Double,
ffNumber, 10, 2); edNakllD.SelectAll ;
end else
stDate.Caption : = LookupResiiln
end; var
Txt: String『11';
procedure TForml.edNakllDChange(Sender: TObject);
// Блокирует ввод текста, если нет правильного числа
begin
if Tag = 0 then // Пропускаем проверку после восстановления
try
NakllD := StrToInt(edNakllD.Text);// Пытаемся преобразовать
Txt := edNaklID.Text;// Все в порядке: запоминаем текст
except// Ошибка/
edNaklID.Text := Txt; // Восстанавливаем текст
〃 н устанавливаем курсор на место ошибочного символа edNaklXD.SelStart := Length(Txt);
end;
end;
В примере для ввода номера накладной используется поле edNaklID. Обработчик изменения текста компонента блокирует очередное изменение, если текст не соответствует правильному текстовому представлению целого числа. Если преобразование текста прошло удачно, новый текст запоминается в глобальной переменной Txt, в противном случае содержимое этой переменной используется для восстановления предыдущего текста.
Фильтрация записей
Помимо описываемых далее средств для фильтрации данных могут использоваться методы SetRange, ApplyRange (и сопутствующие им методы) в компоненте TTable и секция WHBRE SQL-запроса в компонентах TQuery и TStoredProc.
Свойство Filter
Свойство Filter задает критерий фильтрации. В этом случае НД окажется отфильтрованным, как только в его свойство Filtered будет помещено значение True. Синтаксис описания критерия похож на синтаксис секции WHERE SQL-запроса с тем исключениемг что имена переменных программы указывать нельзя, а можно указывать имена полей и литералы (явно заданные значения). Допустимы обычные операции отношения и логические операции AND, NOT и OR, например:
(B0pt>100) AND (BQuan=0)
Строку критерия фильтрации можно ввести во время прогона программы или на этапе конструирования формы. Например, с помощью представленного в листинге 3.4 обработчика события OnClick компонента sbFilter (класс TSpeedButton) критерий фильтрации считывается из поля edFilter и помещается в свойство Filter компонента Nakls (проект GiO3\Hlter\Nakls.dpr, рис. 3.9 и 3.10).
Листинг 3.4. Обработчик события OnQick компонента sbFilter
procedure TfmNakls.sbFilterClick{Sender: TObject);
begin
If edFiIter.Text <> '* then
with Nakls do
begin
Filter := edFilter.Text;
try
164 Глава 3 • Технология BDE.NET
Листинг 3.4 (продолжение)
except
Fi1tered :- False;
end;
end;
end;
":^^^«■:^^^^^•s^^^” 丁岁f 修購号b
№кП& {дета
|л^)тиер
|Тмп накладной |Сумма :.: ./оплата
|воэвр&т |Ко1ф-1Ср(ж а
I 01.03.2000
Точка. Социальный универскПродажа на реализа
550,00р.
O,GOp.
L S50,00p「1 30.04 2ГА .
2 01.03,2000
Яновер
Продажа с лредоплё
335,92р.
Э35,92р.
0,00р. i 1,04 31.03.21!
3:01.03,2000
ИКС ООО
Продажа на реализа
45 337,50р.'
0,00р.
0,00р. : 0,75'10.04.21
4-01.03.2000
ДЕСС-Пйблишерз
Приход по обмену :
6 762,00р.
0,00р.
0,00р.l pi.03Z
5 ;01.03.2000
Розничная продажа
;Продажа с предопле
234,00р.
234,00р.
0,00р.. 1,04:02.03.21
6;01.03.2000
Точка. МГИЭМ
Продажа на реали»
2 326,70р.
0>00р
:2 328,70р. : 1Д :3O.CH.2i
7 01.03-2000
ООО Издательство
Нопкд*' Поставка на реалнм
155 610,00р. X) 201,6 5р
>5 408,35р. :1 30.CH.2i
а.егоз.2000
ГХ»одалитЪ
Продажа на реализа
2 767,50р.:
.QOOp
;0,00р,; 07S.3LO32
9:01.03.20Ю
И лита
Продажа на реалта
ess.oop.
0,00р
0,00р. ; 0,75:31.03.21
10 01.03.2000
ООО Издательство
Нолндж' Поставка м реалюЕ
155 610,0叩..
%рор.
0,00р. i 1 !30,СН.21
11 01.03.2000
ТРИУМФ
Продаже на реалиэа
26 460,00р.
О.ООр
0,00р. : 0,75 31.03.21
12 01.03,2000
Калинин
Возврат раз*”
2 356,90р. ■
…о-ООр
0,00р. :1 01.03.2ry;
|Нвэввмие книги /^торТ^Д^" ■ ■ ■
:|Кшьео|цека ]
孑旧 Сомзенаа работа/ Курбатов/Феникс
О ' 55лоор..
~W阂咨M
j::,
且
Рис. 3.9. Набор данных до фильтрации
HaUld . |п&та ■■ |партивр " ■ ■■■"■ |типнжладной |Сунмо ■ |0шмтЬ|Возврат - |Kbai4>-icpqic 5
>
7 01,03.2000 000 Издательство нНолидж':Поставка на реалим155 610,00р. 50 20 b65p. 55 408,35р. j 1 ■30.04.2г-
10 01.03.2000 000 Издательство "Нолидж1.Поставка на реалмзг 155 610;00р.0,00р.0,00р.;1 ;30.CH.2i
32 01.03.2ОСЮ О<ЭО Издательство нНолид*' Поставка на реапиэг И8 200,00р. 52 371(Э9р.0,00р. :1 ;30,04.21
66 02.03.2000 000 И1датеге»ство "Ноли** Поставка на peanut 7 4 841,00р.0(00р>;0,0 0р. :1 01.06.2i
116 06.03.2000 000 Издательство "Нолидж1:Поставка м рылизб 395 200,00р.0t00p,0,00р- : I :0S.0S.2i
126 07.03.2000 000 Издательство'Нолидж'Поставка м реалий 123 500,00р..0.00р. ■0,00р.'1 :06,06,2i
540 70.03,2000 000 Издательство "Нолидж" Поставка на pea/wai 163 800,00р.0(00р.0,00р. ;1 27.0S.2i
56^ 29.03.2000 000 Издатеп>ство ^олидж1 Поставка на реалих 108 108,00р. О,ОСр. 0(00р. :1 28.CS.2i
623 :31.03.2000 000 Издател>ство "Нолндж' Поставка на реалнм 571 675,00р,01100P. :0,00р, :1 30.06.2<
646:03.04.2000 ИКС ОООПродажа на реашса 62 680,00р.0,00р. ■ O^OOpJ 075:13.0S.2i
ч
ЙНазвание kwth /Автс^» /Иэа-вл ■
2520: 61,75р.2520: 61,75р.DetphfS. Учебным курс[ Фаронов/Нопидж
2520: 61,75р.
2520: 61,75р.
С помощью следующего свойства программист может определить дополнительные условия фильтрации текстовых полей:
type TFilterOption = (foCaselnsensitive, foNoPartialCompare); property Filteroptions: TFilterOptions;
Параметры:
f oCaselnsensitive — фильтрация производится без учета регистра букв;
foNoPartialCompare — поиск производится на точное соответствие.
Событие OnFilterRecord
Событие OnFilterRecord возникает при установке значения True в свойство Filtered. Обработчик события имеет два параметра: имя фильтруемого набора данных и переменную Accept, в которую программа должна поместить значение True, если текущая запись удовлетворяет критерию фильтрации.
В отличие от критерия в строке Filter» ограниченного рамками синтаксиса условного выражения, критерий, реализуемый в обработчике события OnFilterRecord, определяется синтаксисом Delplii и позволяет получать сложные алгоритмы фильтрации. Однако следует помнить о том, что в обработчике OnFilterRecord последовательно перебираются все записи таблицы БД, в то время как методы SetRange, ApplyRange и им сопутствующие методы компонента ТТаЫе используют индексно-последовательный метод доступа, то есть работают с частью записей в физической таблице БД. Это делает обработчик OnFilterRecord предпочтительным для фильтрации небольших объемов записей и сильно ограничивает его применение при больших объемах.
Блокировка таблиц в многопользовательском режиме
При работе с таблицами файл-серверных СУБД в многопользовательском режиме может возникнуть ситуация, когда на момент внесения изменений в какую-либо таблицу БД одним пользователем следует блокировать внесение изменений в ту же таблицу другими пользователями. Более жестким ограничением может служить запрет на просмотр содержимого таблицы со стороны других пользователей.
Запрет достигается с помощью метода
procedure LockTable(LockType: TLockType};
Здесь параметр LockType определяет вид запрета: ItReadLock — запретить чтение; ItWriteLock — запретить запись. Можно запретить и чтение и запись данных, но для этого нужно вызвать метод LockTable дважды.
Попытка внесения изменений в НД, ассоциированный с таблицей БД, для которой запрещена запись данных, равно как и попытка чтения из запрещенной для чтения таблицы, приводят к возбуждению исключительной ситуации EDBEngineError со следующим сообщением:
Table имя_таблицы is locked
После того как необходимость запрета отпадет» он должен быть отменен методом
procedure UnlockTable(LockType: TLockType);
Здесь параметр LockType определяет тип снимаемого запрета.
Обзор событий
Все НД получают в свое распоряжение большое количество событий, унаследованных ими от родительского класса TBDEDataSet. Далее рассматриваются наиболее важные из них.
Реализация каскадных изменений и бизнес-правил
Для реализации каскадных изменений и бизнес-правил в файл-серверных БД обычно используются обработчики событий AfterXXXX и BeforeXXXX. Эти две группы событий связаны с изменениями НД (вставка, удаление или редактирование записи) и отличаются тем, что события BeforeXXXX наступают непосредственно перед изменением НД, а события Af terXXXX — сразу после изменения. К ним относятся:
property After/BeforeCancel — возникает после/до отмены изменений в текущей записи;
property After/BeforeClose — возникает после/до закрытия НД;
property Aft er/BeforeDelete — возникает после/до удаления текущей записи;
property After/BeforeEdit — возникает после/до редактирования текущей записи;
property After/Beforelnsert — возникает после/до вставки новой записи;
property Aft er/BeforeOpen — возникает после/до открытия НД;
property After/BeforePost — возникает после/до выполнения метода Post;
property After/BeforeScroll — возникает после/до перехода к новой записи.
Обработчики этих событий в качестве параметра получают ссылку на НД, вызвавший соответствующее событие. Если необходимо прервать работу обработчика и предотвратить изменение ТБД, нужно возбудить исключение или вызвать процедуру Abort.
Другие события
Событие OnCalcFields возникает, когда программа должна сформировать значения для вычисляемых полей. Следует заметить, что это событие возникает в момент открытия НД и при любом его изменении. Если пользователь интенсивно работает с НД, а алгоритм получения вычисляемых значении достаточно сложен, обработчик этого события может снизить производительность системы. Событие OnCalcFields в этом случае следует предварительно отключать, устанавливая значение False в свойство НД AutoCalcFields.
Следующее событие возникает в момент фильтрации записей:
type TFilterRecordEvent: procedure(DataSet: TDataSet;
var Accept: Boolean) of object;
property OnFilterRecord: TFilterRecordEvent;
Обработчик должен поместить в параметр Accept значение True, если запись удовлетворяет условиям фильтрации.
Событие OnNewRecord возникает при вставке новой записи. В его обработчике программа может поместить в запись значения полей, заданные по умолчанию.
Таблицы
Компонент TTable (таблица), которому посвящен этот раздел, является одним из наследников класса TDBDataSet (набор данных)» свойства, методы и события которого рассмотрены в предыдущем разделе.
Обзор свойств и методов
Здесь описываются наиболее важные специфические для класса TTable свойства и методы (его события унаследованы от класса TDBDataSet и здесь не рассматриваются).
Свойства
Свойства компонента TTable представлены в табл. 3.22.
Таблица 3.22. Свойства компонента TTable
Свойство
Описание
property Datasource: TDataSource;
Содержит имя пивного НД в отношении главный—детальный (только для чтения)
property Defaultindex: Boolean;
Если содержит True, НД в момент открытия будет отсортирован по умалчиваемому индексу
property Exclusive: Boolean;
Если содержит True» после открытия таблицы запрещает работу с ней другим приложениям
property Exists: Boolean;
Указывает, существует ли нужная таблица БД
property IndexDef s: TXndexDefs ;
Содержит информацию об индексах таблицы
property IndexFieldCount:
Указывает количество полей, которые образу-
Integer;
ют текущий ключ
property IndexFieIdNames: String;
Содержит список полей» образующих текущий ключ
property IndexName: String;
Содержит имя используемого индекса
продолжение 抄
Свойство
Описание
property Key Exclusive: Boolean;
Если содержит False, граничные точки диапазона при фуьпьтрации по ключам входят в поисковый диапазон, в противном случае — не входят
property MasterFiGlds: String;
Содержит список полей главной таблицы, по которым в данной таблице будет установлена связь главная—детальная
property MasterSource: TDataSource;
Определяет имя главной таблицы в связи главная—детальная
property Readonly: Boolean;
Если содержит True, ТБД используется только для чтения данных
property Tabi eName: TFileName;
Type TTableType = (ttDefault, ttParadox, ttDBase, ttASCII, ttFoxPro);
property TableType: TTableType;
Содержит имя таблицы
Определяет тип таблицы: ttDefault — тип определяется расширением табличного файла; ttParadox — таблица Paradox; ttDBase — таблица dBASE; ttASCii — текстовая таблица; ttFoxPro — таблица FoxPro
Методы
Методы компонента ТТаЫе перечислены в табл. 3.23.
Таблица 3.23. Методы компонента ТТаЫе
Метод
Описание
type TIndexOption = (ixPritnary, ixUnique, ixDescending, ixCaselnsensitive, ixExpression, ixNonMa int a ined);
TlndexOptions = set of TTndexQption;
Создает новый индекс: Name — имя индекса; Fields — список индексных полей; Options — параметры индекса (см. далее)
procedure Addindex (const Name, Fields: String; Options: TlndexOptions);
procedure ApplyRange;
Включает механизм фильтрации записей по ключевым полям
type TBatchMode = (batAppend, batupdate, batAppendUpdate, batDelete, batCopy);
function BatchMove (ASource:
Копирует записи из НД ASource в текущую таблицу и возвращает количество скопированных записей. Параметр AMode определяет режим копирования (см. далее)
TBDEDataSet; AMpde:
TBatchMode): Integer;
Таблицы 169
Метод
Описание
procedure CancelRange;
Отменяет фильтрацию записей по ключевым полям
procedure CloselndexFile (const
IndexFile: String);
Закрывает идексный файл 工ndexFile
procedure CreateTable;
Создает новую таблицу по информации, хранящейся в свойствах FieldDef sT Fields и IndexDefs
procedure Deletelndex (const
Name: String);
Удаляет индекс с именем Name
procedure DeleteTable;
Удаляет таблицу
procedure EditKey;
Переводит таблицу в режим dsSetKey н позволяет модифицировать ключи поиска
procedure EditRangeEnd;
Позволяет изменить конечное значение диапазона фильтрации по индексным полям
procedure EditRangeStart;
Позволяет изменить начальное значение диапазона фильтрации по индексным полям
procedure EmptyTable;
Удаляет все записи из таблицы
function FindKey (conet KeyValues:
array of const) : Boolean;
Отыскивает запись по указанным значениям Key Values ключевых полей и возвращает True в случае успеха
procedure FindNearest (const
Keyvalues: array of conet);
Перемещает курсор на запись, наиболее полно удовлетворяющую указанным значениям KeyValues ключевых полей
procedure GetDatailLinkFields (MaterFields, DetailFields: TObjectList);
Создает два списка ключевых полей: для главной таблицы MasterFields и для детальной —DetailFields
procedure GetlndexNames (List: TStrings);
Наполняет список List именами ключевых полей
procedure GetProviderAttributes (List: TObjectllst);
Получает из BDE и помещает в список List языковой драйвер, маршрут доступа и имя таблицы
procedure GotoCurrent {Table: TTable);
Устанавливает курсор текущего НД в положение курсора НД Table, основанного на той же физической таблице
function GotoKey: Boolean;
Пытается отыскать запись, ключевые поля которой соответствуют значениям, связанным с предыдущими вызовами методов StartKey или Ed it Key. Перемещает курсор на найденную запись и возвращает True в случае успеха
procedure GotoNearest;
Перемещает курсор на запись, наиболее полно удовлетворяющую значениям ключей, ус- таиовленлых методамм SetKey или Ed it Key
продолжение 於
Таблица 3.23 (продолжение)
Метод
Описание
type TLockType = (ItReadLock, ItWriteLock);
procedure LockTable (LockType: TLockType);
Блокирует таблицу, ограничивая доступ к ней другим пользователям: ItReadLock — блокировать запись и чтение; ItWriteLock —— блокировать только запись
procedure OpenlndexFile
(IndexFile: String);
Открывает индексный файл IndexFile
procedure RenameTable (const NewName: String);
Переименовывает таблицу
procedure SetKey;
Переводит таблицу в режим dsSetKey и очищает буфер ключей. С помощью метода Field- ByName (см. табл. 3.15) программа должна установить новый набор ключей и с помощью метода ApplayRange отфильтровать НД
procedure SetRange (const
Startvalues, Endvalues: array of const);
Переводит таблицу в режим dsSetKey, устанавливает новый набор начальных (Start- Values) и конечных (Endvalues) значений буфера ключей и фильтрует НД по индексным ключам
procedure SetBangeEnd;
Переводит НД в режим dsSetKey и очищает буфер конечных значений ключей
procedure SetRangeStart;
Переводит НД в режим dsSetKey и очищает буфер начальных значений ключей
procedure UnlockTable (LockType: TLockType);
Отменяет блокировку таблицы (см. описание метода LockTable)
Аргумент Options метода Addindex определяет параметры индекса, в том числе:
ixPrimary — первичный индекс;
ixUnique — уникальный индекс;
ixDescending — индекс, сортирующий по убыванию значений;
ixCaselnsensitive — индекс, чувствительный к регистру букв в текстовых полях;
ixExpression — индекс, определенный по индексному выражению;
ixNonMaintained — индекс не обновляется автоматически в момент открытия таблицы.
Параметр AMode метода BatchMove определяет режим копирования:
batAppend — добавить все записи в конец таблицы;
batUpdate — обновить записи с одинаковыми ключевыми полями;
ba tAppendUpda tе — обновить записи с одинаковыми ключевыми полями и добавить остальные записи в конец таблицы;
batDelete — удалить записи с одинаковыми ключевыми полями;
batCopy — удалить все записи текущей таблицы и заменить их записями копируемой таблицы.
Индексы
Смена текущего индекса
Возможность менять текущий индекс и таким способом влиять на сортировку табличных данных является отличительной особенностью компонента TTable. В двух других компонентах-наборах программист не может явно указать индекс, а сортировка данных осуществляется в секции ORDER BY SQL-запроса.
Для смены текущего индекса предназначены свойства IndexName и IndexFieldNames. В первое нужно поместить имя индекса, во второе — список индексных полей, входящий в состав индекса. Эти свойства взаимоисключающие: установка значения в одно из них очищает другое. Если НД открыт, смена текущего индекса приводит к немедленному изменению порядка следования записей в таблице.
Добавление нового индекса
Добавление нового индекса происходит в режиме эксклюзивного доступа к таблице БД (свойство Exclusive = True) и осуществляется следующим методом:
procedure Addindex(const Name, Fields: string;
Options: TIndexOptions)
Здесь параметр Name определяет имя индекса, а параметр Fields — список индексных полей. В случае нескольких полей соседние имена в списке разделяет точка с запятой. Должны указываться только поля, объявленные в структуре таблицы ЕД, в противном случае будет возбуждена исключительная ситуация. Параметр Options является множеством, которое содержит значения, определяющие свойства индекса:
ixCaselnsensitive — индекс чувствителен к регистру букв;
ixDescending — индексные поля сортируются по убыванию значений;
ixPrirnary — создается первичный ключ;
ixUnique — значения полей в индексе должны однозначно определять запись.
Удаление индекса
Удаление существующего индекса происходит в режиме эксклюзивного доступа к таблице БД и осуществляется следующим методом:
procedure Deletelndex(const Name: String}
Здесь параметр Name определяет имя удаляемого индекса. При попытке удаления несуществующего индекса возбуждается исключительная ситуация.
Составные индексы
Составными называются индексы, построенные по значениям двух и более полей. Такие индексы широко используются на практике для ускорения поиска нужной записи или группы записей методами FindKey и FindNearest (см. далее). Если в таблице построен индекс только по полю Fieldl, а требуется отыскать записи, содержащие нужные значения в полях Fieldl н Field2, то методы FindKey и FindNearest могут установить курсор лишь в начало цело!! группы записей, поля Fieldl в которых имеют нужные значения, но различаются значениями остальных полей. В этом случае для поиска записей с нужными значениями поля Field2 придется последовательно просматривать таблицу, начиная с найденной записи. Если построен составной индекс по полям Fieldl и Field2, методы FindKey и FindNearest сразу позиционируют курсор на нужную запись и для таблиц большого размера могут существенно сократить время поиска. Например, в моей практике был случай, когда в таблице, насчитывающей более 800 000 записей, нужно было отыскать группу записей с заданными значениями трех полей. И хотя по каждому полю в отдельности был построен индекс, поиск проходил с заметными задержками (5-6 с), которые вызывали у пользователей вполне оправданное раздражение. После построения составного индекса время поиска сократилось до долей секунды, н пользователи просто перестали замечать задержки.
Для создания составного индекса в серверных таблицах и таблицах типа Paradox с помощью утилиты SQL Explorer используется SQL-запрос типа
CREATE INDEX IndexName ON TableName(Fieldl, Field2,...)
В широко распространенных таблицах типа dBASE нельзя создать составной индекс и. следовательно, реализовать быстрый индексный поиск при участии нескольких полей. В базирующихся на них средствах разработки (dBASE Ш+, dBASE IV, FoxPro, Clipper) для этих целей обычно используется индекс, построенный по индексному выражению, с приведением нужных полей к строковому типу. Например:
STR(FINCODE,SJ+LEFTtFINTYPE,1)+DTOS(FINDATE)
Это индексное выражение формирует строку из 5 символов преобразования целого значения поля FINCODE. первого символа значения строкового поля F工NTYPE it преобразованного к строке значения даты из поля FINDATE.
Увы! Delphi не имеет средств пшгека по индексным выражениям. Таким образом, использование таблиц dBASE в приложениях Delphi менее удобно, чем таблиц Paradox: если вы собираетесь разработать приложение для пока еще не созданной БД и выбрали традиционную архитектуру файл-серверных таблиц, обратите на это внимание; если вы создаете приложение для уже существующей и наполненной БД, в которой используются таблицы dBASE, имеет смысл подумать □ передаче содержащихся в них данных в таблицы Paradox с помощью компонентов TBatchMove.
Эксклюзивный доступ к таблице
Свойство Exclusive дает программе эксклюзивный доступ к таблице — в этом случае в свойство нужно поместить значение True. Это означает, что никто, кроме вашей программы, не только не сможет вносить изменения в таблицу БД, но вообще не получит к ней доступа. Установить эксклюзивный доступ можно лишь тогда, когда ни один пользователь не имеет доступа к таблице БД и та не открыта.
ПРИМЕЧАНИЕ
Среда Delphi тоже считается пользователем, если на этапе конструирования формы компонент ТТаЫе активизирован (его свойство Active содержит True). Поэтому, если в программном коде делается попытка получения прав эксклюзивного доступа к таблице БД, а программа запущена из среды Delphi, эта попытка будет блокирована, поскольку на вашей машине имеется два пользователя, осуществляющих доступ к этой таблице БД: выполняющееся приложение и среда Delphi. Если ваша программа должна обращаться к методам, требующим эксклюзивных прав доступа, нужно закрыть таблицу на этапе конструирования и открывать ее программно, например, в обработчике события OnCreate главной формы.
Удаление записей и таблиц
Метод EmptyTable удаляет все записи в таблице ВД, связанной с данным НД. После этой операции таблица БД будет пустой. Метод применим только к закрытым НД и только в режиме эксклюзивного доступа (см. ранее). В противном случае возбуждается исключение и очистка таблицы БД блокируется.
С помощью процедуры DeleteTable таблица удаляется физически. Метод применим только к закрытым НД, но для его выполнения не нужно блокировать доступ к таблице с помощью свойства Exclusive.
Поиск записей в таблице
Характерной особенностью компонента ТТаЫе является реализованная в нем возможность работы с индексами. Эта особенность проявляется также н в поиске записей, где помимо «безындексных» методов Locate и Lookup, которые компонент ТТаЫе унаследовал от TDBDataSet, таблица имеет два собственных метода, использующих текущий индекс.
Точный поиск
Для точного поиска (поиска на точное соответствие) применяется метод FindKey. Он пытается отыскать в НД запись, у которой индексные поля соответствуют значениям, указанным в параметре обращения. Если такая запись найдена, метод FindKey возвращает True, и указатель текущей записи в НД (курсор НД) устанавливается на эту запись, то есть она делается текущей. Если найдена группа записей, отвечающих условию, текущей становится лошчески первая из них. Если запись не найдена, курсор НД не перемещается и метод возвращает False.
Неточный поиск
Неточный поиск (поиск на неточное, то есть приблизительное, соответствие) осуществляется методом FindNearest. Он пытается отыскать в НД запись, у которой индексные поля соответствуют указанным значениям. Если такая запись найдена, указатель текущей записи в НД перемещается на нее или на следующую за ней запись в зависимости от значения свойства Key Exclusive. Если KeyExclusive = False (по умолчанию), указатель текущей записи перемещается на нее. Если KeyExclusive = True, указатель текущей записи перемещается на следующую запись.
Если запись не найдена, указатель текущей записи перемещается на ближайшую запись с большим значением индекса.
Выборка записей
В большинстве практически важных случаев НД должен содержать не все записи таблицы БД, а лишь некоторую их часть, соответствующую условиям отбора. Как и в случае поиска записей, компонент ттаЫе помимо описанных в предыдущем разделе свойств Filter, Filtered и события OnFilterRecord имеет собственные методы отбора, основанные на использовании текущего индекса.
Следующий метод показывает в НД только те записи, индексные поля которых лежат в диапазоне от Startvalues до Endvalues:
procedure SetRange(const Startvalues, Endvalues: array of const)
Например, представленный ниже обработчик покажет все накладные за один день (если вы захотите использовать такой обработчик, предварительно установите в свойство Nakls .KeyFieldNames имя индексного поля NDate):
procedure TfmNakls.DateTimePickerlChange(Sender: TObject); begin
Nakls.SetRange([DateTimePickerl.Date], [DateTimePickerl.Date]); end;
Вместо единственного метода SetRange можно использовать целых три: SetRangeStart — для установки начальной границы диапазона фильтрации; SetRangeEnd — для установки конечной границы и ApplyRange — для осуществления фильтрации:
procedure TForml. DateTimePickerlChange(Sender: TObject};
begin
with Nakls do
begin
SetRangeStart;
NaklsNDate.Value := DateTimePickerl.Date;
SetRangeEnd;
NaklsNDate.Value := DateTimePickerl.Date; ApplyRange; end; {with} end;
В этом варианте вы можете обратиться к свойству Key Exclusive, чтобы указать, надо ли включать то или иное граничное значение в выборку (False — включать). По умолчанию для этого свойства используется значение False, поэтому два предыдущих варианта формировали идентичные выборки. Однако в следующем варианте таблица Nakls всегда будет пустой:
procedure TPorml. DateTimePickerlChange(Sender: TObject); begin
with Nakls do
begin
SetRangeStart;
KeyExclusive := True;
NaklsNDate.Value := DateTimePicker1,Date;
SetRangeEnd;
KeyExclusive := True;
Nak1sNDate.Value := DateTimePickerl.Date; ApplyRange;
end; // with DM,Nakls end;
Запросы
Характерной особенностью компонента TQuery (запрос) является использование в нем специального языка для работы с реляционными БД — SQL (Structured Query Languague — язык структурированных запросов)1. С помощью этого языка программист составляет SQL-запрос, который помещается в специально для этого предназначенное свойство TQuery. SQL. После вызова метода Open или ExecSQL компонента TQuery запрос передается машине баз данных (BDE). Последняя имеет встроенный интерпретатор SQL, позволяющий ей выло力н5nb описанные в запросе действия. Если источником данных является серверная БД, BDE пере* дает запрос серверу, в противном случае выполняет его сама. Таким образом, преимуществом технологии BDE.NET является возможность обращаться с запросами к данным, размещенным в фаил-серверной БД.
Если запрос требует получения из БД нужных сведений (запрос SELECT), сформированные с помощью BDE данные помещаются в локальную таблицу в виде временного файла в каталоге запуска программы и TQuery становится владельцем этой таблицы. Данные из временной таблицы через компонент-посредник TDataSource передаются визуальным компонентам и отображаются в них точно так же, как если бы они были получены компонентом ТТаЫе. Однако, в отличие от ТТаЫе, пользователь не может их изменять, так как они представляют собой лишь копию реальных данных. Для изменения хранящейся в БД информации формируются специальные запросы (INSERT, UPDATE, DELETE). В этом случае
Основные сведения о языке SQL приведены в приложении Б.
BDE не формирует новые н никак не использует ранее созданные временные таблицы, но лишь интерпретирует запрос и уведомляет программу о том, насколько успешно прошло его выполнение. Таким образом, необходимость программного изменения запроса в случае модификации НД является другим характерным отличием компонентов TQuery от ТТаЫе.
Следует оговориться, что при некоторых ограничениях на SQL-запрос компонент TQuery может создать «живой» НД и вносимые в него изменения BDE будет немедленно переносить в таблицу БД точно так же, как это делает компонент TTable.
Подведя итог, нужно сказать, что при работе с локальными или файл-серверными БД скорость доступа к данным у TQuery в общем случае меньше, чем у ТТаЫе, так как для своей работы TQuery создает временные таблицы (в файл-серверных БД TTable этого не делает). С другой стороны, широкие возможности SQL позволяют с помощью компонентов TQuery получать НД, которые невозможно получить с помощью ТТаЫе (например, объединение в одном НД данных из нескольких таблиц БД). При работе с серверными БД компонент TTable теряет всякие преимущества, так как в этом случае он также создает временную таблицу, являющуюся локальной копией всей серверной таблицы БД, а уже затем формирует из нее нужный НД. Затраты времени на создание больших локальных таблиц и значительно более скромные возможности компонента ТТаЫе в отношении получения сложных НД практически исключают его использование в клиент-серверных приложениях.
Компонент TQuery порожден от родительского класса TDBDataSet н наследует от него основные методы, события и свойства. Он имеет также собственные свойства, методы и события, наиболее важные из которых рассматриваются в этом разделе.
Обзор свойств
Свойства компонента TQuery представлены в табл. 3.24.
Таблица 3#24. Свойства компонента TQuery
СвойствоОписание
property Constrained: Boolean; Если содержит True, в изменяемом («живом»)
НД на записи, вводимые илн измс1шсмые пользователем, накладываются ограгппспия секции WHERE оператора SELECT
property Datasource: TDataSource; Содержит ссылку на компонент TDataSource, используемый для формирования параметрического запроса
property Local: Boolean;Содержит True, если TQuery работает с ло
кальной или файл-сервсрпой БД
Запросы 177
Свойство
Описание
property ParamCheck: Boolean;
Если содержит True, список параметров бу* дет автоматически обновляться при изменении запроса на этапе прогона программы
property Params [Index: Word]:
Содержит массив объектов-параметров клас-
TParams;
са TParams (см. далее)
property Prepared: Boolean;
Содержит True» если запрос был подготовлен к выполнению методом Prepare
property RequestLive: Boolean;
Содержит True, если TQuery будет возвращать изменяемый (<живой>) НД
property RowsAf fected; Integer;
Содержит количество записей, которые были изменены или удалены в результате выполнения запроса
property SQL: TStrings;
Содержит текст SQL-запроса
property Text: PChar;
Содержит текст SQL-запроса, который был в действител ьности передан BDE
property UniDirectional: Boolean;
Если содержит True, курсор НД может перемещаться только вперед. Такие НД требуют меньше памяти и быстрее обрабатываются (см. примечание далее)
ПРИМЕЧАНИЕ
Свойство UniDirectional используется в клиент-серверных базах данных для серверов, которые не поддерживают двунаправленные курсоры. В этом случае значение False, заданное по умолчанию, требует от Delphi имитировать двунаправленный курсор за счет создания на машине клиента буфера записей. Если НД предполагается просматривать только в одном направлении — от первой записи к последней^ — в свойство следует поместить значение True. Для файл-серверных БД это свойство игнорируется, так как BDE всегда поддерживает двунаправленные курсоры.
Свойство Params содержит набор ссылок на объекты класса TParams. Наиболее важные свойства и методы этого класса перечислены в табл. 3.25 и 3.26.
Таблица 3.25. Свойства класса TParams
Свойство
Описание
property Items [ Index: Word]: TParam;
Содержит массив объектов-параметров класса TParam (см. табл. 327). Эго свойство лля класса TParams является умалчиваемым. Значение параметра Index должно лежать в диапазоне от 0 до Count-1
property ParamValues [const
ParamName: String]: Variant;
Открывает доступ к значению параметра по его имени ParamName
property Count: Integer;
Содержит количество параметров в массиве
Items
Таблица 3.26. Методы класса TParams
Метод
Описание
procedure AddParam (Value: TParam);
Добавляет объект-параметр к массиву Items
type TParamType = (ptUnknown,
Создает объект-параметр и добавляет его к мае-
ptinput, ptOutput, ptlnputOutput,
сиву Items. Тип параметра ParamType: ptUn-
ptResult);
known — не определен; перед передачей в со-
function CreateParam (FldType:
TFieldType; const ParainName:
храняемую процедуру этот тип должен быть заменен другим; ptinput — предназначен для передачи значения в запрос; ptOutput — пред-
String; ParamType: TParamType):
назначен для получения значения из запроса;
TParam;
ptResult — определяет результат запроса; в Items может быть только один параметр
этого типа
function FindParam(const Value: String}: TParam;
Ищет объект-параметр по его имени Value
procedure RemoveParam (Value:
Удаляет объект-параметр value из списка
TParam);
Items
В табл. 3.27 перечислены наиболее важные свойства класса ТРагаш (см. описание свойства Items в табл. 3.25).
Таблица 3.27. Свойства класса TParam
Свойство
Описание
property AsXXXX: ХХХХ;
Эти свойства (AeString, Aslnteger и т. д.) служат для преобразования значения параметра к нужному типу
property IsNull: Boolean;
Содержит True, если с параметром не связано значение
property Name: String;
Содержит имя параметра
property Value: Variant ;
Содержит значение параметра
Обзор методов
Наиболее важные методы компонента TQuery представлены в табл. 3.28.
Таблица 3.28. Методы компонента TQuery
Метод
Описание
procedure ExecSQL;
Выполняет запросы INSERT, UPDATE, DELETE и CREATE TABLE. Для выполнения запроса SELECT вместо метода ExecSQL используется метод Open или свойство Active
procedure GetDetailLinkFields (MasterFields, DetailFields:
TList); override;
Заполняет список MasterFields полями главной таблицы и список DetailFields полями детальной таблицы
Запросы 179
Метод
Описание
function ParamByName (const
Value: String): TParam;
procedure Prepare;
Открывает доступ к параметру по его имени
Value
Передаст BDE запрос для того, чтобы сама библиотека BDE и удаленный сервер БД распределили свои ресурсы и дополнительно оптимизировали запрос
procedure UnPrepare;
Отменяет последствия вызова метода Prepare
Свойство SQL
Следующее свойство является коллекцией строк, в которую на этапе разработки или прогона программы помещается текст запроса:
property SQL: TStrings
Если текст размещен на этапе конструирования, для такого НД можно создать объекты-поля. При любом изменении свойства компонент автоматически переходит в неактивное состояние (его свойство Active получает значение False). После изменения текста компонент следует открыть заново.
Для введения текста запроса на этапе разработки нужно раскрыть и использовать связанный с этим свойством многострочный текстовый редактор (рис. 3.11).
Рис. 3.11. Окно редактора свойства SQL с текстом запроса
Методы Open и ExecSQL
В отличие от таблицы ТТаЫе, компонент TQuery имеет два метода для выполнения запроса. Метод Open используется в запросах SELECT, возвращающих НД. Все остальные запросы (CREATE, DROP, INSERT и т. п.) не возвращают данные, поэтому для их исполнения необходимо обращаться к методу ExecSQL,
Параметрические запросы
Важной особенностью компонента TQuery является возможность создания и использования так называемых параметрических запросов. В такого рода запросах группа параметров позволяет уточнить запрос. Параметры меняются в процессе прогона программы и в общем случае порождают одинаковые по структуре, но разные по содержанию НД.
Пусть, например, нужно создать запрос, который на этапе прогона возвращал бы НД со списком партнеров, поставивших книги в определенный день. В этом случае вместо статического (не меняющегося) запроса следует использовать такой параметрический запрос:
/* Этот запрос формирует список всех партнеров, поставивших книги в день, определяемый параметром DATE */ SELECT NakllD, FName, NSuw FROM Nakls( Firms
WHERE
FirmTD 二 NFirm AND NDate=:DATE AND NType IN (0, 6)
ORDER BY FName
Начальное значение параметра DATE определяется на этапе разработки программы с помощью редактора свойства Params (рис. 3.12, слева) и инспектора объек* тов (рис. 3.12, справа).
Queryl^aramsfD]讣出林彳习Queryl^aramsfD]讣出林彳习DataType iftUnknown» %,,.•;*NumericSca^OParamType : pt UnknownPrecision :0Size!.OEl Value;DataType iftUnknown» %,,.•;*NumericSca^OParamType : pt UnknownPrecision :0Size!.OEl Value;33
Queryl^aramsfD]讣出林彳习
Queryl^aramsfD]讣出林彳习
DataType iftUnknown
» %,,.•;*
NumericSca^O
ParamType : pt Unknown
Precision :0
Size!.O
El Value;
DataType iftUnknown
» %,,.•;*
NumericSca^O
ParamType : pt Unknown
Precision :0
Size!.O
El Value;
3
3
Рис 3.12. Определение начального значения параметра
В тексте запроса имени параметра предшествует двоеточие. Имена параметров могут быть произвольными идентификаторами Delphi. Регистр букв в них не важен. Для задания начального значения параметра обычно в окне инспектора объектов достаточно определить его свойство Value — Delphi автоматически укажет его тип данных в свойстве DataType. Если тип оказывается неверным (например, вместо Integer выбран Smalllnt), следует раскрыть список этого свойства и выбрать тип данных явно. Не следует менять имя параметра в свойстве Name, так как в этом случае Delphi не корректирует текст запроса и в нем будет фигурировать прежнее имя.
Для программного задания значения параметра используется показанное ниже свойство компонента TQuery:
property Params[Index: Word]: TParams;
Можно также использовать следующий метод компонента TQuery:
function ParamByName(const Value: String): TParam;
В первом случае конкретаый параметр (в параметрическом запросе может быть сколько угодно параметров) задается индексом Index, причем первый по тексту запроса параметр имеет индекс 0, второй — 1 и т. д. Во втором случае параметр определяется своим именем в тексте запроса (но не именем в свойстве Name инспектора объектов!). В любом случае при обращении к параметру его значение нужно явно приводить к типу данных параметра свойством AsXXXX:
quNakls.Params[0].AsDate := DateTimePickerl.Date;
quNakls.ParamByName(* Date *) .AsDate := DateTimePickerl.Date;
Если к моменту программного изменения параметра запрос был открыт, его нужно закрыть, установить параметр(ы) и открыть вновь.
Значение Null свидетельствует о том, что полю не присвоено никакого значения («пустое» поле). Значение 0 для числовых полей или пустая строка для текстовых полей 一 это вполне определенные, отличные от Null значения. Чтобы присвоить параметру значение Null при прогоне программы, следует вьшолнить его метод Clear (на этапе разработки нужно очистить свойство Value параметра в окне инспектора объектов).
Для передачи параметров может служить свойство DataSource компонента TQuary. Если это свойство определено, явные присваивания значений параметрам не производятся, то есть не используются операторы присваивания типа
Queryl.ParamByName('ИмяПараметра').value := Значение;
В этом случае в наборе данных, связанном со свойством DataSource, отыскиваются поля, имена которых совпадают с именами параметров запроса. Если такие поля есть, их текущие значения берутся в качестве значений параметров, в противном случае возбуждается исключительная ситуация. Замечу, что только таким способом можно реализовать связь главный—детальный, если детальный НД создан с помощью компонента TQuery.
Методы Prepare и UnPrepare
Синтаксис S QL-операторов проверяется только при их выполнении методом Open или ExecSQL. Проверка синтаксиса требует некоторого времени, которое можно сэкономить, заранее подготовив запрос к многократному использованию методом Prepare компонента TQuery. После этого свойство Prepared компонента TQuery получит значение True, и при очередном выполнении запроса его синтаксис уже не будет проверяться.
При выполнении запрос компилируется и запоминается в буфере машины BDE, которая предварительно его оптимизирует, чтобы вьшолнить запрос в кратчайшее
время. Для освобождения выделенных запросу ресурсов используется метод UnPrepare. При выполнении неподготовленного запроса всегда сначала вызывается Prepare, а после выполнения — UnPrepare.
Изменяемые запросы
Записи НД, возвращаемые компонентом TQuery, могут изменяться подобно тому, как это происходит в компоненте ТТаЫе. Возможность изменения НД, возвращаемого после выполнения оператора SELECT, определяется свойством CanModify, значение которого устанавливается автоматически в зависимости от выполнения следующих условий:
свойство RequestLive компонента должно содержать значение True;
НД формируется обращением только к одной физической таблице БД;
НД не сортируется (то есть в запросе не должно быть секции ORDER BY);
в НД не создаются значения с помощью агрегатных функций;
НД не кэшируется (свойство CashedUpdat.es должно содержать значение False);
при обращении к серверу Sybase SQL Server таблица БД должна иметь уникальный индекс.
Свойство RequestLive компонента TQuery игнорируется, если нарушено хотя бы одно из перечисленных условий. Такие НД могут лишь отображать данные, а попытка вызвать любой из их методов — Insert, Edit или Delete — породит исключительную ситуацию. Для редактирования, вставки или удаления записей в этом случае нужно использовать либо специальные компоненты TUpdateSQL, либо соответствующие запросы Update, Insert, Delete, передаваемые SQL-серверу или BDE с помощью метода TQuery. ExecSQL. В том и другом случаях имеется одна существенная проблема, связанная с соответствующим обновлением данных на экране пользователя. Дело в том, что в обоих этих случаях обновление записей реализуется независимо от их отображения. Сетка DBGrid, например, будет содержать данные из НД, который лишь отображает их из нескольких таблиц и ничего《не подозревает» о возможном изменении одной или нескольких из них. Чтобы обновить демонстрируемые записи, в локальных БД часто используется метод Refresh компонентов ТТаЫе и TQuery, однако применение этого метода в серверных БД запрещено: если пользователь пожелает обновить демонстрируемые на экране данные, он должен будет закрыть НД и затем заново его открыть. При отображении сложного запроса, содержащего тысячи записей, это может привести к существенным задержкам, а если изменять данные требуется часто (например, при вводе нескольких записей подряд), обновление вообще становится невозможным.
Разумеется, в этом случае можно не обновлять отображаемые записи, а лишь тем или иным способом известить пользователя о том, что демонстрируемый ему экран нуждается в обновлении. Наиболее часто для этих целей используется дополнительная кнопка, первоначально скрытая от пользователя н появляющаяся только после внесения изменений. Для привлечения внимания пользователя
к новому интерфейсному объекту кнопку можно сделать «мигающей^ и подать соответствующий звуковой сигнал. В некоторых случаях на экран выводится всплывающее окно, частично перекрывающее демонстрируемые данные. В следующем фрагменте после обращения к методу ExecSQL компонента quUpdate класса TQuery в центре экрана появляется всплывающее окно класса TAlarm, содержащее сообщение о необходимости актуализировать данные, и одновременно становится видимой кнопка bbRefresh, с помощью которой это можно сделать:
procedure TForml.bbUpdateClick(Sender: TObject); begin
try
quUpda t e. Exec SQL ;/ / Изменяем данные
Application-CreateForrntTAlarm, Alarm); with Alarm do begin// Выводим всплывающее окно
Show; SetWindowPos(Handle, hwnd^TopMost,
(Screen.Width-Width) div 2, (Screen.Height-Height) div 2, Width, Height, swp_NoActivate); end; bbRefresh.Show;// Показываем кнопку обновления
MessageBeep (mb_IconExcleniation) ; // Издаем звуковой сигнал except ShowMessage{* Ошибка изменения данных!') end end;
Однако все это ничуть не уменьшает затраты времени, связанные с закрытием и повторным открытием сложного НД. Обновление «живых> НД реализуется значительно быстрее, но в этом случае работу по созданию сложного НД приходится выполнять на клиентском месте, что обычно медленнее и приводит к заметным задержкам при <листании> данных.
Пусть, например, осуществляется выборка сразу из трех таблиц: главной таблицы NAKLS, содержащей документацию об отгрузке книг покупателям (накладные), и двух таблиц подстановки, FIRMS и TYPENAKL, содержащих информацию о покупателях и типах накладных. Таблицы связаны по парам полей: NAKLS. NFirm — FIRMS .FirmlD и NAKLS.NType — TYPES .TypeID. Показанный ниже SQL-запрос создаст необновляемый НД, который, однако, будет достаточно быстро листаться в сетке DBGrid, так как необходимое соединение полей реализуется сервером (или BDE):
SELECT
.../* Перечень полей, выбираемых из таблицы NAKLS */,
FName /* Поле с именем партнера */, TName /* Поле с наименованием типа накладной */
FROM
Nakls, Firms, TypeNakl
WHERE
FirmID = NFirm AND TypelD = NType
Вместо этого можно создать обновляемый НД:
SELECT
.../* Перечень полей^ выбираемых из таблицы NAKLS */
FROM
Nakls
К обновляемому НД нужно добавить объекты-поля типа fkLookup со ссылкой на два вспомогательных НД с данными из таблиц Firms и TypeNakl. Для конечного пользователя результат будет одинаков, но второй НД можно обновлять методами EDIT...POST, в то время как для первого придется использовать SQL-запрос UPDATE (INSERT, DELETE) С последующими вызовами МСТОДОВ CLOSE И OPEN. Поскольку для второго НД соединение полей реализуется клиентом, он будет листаться с заметными паузами. В моей практике, например, одна из главных таблиц имела размер несколько сотен тысяч записей, в то время как таблицы подстановки состояли из нескольких тысяч записей. В первом случае (при объединении полей сервером) листание полного экрана (компонент TDEGrid) проходило в доли секунды и было практически незаметным, в то время как во втором — с паузами в 3-4 с. Однако обновление записи главной таблицы в первом случае реализовывалось более чем за минуту, в то время как во втором — за 1-2 с, то есть в 30-60 раз быстрее. Таким образом, при реализации сложных запросов следует искать компромисс между скоростью навигации и временем обновления: для каких-то групп пользователей может быть важным одно, а для других — другое. Оператор SELECT обычно фильтрует записи в соответствии с условиями, описанными в секции where. В «живом» запросе пользователь может ввести или из- меншъ записи так, что они перестанут удовлетворять условиям секции WHERE. Как должен вести себя в этом случае НД, определяется значением свойства Constrained: если оно содержит значение True, введенная или модифицированная запись фильтруется и исчезает из НД (но сохраняется в реальной таблице БД), в противном случае присутствует в НД наряду с «правильными^ записями. Так сказано в документации и встроенной справочной службе Delphi. На практике (в этом нетрудно убедиться, поставив несложный эксперимент) свойство Constrained никак не влияет на поведение НД.
Сортировка в обратном порядке
Сортировка в обратном порядке легко реализуется в компоненте TTable, если с таблицей связан нисходящий (DESCENDING) индекс. Однако при работе с компонентом TQuery явно использовать тот или иной индекс нельзя — выбор индекса реализуется сервером БД. В части ORDER BY предложения SELECT также нельзя указать порядок сортировки или какое-либо выражение вместо списка полей, поэтому в общем случае нисходящая сортировка в SQL-запросе невозможна. Однако при сортировке по числовым полям и работе с файл-серверными БД этого можно добиться, введя вычисляемое поле, содержащее «обратные» значения,
и выполнив сортировку по этому полю. Если, например, в поле Summa указана сумма и требуется нисходящий порядок сортировки по этому полю, нужно ввести в запрос вычисляемое поле, в котором положительные значения Summa заменяются отрицательными, и выполнить сортировку по этому новому полю:
SBLECT .... -Summa AS SortSrnnma
FROM ...
ORDER BY SortSumma
К сожалению, этот прием не подходит для нисходящей сортировки по текстовым полям.
Следует заметить, что хотя SQL-интерпретатор BDE допускает сортировку по вычисляемым полям, стандарт SQL92 этого не требует, поэтому при работе с серверной БД нужно проверять возможность подобной сортировки. В InterBase, например, сортировка по вычисляемым столбцам невозможна, и для нисходящей сортировки требуется реальный «обратный^ столбец.
Визуализация данных
Характерной особенностью визуализации данных (визуализирующие компоненты сосредоточены в категории Data Controls палитры компонентов Delphi) является их подключение к необходимым компонентам-наборам через связующие компоненты TDataSource (источник данных). В этом разделе описьшаются основные приемы работы как с компонентами-источниками TDataSource, так и с компонентами, предназначенными для визуализации данных.
Компонент TDataSource
Свойства
Для правильной работы компонента TDataSource необходимо указать в свойстве DataSet имя связанного с ним компонента-набора. После этого компонент TDataSource играет роль своеобразного клапана, открывающего доступ компонентам визуализации к данным или блокирующего этот доступ. Для этого используется свойство Enabled компонента: если программа поместит в него значение False, связь данных с отображающими их компонентами блокируется. Этот прием широко используется на практике, если нужно осуществить навигацию по записям НД, не отображая этот процесс в компонентах визуализации. Например, в процедуре Count, представленной в листинге 3.5, реализуется подсчет сумм всех накладных.
Листинг 35 Подсчет сумм всех накладных
procedure TfmNakls.Count;
/ / Посчитывает общее количество накладных, а также суммы накладных // поставкиt продажиt возврата и обмена книг var
N: Integer;
NaklsNType.AsInt eger ofNaklsNType.AsInt eger ofcase0,6:1,7:2,3:4,5: end;case0,6:1,7:2,3:4,5: end;until notuntil notNakls.FindNext;Nakls.FindNext;
NaklsNType.AsInt eger of
NaklsNType.AsInt eger of
case
0,6:
1,7:
2,3:
4,5: end;
case
0,6:
1,7:
2,3:
4,5: end;
until not
until not
Nakls.FindNext;
Nakls.FindNext;
186 Глава 3 • Технология BDE.NET
Листинг 3.5 (продолжение)
SI, SO, SR, SC: Real;
BM: TBookmark ;
BegTime: TDateTime; // Измерение времени счета begin
N :
=0;
// Облгее количество
SI
:=0;
// Сумма поставок
SO
:=0;
// Сумма продаж
SR
:=0;
// Сумма возврата
SC
:=о;
// Сумма обмена
BegTime := Time;
// Запоминаем текущую запись
BM := Nakls-GetBookmark;
// Отключаем доступ к данным сетки DBGridl и DBGrid2,
// если установлен флажок CheckBoxl
丄£ CheckBoxl.Checked then
begin
DataSourcel.Enabled := False;
DataSource2.Enabled := False;
end;
〃 Переходим в начало ВД
Nakls.First;
repeat
inc (N);
SI+NaklsNSum. Value; SO+Nakl sNSum .Value;
:=SR+NaklsNSum.Value; :=SC+NaklsNSum. Value ;
// Лереходим к начальной запив и удаляем закладку Nakls.GotoBookmark(ВМ);
Nakls.FreeBookmark(BM);
// Включаем доступ к данным
True;True?True;True?DataSourcel.Enabled :
True;
True?
True;
True?
DataSource2.Enabled :
// Отображаем результат
ShovMessage(1 Всего •+IntToStr(N) + • накл. Поставка: * +
FloatToStrF(SI, FloatToStrF(SO, FloatToStrF(SR, FloatToStrF(SC,FloatToStrF(SI, FloatToStrF(SO, FloatToStrF(SR, FloatToStrF(SC,ffNumber, f f Number, ffNumber, ffNumber,ffNumber, f f Number, ffNumber, ffNumber,10,10,10,10,10,10,10,10,2)+'p, Продажа: '+2) + *p. Возврат: * +2) + *р. Обмен: 1 +2) +2)+'p, Продажа: '+2) + *p. Возврат: * +2) + *р. Обмен: 1 +2) +'р.'#131 Время счета: •+TimeToStr(Time-BegTime)); DBGridl.SetFocus;end;'р.'#131 Время счета: •+TimeToStr(Time-BegTime)); DBGridl.SetFocus;end;
FloatToStrF(SI, FloatToStrF(SO, FloatToStrF(SR, FloatToStrF(SC,
FloatToStrF(SI, FloatToStrF(SO, FloatToStrF(SR, FloatToStrF(SC,
ffNumber, f f Number, ffNumber, ffNumber,
ffNumber, f f Number, ffNumber, ffNumber,
10,
10,
10,
10,
10,
10,
10,
10,
2)+'p, Продажа: '+
2) + *p. Возврат: * +
2) + *р. Обмен: 1 +
2) +
2)+'p, Продажа: '+
2) + *p. Возврат: * +
2) + *р. Обмен: 1 +
2) +
'р.'#131 Время счета: •+TimeToStr(Time-BegTime)); DBGridl.SetFocus;
end;
'р.'#131 Время счета: •+TimeToStr(Time-BegTime)); DBGridl.SetFocus;
end;
Несложные замеры времени показывают, что при отключении доступа время работы процедуры составляет менее 1 с» а при сохранении — 8 с (процессор —
1700 МГц, память — 256 Мбайт). В нашей демонстрационной БД содержится информация всего примерно 700 накладных. В реальной БД с десятками тысяч записей экономия времени может достигать нескольких минут, в особенности на менее быстрых компьютерах.
События
Для компонента TDataSource определены три события, возникающие при изменении состояния связанного с ним НД:
type TDataChangeEvent = procedure(Sender: TObj ect;
Field: TField) of object;
property OnDataChange: TDataChangeEvent; property OnStateChange: TNotifyEvent;
property OnUpdateData: TNotifyEvent;
Событие OnDataChange возбуждается сразу после изменения какого-либо поля и при переходе к следующему полю той же записи или при переходе к новой записи. В первом случае параметр Field содержит измененное поле, во втором — NIL. Это событие удобно использовать для синхронизации содержимого меток TLabel, TStaticText или других не связанных с данными компонентов, с изменением курсора или содержимого полей текущей записи НД.
Событие OnStateChange возникает при каждом изменении состояния связанного НД. Его удобно использовать для предоставления или отмены доступа к командам меню, кнопкам и другим интерфейсным компонентам.
Событие OnUpdateData возбуждается непосредственно перед запоминанием изменений в таблице (до выполнения метода Post). В его обработчике можно запретить внесение изменений для тех или иных групп пользователей*
Компонент TDBGrid
Компонент TDBGrid (сетка) отображает содержимое НД в виде таблицы, в которой столбцы соответствуют полям НД, а строки — записям.
Свойства
Свойства компонента TDBGrid представлены в табл. 3.29.
Таблица 3.29. Свойства компонента TDBGrid
СвойствоОписание
type TFormBorderStyle = (bsNone, Определяет стиль рамки компонента (см. да- bsSingle, bsSizeable, bsDialog,лее)
bsToolWindow, bsSizeToolWin);
TBorderStyle = bsNone..bsSingle;
property Borderstyle:
TFormBorderStyle;
Таблица 3.29 (продолжение)
Свойство
Описание
property Columns: TDBGridColumns;
Содержит индексированный набор объектов- столбцов типа TDBGr idCo Luims (см. далее)
property Datasource: TDataSource;
Содержит ссылку на компонент типа TDataSource, служащий источником данных
property Def au 11Drawing: Boolean;
Если содержит True, содержимое ячеек сетки прорисовывается автоматически, в против* иом случае — в обработчике события OnDraw- ColumnCell или OnDrawDataCel 1
property EditorMode: Boolean;
Если содержит True, пользователь может редактировать ячейку после нажатия клавиши F2 или Enter. Игнорируется, если свойство Options включает значение goEditing или goAlwaysShowEditor
property FieldCount: Integer;
Содержит количество столбцов
property Fields [Index: Integer]:
Открывает индексированный доступ к полям
TField;
связанного с компонентом НД
property FixedColor: TColor;
Определяет цвет фиксированных полей
type TDBGridOption = (dg Edi ting,
Определяет вид и поведение компонента (см.
dgAlwaysShowEditor, dgTitles, dglndicator, dgColumnResize, dgColLines, dgRowLines, dgTabs, dgRowSelect, dgAlway sShowSe Lection, dgConf irmDelete, dgCancelOnExit, dgMultiSelect);
TDBGridOptions = set of TDBGridOption;
property Options: TDBGridOptions;
далее)
property Readonly: Boolean;
При значении True запрещает модификацию данных
property SelectedField: TField;
Открывает доступ к палю НД, связанному с текущим столбцом
property Selectedlndex: Integer;
Определяет индекс выбранного столбца в свойстве Columns
property TitleFont: TFont;
Определяет шрифт для заголовков столбцов
Свойство Borderstyle определяет стиль рамки компонента. Допустимые значения:
bsNone — нет рамки;
bsSingle — рамка толщиной 1 пиксел;
bsSizeable — обычная рамка изменяемых размеров;
bsDialog — диалоговая рамка (без возможности изменения размеров);
bsToolWindow — рамка bsSingle с уменьшенным заголовком;
bsSizeToolWin — рамка bsSizeable с уменьшенным заголовком.
Свойство Options определяет вид и поведение компонента. Допустимые значения:
dgEditing — разрешает изменение НД;
dgAlwaysShowEditor — автоматически переводит столбец в режим редактирования при его выделении;
dgTitles — показывает заголовки столбцов;
dglndicator — показывает индикатор текущей строки в самом левом фиксированном столбце;
dgColumnHesize — разрешает пользователю вручную изменять ширину столбцов;
dgColLines — показывает разделяющие вертикальные линии;
dgRowLines — показывает разделяющие горизонтальные линии;
dgTabs — разрешает переход от столбца к столбцу с помощью клавиши Tab;
dgRowS elect — разрешает выделение цветом всей выбранной строки;
dgAlwaysShowSelection — выделение текущей строки сохраняется, если компонент теряет фокус ввода;
dgC on f i rmDe 1 e t e — удаление строки должно подтверждаться;
dgCancelOnExit — если пользователь вставил пустую строку и покинул ее, она не помещается в НД;
dgMultiSelect — разрешает множественный выбор строк.
Объекты класса TDBGridColumns имеют заданное по умолчанию свойство Items, открывающее индексированный доступ к объектам-столбцам класса TColumn, и свойство Count, возвращающее количество элементов в свойстве items. В табл. 3.30 и 3.31 перечисляются наиболее важные методы класса TDBGridColumns и свойства класса TColumn.
Таблица ЗЛО. Методы класса TDBGridColumns
Метод
Описание
function Add: TColumn ;
Создает и возвращает объект-столбец
procedure RebuildColumns;
Удаляет старые определения объектов-столбцов и создает новые со свойствами, заданны-
ми по умолчанию
procedure RestoreDefaults ;
Восстанавливает определения всех объектов- столбцов, заданные по умолчанию
Таблица 3.31. Свойства класса TColumn
Свойство
Описание
type TColumnButtonstyle = (cbsAutOt cbsEllipsis, cbsNone);
property Buttonstyle:
TColumnButtonStyle;
Определяет стиль назначенной столбцу кнопки: cbsAuto — столбец содержит кнопку раскрывающегося списка; cbsEllipsis — столбец содержит кнопку, щелчок по которой вызывает событие OnEditButtonClick; cbs- None — столбец не содержит кнопки
property Color: TColor ; property DisplayName: String; property Field: TField;
Определяет цвет столбца
Содержит заголовок столбца
Содержит ссылку на связанное со столбцом поле НД
property FieldName: String;
property Font: TFont ;
property PickList: TStrings;
Содержит имя связанного со столбцом поля НД
Определяет шрифт столбца
Определяет элементы раскрывающегося списка, если в Buttonstyle установлено значение cbsAuto
property Readonly: Boolean;
Если содержит True, данные в столбце нельзя изменять
property Title: TColumnTitle;
Содержит ссылку на объект-заголовок, имеющий стандартные для визуальных компонентов свойства Alignment, Caption, Color и Font, позволяющие управлять текстом в заголовке столбца
property Visible: Boolean;
Если содержит False, столбец не отображается в сетке
property Width: Integer;
Содержит ширину столбца в пикселах
Методы
Методы компонента TDBGrid перечислены в табл. 3.32.
Таблица 3.32. Методы компонента TDBGrid
Метод
Описание
procedure DefaultDrawColinnnCell (const Rect: TRect; DataCol:
Осуществляет прорисовку ячейки таблицы, заданную по умолчанию: Rect — координаты
Integer; Column: TColumn; State: TGridDrawState);
ячейки; DataCol — индекс столбца; Column — столбец ячейки; State — состояние прорисовки
function Vai idFieldlndex
(Fieldindex: Integer): Boolean;
Возвращает True, если со столбцом с индексом Fieldindex связано поле НД. Если поле вычисляемое или оно не связано со столбцом, возвращает False
События
События компонента TDBGrid перечислены в табл. 3.33.
Таблица 3.33. События компонента TDBGrid
Событие
Описание
type TDBGridClickEvent = procedure (Column: TColumn) of obj ect;
Возникает после щелчка мышью в ячейке
property OnCellClick: TDBGridClickEvent;
property OnColEnter: TNotifyEvent;
Возникает в момент получения ячейкой фокуса ввода
property OnColExit: TNotifyEvent;
Возникает перед тем, как ячейка потеряет фокус ввода
type TMovedEvent = procedure (Sender: TObject; Fromlndex, Tolndex: Longlnt) of object;
Возникает при перемещении столбца: From- 工ndex — позиция столбца до перемещения; Tolndex — новая позиция столбца
property OnCo 1 umnMoved: TMovedEvent;
type Dr awCo 1 umnC ell Event = procedure (Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn;
State: TGridDrawState) of object;
Возникает при необходимости прорисовки ячейки: Rect — прямоугольник прорисовки; DataCol — индекс столбца в свойстве Columns; Column — столбец; State —— состояние прорисовки
property OnDrawColumnCel 1: TDrawColumnCellEvent;
pre^erty OnEditButtonClick: TNo tifyEvent;
Возникает при щелчке на кнопке в столбце
type TDBGr i dC 1 i ckEven t = procedure (Column: TColumn) of object;
Возникает при щелчке на заголовке
property onTitleClick:
TDBGridClickEvent;
Создание объектов-столбцов
Объекты-столбцы предназначены для гибкого управления свойствами визуального представления данных, отображаемых в столбцах сетки. С их помощью можно менять порядок следования отображаемых полей НД, заголовки столбцов, используемые в столбце шрифт и фоновый цвет.
Обьпшо объекты-столбцы создаются на этапе разработки программы с помощью редактора столбцов (рис. 3.13). Для его вызова нужно выбрать команду Columns Editor в контекстном меню компонента.
С помощью кнопки 耸 создастся новый объект-столбец; кнопка 百 позволяет удалить выделенный в окне редактора объект; с помощью кнопки Ш создаются объекты-столбцы для всех доступных полей НД; наконец, кнопка Ж служит для восстановления свойств выделенного объекта-столбца, заданных по умолчанию.
При работе с редактором сначала щелкните на кнопке 驟;чтобы создать столбцы для всех полей НД, затем удалите ненужные столб-
Рис. 3.13. Окно редактора столбцов цы. «Схватив» столбец мышью, перетащите его на нужное место (увеличенный на единицу номер слева от столбца покажет, каким но счету слева направо будет столбец в сетке). Для изменения заголовка столбца раскройте сложное свойство Title в окне инспектора объектов и измените его вложенное свойство Caption.
ПРИМЕЧАНИЕ
Если в сетке TDBGrid нужно оставить пустым заголовок какого-либо столбца, недостаточно просто удалить содержимое вложенного свойства Caption свойства Title соответствующего объекта-столбца — нужно поместить в заголовок хотя бы один пробел.
С помощью трех других вложенных свойств можно изменять выравнивание текста заголовка относительно границ столбца (Alignment), фоновый цвет заголовка (Color), цвет и шрифт текста (Font). Фоновый цвет столбца (кроме заголовка) и цвет/шрифт для отображаемых в нем данных изменяются с помощью свойств Color л Font. Защитить отображаемые в столбце данные от изменения можно с помощью свойства Readonly, а временно удалить его из сетки — с помощью свойства Visible.
Создание объектов-столбцов на этапе прогона программы обычно не требуется. Ис- к.лючением является разработка «умной» программы, которая запоминает сделанные пользователем в столбцах изменения (порядок их следования, ширину) при завершении работы и восстанавливает в момент очередного старта. Наиболее подходящим местом для запоминания параметров объектов-столбцов является реестр Windows. Два обработчика, представленные в листинге 3.6, демонстрируют технику запоминания объектов-столбцов в реестре (обработчик FormClose) и создания столбцов (FormCreate).
Листинг 3.6. Создание столбцов и запоминание их параметров в реестре Windows
uses Registry; f При работе с компонентом TRegistry нужна ссылка на модуль Registry }
procedure TfmNakls.FormClose(Sender: TObject;
var Action: TCloseAction);
var
Registry: TRegistry;
k: Integer;
begin
Registry := TRegistry.Create;
with Registry do begin
for к := 0 七о DBGridX.Columns.Count-1 do with DBGridl.Columns do
begin
OpenKey{1\Software', True);
OpenKey(1Nakls•, True);
OpenKey('DBGridl', True);
OpenKey(•Col * +IntToStr(k), True);
WriteString('Field', Items[k].FieldName);
WriteString(•Caption*, Items[k].Title.Caption);
Writelnteger (•width' f Items [k] .width); CloseKey end; // for Destroy; Action := caFree end // with end;
procedure TfmNakls.FormCreate(Sender: TObject); var
Registry : TRegistry;
k, Ns Integer;
begin
Registry := TRegistry.Create;
f Проверяем существование ключа software/nakls/DBGridl, ина^е при первом запуске программы все столбцы в сетке будут уничтожены 丿
if (Regie try. OpenKey (* software* , False)} and
(Registry.OpenKey('nakls1,False)) and
(Registiy.OpenKey('DBGridl',False)) then
with Registry do begin
N := DBGridl.Columns.Count-1;
// Удаляем столбцы в сетке:
DBGridl.Columns.Clear;
for k. : = 0 to N do with DBGridl. Columns do begin
OpenKey('\Software', True);
OpenKey('Nakls', True);
OpenKey('DBGridl', False);
OpenKey {'Col'+IntT.oStr(k), False);
Add; // Добавляем очередной столбец
Items[k].FieldName := Readstring(1 Field');
Items[k].Title.Caption := Readstring(* Caption *);
Items [k] .Width := ReadZnteger('width'); CloseKey end end; Registry.Destroy end;
7 Зак. 449
Пустые столбцы
Если создать объект-столбец и оставить незаполненным его свойство FiledName, будет создан пустой столбец. С помощью обработчика OnDrawColumnCell сетки (см. далее) в таком столбце можно выводить какую-либо информацию, основываясь на информации из действительно существующих полей набора данных. Например, из трех полей, содержащих, соответственно, название книги, имя автора и название издательства» можно в пустом столбце показать все три строки вместе. Однако для формирования нужной информации из полей НД значительно удобнее использовать событие OnGetText объекта-поля или создать в НД вычисляемое поле с соответствующим алгоритмом формирования выводимого значения. Чаще всего пустые столбцы действительно остаются пустыми, но при этом в строки столбца вставляются кнопки (для этого в свойство Buttonstyle устанавливается значение cbsEllips). При щелчке на кнопке (она становится видимой только в режиме редактирования ячейки с кнопкой) возникает событие OnEditButtonclick, которое программист может использовать по своему усмотрению. Например, графические поля, если их выводить для каждой записи в отдельном столбце сетки или даже для текущей записи с помощью отдельного компонента TDBlmage, требуют существенных затрат времени на вывод. Для ускорения листания сетки вместо графического поля устанавливается пустой столбец с кнопкой, а в обработчике события OnEditButtonclick предусматривается вызов формы» показывающей содержимое графического поля текущей записи или активизацию компонента TDBImage, расположенного на той же форме, что и сетка TDBGrid. Аналогичным образом можно поступать с мемо-полямн.
На рис. 3.14 показано окно отбора книг из списка (проект Q)03\EmptyCol\ EmptyCoLdpr). Самый правый столбец сетки — пустой. С помощью его кнопки в обработчике события OnEditButtonclick открывается диалоговое окно, в котором пользователь может указать количество экземпляров книги. Если диалог с пользователем заканчивается успешно, столбец будет отображать выбранные пользователем книги. Это достигается с помощью обработчика события OnDrawColumnCell. Замечу, что показанное на рисунке окно появляется после выбора команды Вставить в контекстном меню нижнего окна со списком связанных с накладной книг.
Формирование списка возможных значений столбца
Свойство PickList объекта-столбца содержит список возможных значений столбца. Если это свойство заполнено, при редактировании ячейки столбца в ее правом углу появляется небольшая кнопка, щелчок на которой раскрывает список. Это свойство для столбцов, отображающих подстановочные (lookup) поля НД, автомаптчески формируется содержимым отображаемого поля. На рис. 3.15 показан список, который содержит допустимые значения столбца Тип накладной. Для остальных столбцов это свойство в большинстве случаев остается пустым, по программист может заполнить его как на этапе разработки программы, так и при ее прогоне.
JOrtop ины ?.・〔x пай :1ЛДИоЛ tb 9N9 |Назву»»,Авгрр:/И¥4ytЦ>СТ8 ,宀冷「::;俨•「汜 丁1 :10 минут на урок М5 Word 2000 /Эйткен /Вильямс …"Ю мкнут на ^^^麻JOrtop ины ?.・〔x пай :1ЛДИоЛ tb 9N9 |Назву»»,Авгрр:/И¥4ytЦ>СТ8 ,宀冷「::;俨•「汜 丁1 :10 минут на урок М5 Word 2000 /Эйткен /Вильямс …"Ю мкнут на ^^^麻汇"匾^|g^г「:"兪侖|為訂妥:汇"匾^|g^г「:"兪侖|為訂妥:3636<3 :10 минут на уг-一一 4 иООкомпонеН5^1001 секрету6 :12 уроков те^一 7 i 13 шагов к yd 8;1С;Бухгаптеф9 !3D Studio MAX::亠 10 :X> Studio MA> : ■:> И :3O studio MA)_ 12 :3D Studio MAJ_ 13-3D Studio MaxH 6СЮ яукоеь:^<3 :10 минут на уг-一一 4 иООкомпонеН5^1001 секрету6 :12 уроков те^一 7 i 13 шагов к yd 8;1С;Бухгаптеф9 !3D Studio MAX::亠 10 :X> Studio MA> : ■:> И :3O studio MA)_ 12 :3D Studio MAJ_ 13-3D Studio MaxH 6СЮ яукоеь:^3Q Studio: MAX R3.Спецэффекты и дизайн а СЕНГОМ3Q Studio: MAX R3.Спецэффекты и дизайн а СЕНГОМ15 58 вопросов пс Windows Й15 58 вопросов пс Windows Йс ответами /Дьяконов /Солонс ответами /Дьяконов /Солон111142,00р.21,00р.42,00р.40,00р.55^ 00р. И,00р.6,00р.190,00р.60,00р.105,00р.167,00р. К 150,00 р.100,00р.76,00р, 7Ь00р.42,00р.21,00р.42,00р.40,00р.55^ 00р. И,00р.6,00р.190,00р.60,00р.105,00р.167,00р. К 150,00 р.100,00р.76,00р, 7Ь00р.
JOrtop ины ?.・〔x пай :1ЛДИоЛ tb 9
N9 |Назву»»,Авгрр:/И¥4ytЦ>СТ8 ,宀冷「::;俨•「汜 丁
1 :10 минут на урок М5 Word 2000 /Эйткен /Вильямс …"Ю мкнут на ^^^麻
JOrtop ины ?.・〔x пай :1ЛДИоЛ tb 9
N9 |Назву»»,Авгрр:/И¥4ytЦ>СТ8 ,宀冷「::;俨•「汜 丁
1 :10 минут на урок М5 Word 2000 /Эйткен /Вильямс …"Ю мкнут на ^^^麻
汇"匾^|g^г「:"兪侖|為訂妥:
汇"匾^|g^г「:"兪侖|為訂妥:
36
36
<3 :10 минут на уг-
一一 4 иООкомпонеН
5^1001 секрету
6 :12 уроков те^
一 7 i 13 шагов к yd 8;1С;Бухгаптеф
9 !3D Studio MAX:
:亠 10 :X> Studio MA> : ■:> И :3O studio MA)
_ 12 :3D Studio MAJ
_ 13-3D Studio Max
H 6СЮ яукоеь:^
<3 :10 минут на уг-
一一 4 иООкомпонеН
5^1001 секрету
6 :12 уроков те^
一 7 i 13 шагов к yd 8;1С;Бухгаптеф
9 !3D Studio MAX:
:亠 10 :X> Studio MA> : ■:> И :3O studio MA)
_ 12 :3D Studio MAJ
_ 13-3D Studio Max
H 6СЮ яукоеь:^
3Q Studio: MAX R3.Спецэффекты и дизайн а СЕНГОМ
3Q Studio: MAX R3.Спецэффекты и дизайн а СЕНГОМ
15 58 вопросов пс Windows Й
15 58 вопросов пс Windows Й
с ответами /Дьяконов /Солон
с ответами /Дьяконов /Солон
11
11
42,00р.
21,00р.
42,00р.
40,00р.
55^ 00р. И,00р.
6,00р.
190,00р.
60,00р.
105,00р.
167,00р. К 150,00 р.
100,00р.
76,00р, 7Ь00р.
42,00р.
21,00р.
42,00р.
40,00р.
55^ 00р. И,00р.
6,00р.
190,00р.
60,00р.
105,00р.
167,00р. К 150,00 р.
100,00р.
76,00р, 7Ь00р.
I,出卜 К СуЕ?[I,出卜 К СуЕ?[Щелкните 呀好质в,в столбце Хря-во"
I,出卜 К СуЕ?[
I,出卜 К СуЕ?[
Рис. 3.14. Отбор книг для накладной
二:^"广的外 5"d?r 代飞产卢 > f^w^pj'i*** ♦飞5 G ) *** P ^Накладны» иа книги
二,击7丽“貝/^嗓整工好碑 仔无工昼毎广
NaWd |Датй〔Партнер:- : :|тил накладной
Сужа (оплата |боз&рдт Ikom^^Cp а
1 01.03.2000 Точка, Социальный универсиПродажа на реализацию
550,00р.'0,0 0р. . 550,00р. ■1 :3 0.";
2 01.03.2000 .Яноеер
Продажа с предоплатой
335,92р,335,92р.0,00р. 1,MTL
3 01.03-2000 ИКС ОООЛродажа на ррализацню !5 337,50р.0,00р. ;0,00р, 0,7S: 10. i
4 01.03.2000 ДЕСС-Паблншер5
Приход по обмену
6 782,00р.0,00р. '0(00р.1 :01.
5 01-03.2000 Розничная продажа
Продажа с предолдатой
234,00р.234,00р. :0,00р.' 1,04 02,
6 01.03,2000 Точка. МГИЭМ
дежа на реализацию| —
2 320,70р. ■0,00р/2 320,70р.1.1 :30,
7 01,03.2000 000 Издательство "Нолндж1
Поставка на реалии: а
55 610,00р. X)201,65р.弟 406.3SP-1 :30,
8 01.03.2000 ПродалитЪ
Возврат поставки
2 767,50р-0,00р. ;0,00р. : 0,75 '31.
9 01.03,2000 Илита
Возврат продажи ; £:
655,00р.. qOOE; О.ООр, . 0,75 31.
10 01.03.2000 000 Издательство "Нолидж*
Приход по обмену
55 6!OfOOp.. GOOpJ 0)00р. :1 30.
Уход по обмену,■ ■
11 01.ОЭ.2000 ТРИУМФ
Поставка с предопла; v
;6 460,00р.0,00р.0,00р, ; 075 31. у
Назмние книги /Датор /Иэдате/ьстео
■ ■]Коп-во]Цека |л
>
Исторг экономических учений/ Бепоусов/Фвникс
12 4S,g
История философии.Учебник для студентов ВУЗов/ Кохановский/Феникс
15 29,70p-'
История экомом(-»:и:Уме6ник дпя вькшей школы/ Конатогюв/Акадвмическнй проект4 44,00р.
Философия■ Учебн!*: дпя XXI века/ Канке/Погос
5 57,20р.
Jls» 小
Рис. 3.15. Пример раскрывающегося списка для подстановочного поля
В процедуре PickListFill, предстанленной в листинге 3.7, список возможных зиачени!! столбца Коэф-т заполняется неповторяющимися значениями пиля NCoef f таблицы NAKLS (проект ChO3\PickList\PickList.dpr, рис. 3.16).
専
躋磅又j
三:
Двта^;;:^?.?|Партнер|типн»6иднойIcywa jOnnw^ iflcoa^^^li^^
01.03.2000 Точка. Социальный универоПродажа на реализацию : 550,00р. -0,00р. ; SSO^OOp. -1 30.04.2000 : ^;i
01.03.2000 :Яновер:Продажа с предоплатой : 335,92р. ; 335,92р. ;0,00р. . 1([М 31.03,2000
01.03.2000 WCC ООО^Продажа на реализацию 45 337j50p.0f00p. i 0,00р. ; 0,7S 10.04.2000
01.03.2000 如СиПаблиш^з:Приход по обмену; 6 782/ООр.0,00р」0(00р.1 ;01<03.2000
►
01.03.2000 Ромичмая продажа^Продажа с предоплатой 234,00р. : 234,00р.;0,00р. ^04|;*]02.03.2000
О1.СЭ.2000 .Точка. МГИЭМ'продажа на реализацию! 2 328z70p.0,00р. 2 Згв^Ор, а9^
2N.2000
01.03.2000 000 Издательство "Нолидж* Поставка на рмлимцию^Б 610л00р. 50 201)65р,为 4 06,35р. %'^
Ю.М.2000
01.03,2000 ЛродалитЪПродажа не реалимцию; 2 767?50р. : О^ООр. ;0,00р. 1
1.СЭ.2000
01.03,2000 И лита:Продвжа на реаляэгшпо :険5,00р. :0;00р.:0,00р.;吵 М
1.03.2000^1
«
j |назм»^ к^м^/Автор/Издгвл ?.
:1коп-во]Цена^ |Сумка 扌
卜Ьдплппипнннт йычиспмтит+*>1й гигт*мы( КлгнймиНлпип*
拉1盛
з 7R.rem.- E%
"「五9058 1;
Рис. 3.16. Список столбца «Коэф-т» состоит из неповторяющихсязначений поля NCoeff таблицы NAKLS
Листинг 3.7. Заполнение столбца сетки значениями поля набора данных procedure TfmNakls.PickListFill;
// 3曰门о/7няет список pfukLisc столбца пКаэф-тм неполторяющимися
// значениями поля NCoeff таблицы NAKLS
var
N: Integer;
begin
[Столбец со значениями поля NCoeff может менять свое положение, поэтому сначала ищем его: }
N : = 0 ;
while DBGridl.Columns[N].FieldNameo'NCoeff' do inc(N);
// Заполняем список;
cjuCoef f .Open;
while not quCoeff.EOF do with DBGridl.Columns[N].PickList do
begin
Add (qijCoef fNCoef f . AsSt ring);
quCoeff.Next
end;
quCoef£.Close
end;
Чтобы воспроизвести этот пример, поместите на форму компонент TQuery, назовите его quCoef f, свяжите с локальным псевдонимом АДА и напишите такой запрос: SELECT DISTINCT NCoeff
FROM Nakls
ORDER BY NCoeff
Создайте для НД quCoef f объект-поле quCoef fNCoef f. Процедуру PickListFill можно вызвать в конце обработчика FormCreate.
Управление отображением данных
С помощью обработчика события OnDrawColumnCell программист может учесть характер отображаемых данных То, как осуществляется прорисовка данных в сетке TDBGrid — стандартным способом или по особому сценарию, — определяется свойством DefaultDrawing. Если это свойство имеет значение False, алгоритм прорисовки должен содержаться в обработчиках события OnDrawCo 1 umnC ell или OnDrawDatасе 11. Замечу, что обработчик события OnDrawDatаСе 11 введен для совместимости с ранними версиями Delphi:
property OnDrawColumnCel1: TDrawColumnCel1Event;
TDrawColumnCellEvent = procedure (Sender: TObject;
const Rect: TRect;
DataCol: Integer;
Column: TColumn;
State: TGridDrawState) of object;
Параметры здесь следующие:
e Rect — координаты области прорисовки;
• DataCol — порядковый номер текущего столбца, начиная с нулевого;
в Column — текущий столбец;
е state — состояние ячейки:
о gdSelected — ячейка выделена;
о gdFocused — ячейка имеет фокус ввода;
о gdFixed — ячейка относится к фиксированной строке (строке заголовков столбцов) или столбцу.
Если параметр State содержит значение gdSelected (то есть ячейка выделена), в обработчике события OnDrawColumnCel 1 необходима прорисовка инверсного прямоугольника, а если значение gdFocused — пунктирного прямоугольника выделения.
Для вывода ячеек стандартным образом используется метод DefaultDrawColumnCell.
Следует заметить, что если для сетки свойство DefaultDrawing содержит значение True, заданное по умолчанию, обработчики будут вызваны после завершения стандартной процедуры прорисовки, то есть программный вывод в этом случае накладывается на стандартный. Это может стать причиной неправильного отображения данных, например так, как показано на рис. 3.17 (проект Ch03\ DrawCell\DrawCell.dpr).
В этом примере использовался обработчик события OnDrawCo 1 umnC ell, представленный в листинге 3.8.
Листинг 3.8. Обработчик события OnDrawColumnCel!
procedure TForml.DBGridlDrawColumnCel1(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumn;
State: TGridDrawState);入
продолжение 夕
Листинг 3.8 (продолжение) begin
if Books['BPrice']>10 then with DBGridl.Canvas do begin
Font.Style := [fsltalic];
TextOut(Rect.Left, Rect.Top, Column.FieId.Text) end end;
闻икЗтрйЦМ!嚥Й1倦隱傅RR鞫伊0Й(密崗彎嚙战義應賜囑^^酿嬲期恵屮国感"J®闕嚟嬲
IT也而*mе,>d hCa»c徊腐緻缪1褐
66 無仇,44рЗ
10IWHXY H3 Jk^CW WM>*$99
” 17 *#4/9P
iOmw^TH& y^ok.Ocbc*сояосто*г5ьно M5ExZ280
"27加仇,уp
100 колпмвнго» общего нлзн&чен^ ^£йж row De^iS
』匕也物,00p
*001 секрет реестра WindowsNT
充35充g5曲p
12 уроков тенниса.Самый достут»ый самоучитель для всех
6; Ю^ООр
13 шагов к успеху или практические советы как быстро достичь карьеры в
39;4,00p :
刀 5” Z7e во/^ссах 力。丁ве『зх
刀 23 a冏 25p:
殁 Slut% MAX 25 спрмочник
/8”A/2p:
如 5ЬлД? МАХ З.Уч^М 毁 c i CD-ROM
66^^75р
30Studb MAXr3.5611?色4”Yz内承a曲 + 9ROM
比 30:〃"乙 37P
笫 Studo МАХ,Вн^г^еннийя^. Tiw 2 丿 CD-ROM
尸6^4组00p
3D Studio Max 3,0 о г объекта до омпчвц# 丿 CD-ROM
68%学次25P
600 叭长8ax 内嘅约кальных програЕ菱5;定 255,25p
第加qvee 加 Windows ЗВ г отэе ram
〃 11®5%,50р;
Access2000‘冷 /тооьлмз те^,Р^сп^^>венн&я 叫如
剧 20® 不,7Sp;
Access Э7.Р^оводсгво 加 ^дкроязык^ nV8A-b S^CW
53\Щ50^
McessМЭнц^жлопе^ягюльз^ателя十 3#陋
% iMagjop
Administrtrin^SQL 5iwerZ64pw^KWfcvMM^odMa^,《rrQ0MM(力应砂
亙:电翅:再画風
Рис. 3.17. Пример двойной прорисовки строк, в которых «Цена» больше 10 р.
Для большей наглядности нестандартный вывод сделан намеренно отличающимся от стандартного (курсив, текст не выравнивается).
Чтобы исключить нежелательное влияние стандартного вывода, нужно вначале закрасить прямоугольник прорисовки:
procedure TForml.DBGridlDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if Books[* Price1]=0 then with DBGridl.Canvas do begin
FilLRac匸(R启ut);// Удаляем стандартный вывод
Font.scyle :二 [fsltalic];
TexcOut(Rect.Left, Rect.Top, Column.Field.Text} end end;
При двойной прорисовке может замедлиться скорость листания данных в сетке, особенно для компьютеров с невысокой производительностью. В этом случае нужно в свойство DefaultDrawing поместить значение False и позаботиться о стандартной прорисовке:
procedure TForml.DBGridlDrawColwnnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
i£ Books[•Price *]=0 then with DBGridl.Canvas do begin
Font.Style := [fsltalic];
TextOut(Rect.Left, Rect.Top, Column.Field,Text) end
else 〃 Вез следующего оператора
// стандартные строки будут пустыми!
DBGridl.DefaultDrawColumnCell(Rect, DataCol# Column, State) end;
Событие OnDrawCo lumnCe 11 возникает при прорисовке каждой ячейки, при этом текущей записью базового НД становится запись с прорисовываемой ячейкой. Это дает возможность проверить информацию в ячейке; отличающейся от рисуемой. В обработчике, представленном в листинге 3.9, в списке накладных серым фоном закрашиваются строки, по которым нет задолженности (проект ChOBXDrawCellZXDrawCell.dpn рис. 3.18).
Листинг 3.9. Выделение записей, по которым нет задолженности
uses db; // В модуле db определена константа ftString
fSR *.DFM}
procedure TfmNakls.DBGridlDrawColuinnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
/ / Закрашивает серым фоном строки с данными о накладных, //по которым нет задолженности begin
i£ (NaklsNSum.Value=NaklsNPayedSum.Value+NaklsNRetSum.Value) and not (gdSelected in State) then
with DBGridl.Canvas do begin
Brush.Color := clGray;
FillRect(Rect);
Font.Color := clWhite;
i£ Column.Field.DataType=ftString then
// В текстовых полях текст выравнивается влево TextOut(Rect.Left+2,Rect.Тор+2,Column.Field*Text)
❷工“❷продолжение步
200 Глава 3 • Технология BDE.NET
Листинг 3.9 (продолжение)
// В остальных полях — вправо
Text Ou t (Recti. Righr-Textwidth (Column .Field.Text)-2, Rect.Top+2,Column.Field.Text)
end; end;end; end;
end; end;
end; end;
i域买i域买炉條打玄,2值油law&,T』uj屯汰椎*yw*落КдПразази4尹8»它第c贄*皆/坤2< Ql.©5.20GC,: Яноеео …‘・;■ ■ ■TRD&aamiJX: rjHA«r.仪гсб :.S3S.92炉條打玄,2值油law&,T』uj屯汰椎*yw*落КдПразази4尹8»它第c贄*皆/坤2< Ql.©5.20GC,: Яноеео …‘・;■ ■ ■TRD&aamiJX: rjHA«r.仪гсб :.S3S.920,00:0,00:二 X二 X3^01.03.2000 ИКС ООО4^01.03.2000 ДЕСС-Паблишерз3^01.03.2000 ИКС ООО4^01.03.2000 ДЕСС-Паблишерз■Продажа на рвализшию ^5 337,50р. j■Продажа на рвализшию ^5 337,50р. jПриход по обменуПриход по обмену!б782,00рН!б782,00рН.§ ; В打U3;N0QS:Рмкямнзй 吶心己 *3 燃::М?&绫々 01 о? :m\^^ [<t.W.§ ; В打U3;N0QS:Рмкямнзй 吶心己 *3 燃::М?&绫々 01 о? :m\^^ [<t.W’Пр” з #<j t мзсчт 巾隔 j ^彳由丁 :门口 n a&¥ 3 кй и吁口,用*辿内叶:? ?:3,70.:’Пр” з #<j t мзсчт 巾隔 j ^彳由丁 :门口 n a&¥ 3 кй и吁口,用*辿内叶:? ?:3,70.:OjOOp.: b^oop.:OjOOp.: b^oop.:234,ОД-: 一234,ОД-: 一?i必庆£汪啪心к<埼3力总了片^Тво卞的口ь收广门黄丁邮出наj>am3u%^ Г?弘也的:?i必庆£汪啪心к<埼3力总了片^Тво卞的口ь收广门黄丁邮出наj>am3u%^ Г?弘也的:
i域买
i域买
炉條打玄,2值油law&,T』uj屯汰椎*yw*落КдПразази4尹8»它第c贄*皆/坤
2< Ql.©5.20GC,: Яноеео …‘・;■ ■ ■TRD&aamiJX: rjHA«r.仪гсб :.S3S.92
炉條打玄,2值油law&,T』uj屯汰椎*yw*落КдПразази4尹8»它第c贄*皆/坤
2< Ql.©5.20GC,: Яноеео …‘・;■ ■ ■TRD&aamiJX: rjHA«r.仪гсб :.S3S.92
0,00:
0,00:
二 X
二 X
3^01.03.2000 ИКС ООО
4^01.03.2000 ДЕСС-Паблишерз
3^01.03.2000 ИКС ООО
4^01.03.2000 ДЕСС-Паблишерз
■Продажа на рвализшию ^5 337,50р. j
■Продажа на рвализшию ^5 337,50р. j
Приход по обмену
Приход по обмену
!б782,00рН
!б782,00рН
.§ ; В打U3;N0QS:Рмкямнзй 吶心己 *3 燃::М?&绫々 01 о? :m\^^ [<t.W
.§ ; В打U3;N0QS:Рмкямнзй 吶心己 *3 燃::М?&绫々 01 о? :m\^^ [<t.W
’Пр” з #<j t мзсчт 巾隔 j ^彳由丁 :门口 n a&¥ 3 кй и吁口,用*辿内叶:? ?:3,70.:
’Пр” з #<j t мзсчт 巾隔 j ^彳由丁 :门口 n a&¥ 3 кй и吁口,用*辿内叶:? ?:3,70.:
OjOOp.: b^oop.:
OjOOp.: b^oop.:
234,ОД-: 一
234,ОД-: 一
?i必庆£汪啪心к<埼3力总了片^Тво卞的口ь收广门黄丁邮出наj>am3u%^ Г?弘也的:
?i必庆£汪啪心к<埼3力总了片^Тво卞的口ь收广门黄丁邮出наj>am3u%^ Г?弘也的:
0,00р.0,00р.[Кшню便厨[Кшню便厨Название кнмги^Автор /Йшательст&оНазвание кнмги^Автор /Йшательст&о0(00р.;0(00р.;8 01.03.2000 ПродалитЪ;Продажама реалиэацию; 2 767,50р.9 -01.03.2000 Илита^Продажа ма реализацию^ 855,00р<;:0,0 0р.10:01.03.2000 000 Издательство 'Ъолидж^Поставка на реалимцию^ 610,00р< :8 01.03.2000 ПродалитЪ;Продажама реалиэацию; 2 767,50р.9 -01.03.2000 Илита^Продажа ма реализацию^ 855,00р<;:0,0 0р.10:01.03.2000 000 Издательство 'Ъолидж^Поставка на реалимцию^ 610,00р< :Рис. 3.18. Серым цветом выделяются оплаченные накладныеРис. 3.18. Серым цветом выделяются оплаченные накладные
0,00р.
0,00р.
[Кшню便厨
[Кшню便厨
Название кнмги^Автор /Йшательст&о
Название кнмги^Автор /Йшательст&о
0(00р.;
0(00р.;
8 01.03.2000 ПродалитЪ;Продажама реалиэацию; 2 767,50р.
9 -01.03.2000 Илита^Продажа ма реализацию^ 855,00р<;:0,0 0р.
10:01.03.2000 000 Издательство 'Ъолидж^Поставка на реалимцию^ 610,00р< :
8 01.03.2000 ПродалитЪ;Продажама реалиэацию; 2 767,50р.
9 -01.03.2000 Илита^Продажа ма реализацию^ 855,00р<;:0,0 0р.
10:01.03.2000 000 Издательство 'Ъолидж^Поставка на реалимцию^ 610,00р< :
Рис. 3.18. Серым цветом выделяются оплаченные накладные
Рис. 3.18. Серым цветом выделяются оплаченные накладные
История экономических учений/ Белоусое/Феникс
История философ*»».Учебник для студентов ВУЗов/ Кохановский/Фенжс
В этом обработчике проверяется активность ячейки, и, если ячейка активна (gdSelected in State), для вывода используется обработчик Def aultDraw- DataCell, заданный по умолчанию. Сдвиг на 2 пиксела вправо и вниз относительно левого верхнего угла прямоугольника Rect ячейки реализован в обработчике Def aultDrawDataCell для стандартного шрифта MS Sans Serif высотой 8 пунктов, поэтому если вы хотите, чтобы выводимый вами текст ие отличался от стандартного, указывайте эти величины смещения (для другого шрифта они нуждаются в корреюгировке). В обработчике проверяется тип данных: строковые данные выргшниваются по левому краю столбца, остальные — по правому (именно так поступает обработчик DefaultDrawDataCell).
Дополнительные возможности сетки
У компонента есть свойство, с помощью которого можно управлять поведением н внешним видом сетки:
type
TDBGridOption = (dgEditing, dgAlwaysShowEditor, dgTitles( dglndicator, dgColumriResize, dgColLines, cigRowLines , dgTabs , dgRowSelect,
dgAlwaysShowSelection, dgConfirmDelete, dgCancelOnExit f dgMultiSelect);
TDBGridOptions = set of TDBGridOption; property Options: TDBGridOptions;
Параметры здесь следующие:
dgEditing — разрешает изменение НД;
dgAlways ShowEdi t or — при выделении столбца автоматически переводит его в режим редактирования;
dgTitles — показывает заголовки столбцов;
dglndicator — показывает указатель текущей строки в самом левом фиксированном столбце;
dgColumnResize — разрешает пользователю с помощью мыши менять ширину столбцов;
dgColLines — показывает в сетке вертикальные разделяющие линии;
dgRowLines — показывает горизонтальные разделяющие линии;
dgTabs — разрешает переход от столбца к столбцу с помощью клавиши Tab;
dgRowSelect — разрешает выделение цветом всей текущей строки;
dgAlwaysShowSelection — выделение текущей строки цветом сохраняется, даже если компонент теряет фокус ввода;
dgConfirmDelete — требует подтверждения удаления строки;
dgCancelOnExit — если пользователь вставляет пустую строку и покидает ее, она не сохраняется в таблице БД;
dgMultiSelect — разрешает множественный выбор строк.
Замечу, что отсутствие в свойстве значения dgEditing защищает отображаемые в сетке данные от изменения независимо от значения свойства Readonly любого ее столбца. Точно так же защищает строки вставка в свойство значения gdRowSelected, кроме того, в этом случае из свойства автоматически удаляются значеш1я dgEditing и dgAlwaysShowEditor (если, разумеется они входили в множество Options; эти значения нельзя вставить в свойство, пока в нем присутствует значение dgRowSelected). В защищенной сетке нельзя изме* нить ни одной ячейки текущей строки, но можно удалить строку или вставить пустую строку (если в свойстве нет значения dgCancelOnExit). Если вы не собираетесь защищать данные, полезно вставить в свойство Options значение dgAlwaysShowEditor — в этом случае столбец автоматически переводится в режим редактирования, как только он получает фокус ввода; если это значение отсутствует, редактировать выделенный столбец можно после нажатия клавиши F2 или Enter либо после двойного щелчка на ячейке мышью.
Компоненты для визуализации полей текущей записи
В отличие от сетки TDBGrid, все рассматриваемые в этом разделе компоненты визуализируют отдельные поля текущей записи. В связи с этим говорят о двух способах визуализации данных: в виде таблицы (сетки) и в виде формы. Последняя
представляет собой обычную форму, на которую помещены компоненты визуализации полей текущей записи. На рис. 3.19 показан пример формы для ввода и редактирования данных по накладной.
B^o/j/редак шронание нлкюдной
•Тип накладной 7;广 Продажа на реализациюj С Возврат поставкиI Возврат продажиj「Приход по обменуУход по обмену' ' : "i 广 Поставка с предоплатойI 广 Продажа с предоплатой•Тип накладной 7;广 Продажа на реализациюj С Возврат поставкиI Возврат продажиj「Приход по обменуУход по обмену' ' : "i 广 Поставка с предоплатойI 广 Продажа с предоплатойДата:' [отгоог* Возврат: |з0М2000
•Тип накладной 7
;广 Продажа на реализацию
j С Возврат поставки
I Возврат продажи
j「Приход по обмену
Уход по обмену' ' : "
i 广 Поставка с предоплатой
I 广 Продажа с предоплатой
•Тип накладной 7
;广 Продажа на реализацию
j С Возврат поставки
I Возврат продажи
j「Приход по обмену
Уход по обмену' ' : "
i 广 Поставка с предоплатой
I 广 Продажа с предоплатой
Партнер: 一
|000 Издательство "Нолидж"
Коэффициент сжидки/наценкй:'
X 8n 炉"X 8n 炉"Сумма J155 610.00р. Оплате; рогОШр'
X 8n 炉"
X 8n 炉"
Рис. 3.19. Пример формы для ввода и редактирования данных по накладной
Для нормальной работы любого из описываемых далее компонентов нужно определить два его свойства: поместить в свойство DataSource имя связанного с набором данных компонента-источника TDataSource, а в свойство DataField — имя отображаемого поля.
Компонент TDBText
С помощью компонента TDBText текстовое содержимое различных полей НД можно показывать в том виде, в котором оно отображается в сетке TDBGrid. Фактически компонент повторяет функциональность метки TLabel за тем исключением, что его текст формируется автоматически на основании значения некоторого поля текущей записи. Отображаемый компонентом текст нельзя изменять, и, следовательно, с его помощью нельзя редактировать связанное с ним поле. Разумеется, тип отображаемого поля должен обеспечивать приведение к текстовому значению.
Для использования компонента TDBText нужно связать его с соответствующим полем НД с помощью свойств DataSource и DataField.
Компонент TDBEdit
Компонент TDBEdit позволяет редактировать значение поля текущей записи НД. Он повторяет функциональность компонента TEdit, позволяющего корректировать текстовое значение переменной, но источником данных и их приемни-
ком для него служит поле НД. Тип этого поля должен обеспечивать приведение к текстовому значению. В форме, показанной на рис. 3.19, компонент TDBEdit использован для ввода и редактирования полей дат, сумм и коэффициента скид- ки/наценки.
При вводе значения в компонент TDBEdit программа автоматически следит за тем, чтобы оно было совместимо по формату с полем НД, Ввод неверных значений блокируется. Например, если в компонент, связанный с полем типа дата-время, попытаться поместить произвольный текст, будет возбуждена исключительная ситуация.
Свойства, методы и события компонента аналогичны свойствам, методам и событиям стандартного компонента TEdit.
Компонент TDBCheckBox
Компонент TDBCheckBox обладает функциональностью стандартного флажка TCheckBox, но источником данных и их приемником для него служит поле НД, которое может бьпъ логическим или символьным, В последнем случае необходимо соответствующим образом установить значения текстовых свойств ValueChecked и ValueUnchecked компонента. Например:
DBCheckBoxl.ValueChecked := "True;Yes;On;Да;Д1;
DBCheckBoxl.ValueUnchecked := 'False;No;Off;Нет;Н*;
Компонент TDBRadioGroup
Компонент TDBRadioGroup служит для представления фиксированного набора возможных значений поля при помощи группы переключателей. Этот компонент обладает функциональностью стандартного переключателя TDBRadioGroup, но источником данных и их приемником для него служит поле НД. На рис. 3.19 этот компонент позволяет выбрать тип накладной.
Количество и названия вариантов возможных значений поля определяются в свойстве
property Items: TStrings;
Компонент будет связывать установку того или иного переключателя с соответствующим значением поля. Для этого список возможных значений определяется свойством
property Values: TStrings;
Например, для формы с рис. 3.19 свойства Items и Values компонента dbrgType типа TDBRadi oGroup определены так, как показано на рис. 3.20.
Списочные компоненты
Визуализирующие компоненты типа TDBListBox, TDBComboBox, TDBLookup- ComboBox, TDBLookupListBox имеют связанные с ними списки TStrings и поэтому дальше объединяются общим названием списочные компоненты БД.
Рис. 3.20. Значения свойств компонента TDBRadioGroup: слева ——Items; справа ——ValuesРис. 3.20. Значения свойств компонента TDBRadioGroup: слева ——Items; справа ——Values
Рис. 3.20. Значения свойств компонента TDBRadioGroup: слева ——Items; справа ——Values
Рис. 3.20. Значения свойств компонента TDBRadioGroup: слева ——Items; справа ——Values
Списочные компоненты предназначены для отображения состояния конкретного поля текущей записи НД, а также для ввода в это поле нового значения (но никак не для навигации по НД!). Первые два компонента имеют первоначально пустые списки,которые программист должен заполнить перед тем, как они станут доступными пользователю. Компоненты TDBLookupXXXX формируют свои списки значениями, взятыми из поля другого НД, и не нуждаются в их наполнении — вот, собственно, и вся разница между ними и первыми двумя компонентами. Компоненты TDBListBox и TDBLookupListBox могут отображать текущее значение связанного с ними поля только в том сл^ае, если это значение совпадает с одним из списочных значений компонента, два других отображают любое значение поля, даже если этого значения нет в связанных с компонентами списках. Точно так же вводить новое значение компоненты XXXXListBox могут только мз своих списков, в то время как компоненты ХУА^ХСошЪоВох в модификациях csSimple и csComboBox содержат текстовую строку для ввода значения, которого нет в списке.
Компоненты TDBLookupXXXX могут исполковаться двумя способам»: если в редактируемом НД есть нужное подстановочное поле, для них, как и для других рассматриваемых в этом разделе компонентов, достаточно определить лишь свойства DataSource и DataField, причем в последнем указать имя подстановочного поля; если в НД пет подстановочного поля, в свойство Datasource помещается имя компонента-источника, связанного с редактируемым НД, в свойство DataField — имя поля с шифром (ссылочного поля) этого НД, в свойство ListSource — имя компонента-источника, связанного с подстановочным НД, в ListField — имя отображаемого (результирующего) поля и, наконец, в KeyField — имя индексного поля, на которое ссылается поле DataField редактируемого НД. Например, в форме на рис. 3.19 компонент TLookupComboBox используется для отображения имени партнера. В первом варианте в его свойство Datasource нужно поместить значение DataSourcel, а в свойство DataField — имя подстановочного поля Firm. Во втором варианте предварительно на форме нужно разместить компонент DataSourceB, связав его с НД Firms, в свойство DataSource по-прежнему помещается значение DataSourcel, а вот в свойство DataField — имя подстановочного поля NFirm, при этом в ListSource — значение DataSource3,
в ListField — FName и в KeyField — Firm工D. Способ использования компонента не имеет значения: в любом случае в поле NFirm НД Nakls будет помещен шифр выбранного партнера.
Компонент TDBMemo
Компонент TDBMemo предназначен для отображения и редактирования мемо-поле(1 (полей комментариев), которые служат для хранения в таблицах БД многострочных текстов. Компонент TDBMemo является практически аналогом компонента ТМешо — с той разницей, что источником данных для него служит мемо-поле НД. В связи с этим его свойства, методы и события в основном совпадают со свойствами, методами и событиями компонента ТМешо.
Специфичными для компонента являются свойства DataSource и DataField (в которые следует поместить имена компонента-источника и мемо-поля соответственно), а также следующие свойства:
property AutoDisplay: Boolean;
property Field: TField;
Если в свойство AutoDisplay помещено значение True, любые изменения мемо-поля автоматически отображаются в компоненте, а при открытии НД компонент будет отображать содержимое мемо-поля текущей записи. Если в свойство AutoDisplay пометено значение False, содержимое мемо-поля заменяется его названием, а для просмотра или редактирования его значения нужно либо дважды щелкнуть на компоненте, либо выделить его и нажать клавишу Enter.
Свойство Field открывает доступ к мемо-полю.
При корректировке текста в компоненте TDBMemo набор данных, которому принадлежит поле, автоматически переводится в состояние dsEdit. Замечу, что изменение значения свойств Text или Lines не переводит НД в режим редактиро- вання, н эти изменения не переносятся в мемо-поле. Поэтому перед внесением изменений в значения свойств Lines или Text следует переводить НД в режим редактирования методом Edit, а затем запоминать изменения методом Post.
Компонент TDBRichEdit
Компонент TDBRichEdit позволяет просматривать и корректировать информацию в мемо-поле форматированного комментария. Текст форматированного комментария может содержать фрагменты, набранные различным шрифтом, размером, стилем, цветом и т. д. В отличие от компонента TDBMemo, который позволяет работать только с однородным (неформатированным) текстом, компонент TDBRichEdit умеет интерпретировать специальные символы разметки текста в формате RTF (Rich Text Format — расширенный текстовый формат). Многие свойства, методы и события компонента аналогичны по назначению одноименным свойствам, методам и событиям компонента TRichEdit и в этом разделе не описываются.
Специфичными для компонента являются свойства DataSource, DataField, AutoDisplay и Field, описанные в предыдущем подразделе.
206 Глава 3 • Технология BDE.NET
Компонент TDBCtrIGrid
Как уже говорилось, существует два средства визуализации данных: таблицы и формы. В таблицах пользователь может видеть одновременно несколько записей НД, что облегчает ему контроль за данными н выбор необходимой записи. При применении формы пользователь в каждый момент видит на экране лишь одну запись НД, по зато имеет простой доступ к любому ее полю, в том числе многострочному или графическому. Компонент TDBCtrIGrid в известной мере сочетает в себе удобства обоих средств: он представляет собой таблицу, каждая ячейка которой отображается в виде формы (проект ChO3\CtrlGrid\ CtrIGrid.dpr, рис, 3.21).
喇^摘綁承辭験承辎曜碘册離k^w :Парг呷 *очка Ьамальный унив^ситаГ ▼〔喇^摘綁承辭験承辎曜碘册離k^w :Парг呷 *очка Ьамальный унив^ситаГ ▼〔■ Партнер Яновер■ Партнер Яновервадвад1鉴1鉴
喇^摘綁承辭験承辎曜碘册離k^w :Парг呷 *очка Ьамальный унив^ситаГ ▼〔
喇^摘綁承辭験承辎曜碘册離k^w :Парг呷 *очка Ьамальный унив^ситаГ ▼〔
■ Партнер Яновер
■ Партнер Яновер
вад
вад
1鉴
1鉴
Тип накп. |г^)ода^ на реализациюТип накп. |г^)ода^ на реализациюТип нам. Продажа с предоплатойТип нам. Продажа с предоплатой'3;'3;
Тип накп. |г^)ода^ на реализацию
Тип накп. |г^)ода^ на реализацию
Тип нам. Продажа с предоплатой
Тип нам. Продажа с предоплатой
'3;
'3;
Дата^ [oi.O3.2OOOДата^ [oi.O3.2OOOСумма I 550,&р:Сумма I 550,&р:Дата ^1X)3.2000" Суйма「云,珏:Дата ^1X)3.2000" Суйма「云,珏:Партнер икс ОООПартнер икс ООО三| 卜 Партнер ДЕСС-Паблишерз三| 卜 Партнер ДЕСС-ПаблишерзТе накл. Продажа на реализациюТе накл. Продажа на реализациюДата [oi.O3.2OOO Cywa. ^5 ззлйр.;:Дата [oi.O3.2OOO Cywa. ^5 ззлйр.;:L. "Партнёр: ■■ Розничная продажа二 Тип накп. Продажа с предоплатойL. "Партнёр: ■■ Розничная продажа二 Тип накп. Продажа с предоплатой11[ип накп. Приход по обмену[ип накп. Приход по обменуДата 机R WEДата 机R WEСу^ ] б782' оор. ИСу^ ] б782' оор. ИПартнер Tog. мгиэмТип накп; Продажа на реализациюПартнер Tog. мгиэмТип накп; Продажа на реализацию1'1'
Дата^ [oi.O3.2OOO
Дата^ [oi.O3.2OOO
Сумма I 550,&р:
Сумма I 550,&р:
Дата ^1X)3.2000" Суйма「云,珏:
Дата ^1X)3.2000" Суйма「云,珏:
Партнер икс ООО
Партнер икс ООО
三| 卜 Партнер ДЕСС-Паблишерз
三| 卜 Партнер ДЕСС-Паблишерз
Те накл. Продажа на реализацию
Те накл. Продажа на реализацию
Дата [oi.O3.2OOO Cywa. ^5 ззлйр.;:
Дата [oi.O3.2OOO Cywa. ^5 ззлйр.;:
L. "Партнёр: ■■ Розничная продажа
二 Тип накп. Продажа с предоплатой
L. "Партнёр: ■■ Розничная продажа
二 Тип накп. Продажа с предоплатой
1
1
[ип накп. Приход по обмену
[ип накп. Приход по обмену
Дата 机R WE
Дата 机R WE
Су^ ] б782' оор. И
Су^ ] б782' оор. И
Партнер Tog. мгиэм
Тип накп; Продажа на реализацию
Партнер Tog. мгиэм
Тип накп; Продажа на реализацию
1'
1'
Дата R[而而丁 • Сумма「234,00р.Дата R[而而丁 • Сумма「234,00р.Дата pi而五丁 , Сумма |Тз2В70р?Дата pi而五丁 , Сумма |Тз2В70р?
Дата R[而而丁 • Сумма「234,00р.
Дата R[而而丁 • Сумма「234,00р.
Дата pi而五丁 , Сумма |Тз2В70р?
Дата pi而五丁 , Сумма |Тз2В70р?
Рис. 3.21. Пример использования компонента TDBCtrIGrid
Для работы с компонентом необходимо поместить его на форму, связать с компонентом TDataSource, который, в свою очередь» связать с каким-либо набором данных (TTable или TQuery), и затем разместить на нем необходимые компоненты для работы с полями базы данных — TDBText, TDBEdit, TDBCheckBox и т. п. Компоненты для работы с полями базы данных требуется разместить в верхней строке компонента TDataSource или, если количество столбцов ColCount компонента больше 1, в левой верхней ячейке компонента (рис. 3.22).
Рис. 3.22. Пример работы с компонентом TDBCtrlGrid на этапе разработки программы
Во время прогона программы расположение компонентов в Bepxneii строке (верхней левой ячейке) компонента TDBCtrlGrid и их состав будут реплицированы на все оставшиеся строки (ячейки), как это видно из рис. 3.21.
Приемы работы с компонентами TDBC匸rlGr id и TDBG匸i ci аналогичны. Текущая строка (ячейка) выделяется пунктирным прямоугольником. Для навигации по сетке компонента используются тс же клавиши, что и для TDBGrid. Дяя вставки новой записи необходимо нажать клавишу Insert или иопытатьс'я ne|)eiiTii с последней записи в НД вниз на одну строку (для сетки с одним столбцом). Для изменения записи достаточно ввести новое значение в какое-либо поле. Для удаления записи необходимо нажать комбинацию клавиш Ctrl+Delete. При этом на возможности редактирования, добавления и удушения записей в компонете TDHCr 匸二匚г 丄壮 влияет ряд свойств как других компонентов, размещенных в ячейках ком нонен га TDBCtrlGrid, так и самого компонента TDBCtrlGrid.
Далее приводится обзор некоторых свойств, методов н событи!! компонента TDBCt-.rlGrid.
Свойства компонента TDBCtrlGrid представлены в табл. 3.34.
Таблица 3.34. Свойства компонента TDBCtrlGrid
СвойствоОписание
property AllowDelete: Boolean;Разрсшаст/запретаст уд;иение записей
property Allowlnsert: Boolean;Разрешает/запрешаст вставку aaniiceii
продолжение 今
Таблица 3.34 (продолжение)
Свойство
Описание
property ColCount: Integer;
Определяет количество столбцов в сетке
type TDBCtrlGridOrientation = (goVertical# goHorizontal);
property Orientation:
TDBCtrlGridOrientation;
Определяет ориентацию сетки: goVertical — вертикальная (по умолчанию); goHorizontal —горизонтальная (с горизонтальной полосой прокрутки)
type TDBCtrlGridBorder = (gbNone, gbRaised);
Тип рамки вокруг каждой ячейки: gbNone — нет рамки; gbRaised — выпуклая рамка
property PanelBorder:
TDBCtrlGridBorder;
property PanelHeight: integer;
Высота ячейки в пикселах
property Panelwidth: Integer;
Ширина ячейки в пикселах
property RowCount: Integer;
Определяет количество одновременно показываемых строк сетки
property SelectedColor: TColor;
Определяет цвет выделенной ячейки
property ShowFocus: Boolean;
Разрешает/запрещает обводить пунктирным прямоугольником ячейку с фокусом ввода
Для компонента TDBCtrlGrid определен метод DoKey:
type TDBCtг1GridKey = (gkNull, gkEditMode, gkPriorTab, gkNextTab, gkLeft, gkRxght, gkUp, gkDown, gkScrollUp, gkScrollDown, gkPageUp, gkPageDown, gkHome, gkEnd, gklnsert, gkAppend, gkDeletie, gkCancel);
procedure DoKey(Key: TDBCtrlGridKey);
Действие, вьшолняемое методом, определяется параметром Key:
gkNull — ничего не делать;
gkEditMode — перевести компонент в режим редактирования;
е gkPriorTab — передать фокус ввода предыдущей ячейке;
е gkNextTab — передать фокус ввода следующей ячейке;
е gkbef t — передать фокус ввода ячейке слева;
gkRight — передать фокус ввода ячейке справа;
gkUp — передать фокус ввода ячейке сверху;
gkDown — передать фокус ввода ячейке снизу;
• gkScrollUp — прокрутить сетку на строку вверх;
е gkScrollDown — прокрутить сетку на строку вниз;
е gkPageUp — прокрутить сетку на экран вверх;
gkPageDown — прокрутить сетку на экран вниз;
gkHome — передать фокус ввода первой ячейке;
gkEnd — передать фокус ввода последней ячейке;
gklnsert — перевести компонент в режим редактирования;
gkAppend — перевести компонент в режим добавления записи;
gkDelete — перевести компонент в режим удаления записи;
gkCancel — восстановить режим просмотра.
Для компонента TDBCtrlGrid определены следующие события, аналогичные одноименным событиям сетки TDBGrid: OnClick, OnDblClick, OnDragDrop, OnDragOver, OnEndDrag, OnEnter, OnExit, OnKeyDown, OnKeyPress, OnKeyUp, OnStartDrag. Дополнительно введено событие, которое наступает для каждой ячейки TDBCtrlGrid перед ее отображением:
property OnPaintPanel: TPaintPanelEvent;
TPaintPanelEvent = procedure(DBCtrlGrid: TDBCtrlGrid;
Index: Integer) of object;
Обработчик этого события может управлять прорисовкой ячейки. Параметр TDBCtrlGrid показывает, какой именно компонент TDBCtrlGrid нуждается в прорисовке; параметр Index определяет индекс отображаемой ячейки.
Компонент TDBNavigator
Строго говоря, компонент TDBNavigator (навигатор БД) не предназначен для отображения данных. Его назначение — дать пользователю программы удобное средство перемещения по записям НД и облегчить ему такие действия, как вставка
First Next Insert Edit Cancel同:旧丁+1令屮X甲Prior Last Delete Update RefreshРис. 3.23. Кнопки навигатора БДFirst Next Insert Edit Cancel同:旧丁+1令屮X甲Prior Last Delete Update RefreshРис. 3.23. Кнопки навигатора БДновой записи, а также редактировав । ние и удаление существующей записи. Однако навигатор БД используется j только совместно с компонентами ви- - зуализации, поэтому мне кажется вполне уместным рассмотреть его особенности именно в этом разделе.
First Next Insert Edit Cancel
同:旧丁+1令屮X甲
Prior Last Delete Update Refresh
Рис. 3.23. Кнопки навигатора БД
First Next Insert Edit Cancel
同:旧丁+1令屮X甲
Prior Last Delete Update Refresh
Рис. 3.23. Кнопки навигатора БД
На рис. 3.23 показаны кнопки навигатора. Назначение кнопок:
First — устанавливает курсор на первую запись;
Prior — устанавливает курсор на предыдущую запись;
Next — устанавливает курсор на следующую запись;
Last — устанавливает курсор на последнюю запись;
Insert — переводит НД в режим вставки новой записи;
Delete — удаляет текущую запись;
Edit — переводит НД в режим редактирования;
Post — запоминает изменения, сделанные в текущей записи;
Cancel — отменяет изменения, сделанные в текущей записи;
Refresh — обновляет НД (для TQuery — только если запрос обновляемый).
С помощью свойства Datasource компонент связывается с нужным источником данных TDataSource — это все, что необходимо для его нормальной работы. Представленное ниже свойство управляет отображением диалогового окна с просьбой подтвердить удаление записи (значение True этого свойства выводит окно):
property ConfirmDelete: Boolean;
Если следующее свойство имеет значение True, кнопки плоские, в противном случае — объемные:
property Flat: Boolean;
С помощью другого свойства можно отображать только те кнопки навигатора, которые действительно необходимы:
type TNavigateBtn = (nbFirst, nbPrior, nbNext, nbLast, nblnsert # nbDelete, nbEdi E # nbPost,, nbCancel, nbRefresh);
type TButtonSet = set of TNavigateBtn; property VisibleButtons: TButtonSet;
Например, если НД является результатом выполнения необновляемого запроса, в навигаторе имеет смысл оставить только первые 4 кнопки.
С помощью следующего метода можно имитировать щелчок на нужной кнопке навигатора:
procedure BtnClick(Index: TNavigateBtn);
Для компонента определены два специфических события:
type ENavClick = procedure (Sender: TObject;
Button: TNavigateBtn) of object;
property BeforeAction: ENavClick;
property OnClick: ENavClick;
Обработчик первого события получает управление перед выполнением действия, связанного со щелчком на кнопке Button, в то время как обработчик OnClick — после выполнения действия.
Технология dbGo.NET
Начиная с версии 5, Delphi поддерживает технолошю ADO (ActiveX Data Objects - объекты данных, построенные как объекты ActiveX), которая развивалась корпорацией Microsoft и которая в конце концов переросла в технологию ADO.NET (см. главу 2).
В последних версиях Delphi «старая» технология ADO называется dbGo. В Delphi 2005 она приспособлена к работе на платформе .NET и называется dbGo.NET. Все компоненты технологии сосредоточены в категории dbGo палитры компонентов Delphi.
На основе этой технологии созданы соответствующие компоненты-наборы TADOTable, TADOQuery, TADOStoredProc, повторяющие в функциональном отношении компоненты ттаЫе, TQuery, TStoredProc, но не требующие раз- вертьгвания и настройки BDE на клиентской машине.
Основные особенности использования технолопш dbGo.NET не зависят от архитектуры БД — эта технология характерна не только для файл-серверных БД, но также и для клиент-серверных и трехзвенных БД. Однако в этой главе (и в книге вообще) мы не будем рассматривать особенности компонентов TADOStoredProc и TRDSConnect ion, предназначенных для поддержки, соответственно, клнент- серверной и трехзвенной архитектур, — если вас интересуют эти вопросы, обратитесь к документации и/или к встроенной справочной службе.
Основным достоинством технологии dbGo.NET является ее естественная ориентация на создание «облегченного» клиента. В рамках этой технологии на машине разработчика БД устанавливаются базовые объекты MS ADO 2.1 и соответствующие компоненты Delphi (рис. 4.1), обеспечивающие использование технологии dbGo.NET (эти установки осуществляются автоматически при развертывании Delphi). На машине сервера данных (это может быть файловый сервер в рамках фаил-серверной технолоши или машина с сервером данных в технологии
клиент—сервер) устанавливается так называемый провайдер данных — некоторая надстройка над специальной технологией OLE DB, «понимающая» запросы объектов ADO и «умеющая» переводить эти запросы в нужные действия с данными. Взаимодействие компонентов ADO и провайдера осуществляется на основе универсальной для Windows технологии ActiveX, причем провайдер реализуется как COM-сервер, а ADO-компоненты — как СОМ-клиенты.
Рис. 4Д. Реализация технологии dbGo.NET в DelphiРис. 4Д. Реализация технологии dbGo.NET в DelphiШНЭООТ5«ОН зьхшхосго^ШНЭООТ5«ОН зьхшхосго^sbzoxoEZOXvzx^qw^xmsbzoxoEZOXvzx^qw^xm
Рис. 4Д. Реализация технологии dbGo.NET в Delphi
Рис. 4Д. Реализация технологии dbGo.NET в Delphi
ШНЭООТ5«ОН зьхшхосго^
ШНЭООТ5«ОН зьхшхосго^
sbzoxoEZOXvzx^qw^xm
sbzoxoEZOXvzx^qw^xm
На машине сервера создается и размещается источник данных. В случае файл- серверных систем отдельные таблицы типа dBASE, FoxPro, Paradox и т. п. должны управляться соответствующим ODBC-драйвером» а в роли провайдера используется Microsoft OLE DB Provider for ODBC drivers. Если по каким-либо причинам не найден нужный драйвер, файл-серверные таблицы можно перевести в формат MS Access. На их основе создается единый файл, содержащий все необходимые таблицы, индексы, хранимые процедуры и прочие элементы БД. Такой файл управляется машиной баз данных Microsoft Jet 4.0 Database Engine, а в роли провайдера используется Microsoft Jet 4.0 OLE DB Provider.
Если применяется промышленный сервер данных Oracle или MS SQL Server, данные не нуждаются в какой-либо предвартельной подготовке, а в роли провайдера используется, соответственно, Microsoft OLE DB Provider for Oracle или Microsoft OLE DB Provider for SQL Server. Нетрудно обнаружить и явный недостаток такой технологии: dbGo.NET не может использоваться, если для соответствующей структуры данных (в частности, для БД многих популярных серверов — InterBase, Informix, DB2 и пр.) не создан нужный провайдер или ODBC-драйвер.
На машине клиента располагаются связные компоненты тADOConneс t i on и компоненты-наборы данных TADOTable, TADOQuery, TADOStoredProc, а также не показанные на рисунке компоненты-наборы TADODataSet и командные компоненты TADOCommand. Каждый из этих компонентов может связываться с провайдером данных либо с помощью связного компонента TADOConnec t i on, либо минуя его и используя собственное свойство Connectionstring. Таким образом, компонент TAD0C оппес t i on играет роль кон центратора соединений с источником данных компонентов-наборов, и в этом смысле он подобен компоненту TDatabase в архитектуре BDE.NET.
Командные компоненты TADOCommand предназначены для реализации запросов на языке определения данных (Data Definition Language, DDL), то есть для реализации SQL-запросов, которые не возвращают данные (запросы типа CREATE, DROP, UPDATE и т. п.). Специальный компонент RDSConnection (не показан на рисунке) созлан для упрощения связи с MS Internet Explorer и при разработке ннтранет-приложений.
Компоненты-наборы с помощью компонентов-источников TDataSource и визуализирующих компонентов TDBGrid, TDBMem。,TDBEdit и т. п. обеспечивают необходимый интерфейс с пользователем программы. Эти компоненты рассмотрены в главе 3.
Пример простой программы
В этом разделе рассматриваются основные особенности использования технологи dbGo.NET. Описанный далее пример (проект Ch04\Nakls\Projectl.dpr) в функциональном плане повторяет пример, рассмотренный в разделе «Пример простой программы» главы 1: в нем иллюстрируется реляционная связь главный —дсталь- ный между таблицами NAKLS и MOVES:
Итак, начните новый VCL-проект и поместите на форму компонент ADOCcn- netion, 5 компонентов ADOTable (категория dbGo палитры компонентов) и 2 компонента DataSource (категория Data Access). Назовите таблицы именами Nakls, Moves, Firms, Books, Types и свяжите источник данных DataSourcel с таблицей Nakls, а источник данных DataSource2 — с таблицей Moves.
Поскольку предполагается использовать файл-серверные таблицы типа Paradox» такие таблицы должны управляться драйвером ODBC. Этот драйвер следует предварительно настроить на работу с нужным каталогом. Для этого в главном меню выберите команду Пуск ► Настройка ► Панель управления ► Администрирование и щелкните на значке Источники данных (ODBC).
На вкладке Пользовательский DSN открывшегося окна выберите в списке Источники данных пользователя пункт Paradox files» как показано на рис. 4.2, и щелкните на кнопке Настройка.
ВНИМАНИЕ
В некоторых конфигурациях Delphi устанавливает не все драйверы ODBC. В этом случае в списке на вкладке Пользовательский DSN вы можете не увидеть пункта Paradox files. Если это так, щелкните на кнопке Добавить и в списке открывшегося окна выберите пункт Microsoft Paradox Driver. В конечном счете будет открыто окно, показанное на рис. 4.2, и вы сможете настроить драйвер. Мне не удалось добиться нормальной работы драйвера Driver do Microsoft Paradox (версия 4.00.6304.00). Зато работают два других драйвера — Microsoft Paradox Driver и Microsoft Paradox Driver-Treiber.
В открывшемся окне (рис. 4.3) сбросьте флажок Использовать текущий каталог, щелкните на кнопке Выбор каталога и с помощью нового диалогового окна
214 Глава 4 • Технология dbGo.NET
выберите каталог размещения файлов, после чего закройте все окна, щелкая на кнопке ОК. При назначении каталога в реальной программе очень часто бывает необходимо сослаться на сетевой серверный диск. В этом случае щелкните на кнопке Сеть в окне выбора каталога и введите сетевое имя диска, например: \ \SRV\C.
警需鄒^^^^^6識}^^' f中吗寶岭岑炉9闻州内沙£田警需鄒^^^^^6識}^^' f中吗寶岭岑炉9闻州内沙£田;'Драйвврк»)': .1:' Трахирорка' I Гр(рп^овк«подклюме»«^: | : 0 программе j ::Iltwtoa^ OSH f СистёммыйОЗН Г ;ф;'Драйвврк»)': .1:' Трахирорка' I Гр(рп^овк«подклюме»«^: | : 0 программе j ::Iltwtoa^ OSH f СистёммыйОЗН Г ;фЙсточмики данеьт пользователяЙсточмики данеьт пользователяИмя :Имя :^Driver do Micraoft Paradox『db) база данных MS Access Microsoft Access Driver (",mdbj^Driver do Micraoft Paradox『db) база данных MS Access Microsoft Access Driver (",mdbj中 ай/iE dBASE 中 айса Excel中 ай/iE dBASE 中 айса ExcelMicrosoft d8a$e Driver ('".dbf) Microsoft Excel Driver C xls)Microsoft d8a$e Driver ('".dbf) Microsoft Excel Driver C xls)Источник дамж ODBC гюльэоветеля сохраняет свеаения об ■ установке связи с источником Он доступен тогЬко этому пот»з(хмггело м может применяться лишь на длиной коьгъкггере.Источник дамж ODBC гюльэоветеля сохраняет свеаения об ■ установке связи с источником Он доступен тогЬко этому пот»з(хмггело м может применяться лишь на длиной коьгъкггере.OKOKОтмена 上屮Отмена 上屮
警需鄒^^^^^6識}^^' f中吗寶岭岑炉9闻州内沙£田
警需鄒^^^^^6識}^^' f中吗寶岭岑炉9闻州内沙£田
;'Драйвврк»)': .1:' Трахирорка' I Гр(рп^овк«подклюме»«^: | : 0 программе j ::Iltwtoa^ OSH f СистёммыйОЗН Г ;ф
;'Драйвврк»)': .1:' Трахирорка' I Гр(рп^овк«подклюме»«^: | : 0 программе j ::Iltwtoa^ OSH f СистёммыйОЗН Г ;ф
Йсточмики данеьт пользователя
Йсточмики данеьт пользователя
Имя :
Имя :
^Driver do Micraoft Paradox『db) база данных MS Access Microsoft Access Driver (",mdbj
^Driver do Micraoft Paradox『db) база данных MS Access Microsoft Access Driver (",mdbj
中 ай/iE dBASE 中 айса Excel
中 ай/iE dBASE 中 айса Excel
Microsoft d8a$e Driver ('".dbf) Microsoft Excel Driver C xls)
Microsoft d8a$e Driver ('".dbf) Microsoft Excel Driver C xls)
Источник дамж ODBC гюльэоветеля сохраняет свеаения об ■ установке связи с источником Он доступен тогЬко этому пот»з(хмггело м может применяться лишь на длиной коьгъкггере.
Источник дамж ODBC гюльэоветеля сохраняет свеаения об ■ установке связи с источником Он доступен тогЬко этому пот»з(хмггело м может применяться лишь на длиной коьгъкггере.
OK
OK
Отмена 上屮
Отмена 上屮
Рис. 4.2. Выбор драйвера ODBCРис. 4.2. Выбор драйвера ODBCИмя йсто«1йка Данкьм; {Paradox files @писаник •: JИмя йсто«1йка Данкьм; {Paradox files @писаник •: J3厂 И спольэоаэть текущий кэталог ! _t.: .. ..::、/ Параметры» j3厂 И спольэоаэть текущий кэталог ! _t.: .. ..::、/ Параметры» j
Рис. 4.2. Выбор драйвера ODBC
Рис. 4.2. Выбор драйвера ODBC
Имя йсто«1йка Данкьм; {Paradox files @писаник •: J
Имя йсто«1йка Данкьм; {Paradox files @писаник •: J
3厂 И спольэоаэть текущий кэталог ! _t
.: .. ..::、/ Параметры» j
3厂 И спольэоаэть текущий кэталог ! _t
.: .. ..::、/ Параметры» j
р Базаданнь»
;^«рсм^ I Paradox 5.x3
I心壮呼 WIBLDATA Н( Вь^экаталога;.
Рис. 4.3. Выбор источника данных для драйвера ODBC
Теперь следует настроить связь объектов dbGo.NET с соответствуюпиiм провайдером. Для этого дважды щелкните на компоненте AdoConnectionl или выде- лше его и окне инспектора объектов и щелкните на кнопке с многоточием в строке свойства Connectionstring, чтобы вызвать окно настройки связи (рис, 4.4).
Source of Connerton - 广 gO^&Unk 咏Source of Connerton - 广 gO^&Unk 咏足 Use .£pnmtucri: swng ■£ ;;■足 Use .£pnmtucri: swng ■£ ;;■
Source of Connerton - 广 gO^&Unk 咏
Source of Connerton - 广 gO^&Unk 咏
足 Use .£pnmtucri: swng ■£ ;;■
足 Use .£pnmtucri: swng ■£ ;;■
Рис. 4.4. Окно настройки связи
Щелкните на кнопке Build и в списке иа вкладке Поставщик данных нового окна выберите пункт Microsoft OLE D8 Provider for ODBC Drivers (рис. 4.5).
:n©crawuHMw/foix |ik龈лечена卜Домлниге通ноj Все |
:Выберите подключаема данные
'; а !
: MediaCatalogDB OLE DB Piovidef: -; ■;
MediaCatalogMefgedDB OLE DB Ptovidet; J L
MediaCatalogWebDB OLE DB Piovidefj 不
Mtcrosoh ISAM 11 OLE DB Provideij
MicrosoFt Jet 4.0 OLE DB Providerj .;
Mb301t OLE DBProvider For D&a Mining Services::二
Microsoft OLE DBProvider foi DTS Packages:
Microsoft OLE DBProvider fo< Indexing Service;
Microtoft OLE DBProvider for Irteinet PuMuhing:j
Microsoft OLE DBRovidw for Olap Services 8.0
Mtcrosotl OLE DBProvider for Oracte(
Microsoft OLE DBProvider for Outlook Search■% ■
-< Micrtisaft OLE DBProvider foi SQLSeivet'.
Microsoft OLE DB Simple Provider'
. MGDataShape.J
F;: SQL Server Replication OLE DB Provide» to: DTS 油:■ |
0K [ Отмена [ Спрмпа
Рис. 4.5. Настройка связи: выбор провайдера
Щелкните на кнопке Далее, в новом окне переедите на вкладку Подключение и, установив переключатель Использовать имя источника данных, выбе!)птс в раскрывающемся списке тип используемых данных — пункт Paradox Files.
Поскольку ранее мы уже настроили драйвер OBDC, можно щелкнуть на кнопке Проверить подключение, чтобы убедиться в нормальном функционировании
связи. Закройте окно щелчком на кнопке ОК и щелкните на кнопке ОК еще раз — связь готова! Чтобы в дальнейшем связь с БД устана в л и вал ас ь без открытия промежуточного дихюгового окна с запросом имени пользователя и пароля, поместите в свойство LoginPrompt компонента AdoConnectiionl значение False.
Теперь пора настроить оставшиеся компоненты. В свойстве Connection компонентов-таблиц сошлитесь на компонент AdoConnectionl. В свойстве TableName этих компонентов выберите соответствующие таблицы БД. В свойстве DataSet компонентов DataSourcel и DataSource2 сошлитесь, соответственно, на таблицы Nakls и Moves.
Свяжем таблицы отношением главная—детальная: установите в свойство Mastersource таблицы MOVES ссылку на источник данных Da^aSourcel и щелкните на кнопке с многоточием в строке свойства MasterFielcls, чтобы вызвать окно настройки (рис. 4.6).
Рис. 4.6. Окно настройки таблиц на связь главная—детальная
Установите связь по общим полям Nakl工D и NakllD и закройте окно щелчком на кнопке ОК.
Сохраните на диске основную форму программы под именем f mdbGoU и сам проект под именем dbGoTest.
Дальнейшая работа над проектом выполняется так же, как описано в подразделе «Разработка главной формы» раздела «Пример простой программы» главы 1. Па рис. 4.7 показано окно работающей программы.
Установление связи с объектом ADO
Установление связи с объектом ADO является ключевым моментом всей техиоло- п-ш. Как уже отмечалось, каждый компонент НД имеет два свойства, с помощью которых он может установить связь с объектом ADO: Connection и Conneo
tionString. В первое помещается ссылка на специальный связной компонент TAdoConnection, играющий роль концентратора соединения с объектом ADO, во вторую — собственно строка связи. Эти свойства взаимоисключающие, то есть установка значения и одно нз них ведет к очистке второго.
:1Двтй -::: Тлйй* 工可瀉;•・.:|Тйп»и»мада^;<^;::7^ |Кой^|опй^т^'-|бййрвт?;-' {фок- а<1 01.03.2000 Точка. Социальный университ<Продажа на реалимцию 2 Oi.03.2000 ЯноверПродажа с предоплатой ■3 01.03.2000 ИКС ОООпродажа на реатмцню4 01.03.2000 ДЕСС-ЛаблмшерэПриход по обмену;5,01.03.2000 Розжчная продажаПродажа с предоплатой !缨01.03.2000.Точка. МГИЭМПродажа на реалшцию :7 01 .G3.2000 ОООИ5двтепьство',Нолиджв ГЪхтавка на реалпмцию8 01.03.2000 ПродалнтЪПрОАЗха на реализацию'9 01.G3.2000 Илитапродажа на реализацкк);10 01.03.2000 000 Издательство "Нолидж" Поставка ма реализациюЬ00;550,00:IJM; 335,92:‘0,5?…*或而; 1,00; 6 782,00| i,w^ гз4,оо;-Liq; гз28(7о;ЬОО ; 15S610,00;0,75: 2 767,50;0,75;855,00;LOO; 155 610#Х:0,М:550(00; 30.04.2000举尸?!Q,M^1-03.2000游;0,(Mi 10.04.20000(00-0,00 :01.03.2000moo; о.м'ог.оэ.гооо0,00: 2 326,70 >,04.200060 201,65- 95 40S,35':30.04.2000aoojо,м; a i.03.20000,00^O,M:3!.O3.2MQ0,00 f0,00:30.04.2000|Н£ЯШ1Й« /Автор /И»АвТ«ЛЬСТВО|Кол-во .Щене ' JR:1Двтй -::: Тлйй* 工可瀉;•・.:|Тйп»и»мада^;<^;::7^ |Кой^|опй^т^'-|бййрвт?;-' {фок- а<1 01.03.2000 Точка. Социальный университ<Продажа на реалимцию 2 Oi.03.2000 ЯноверПродажа с предоплатой ■3 01.03.2000 ИКС ОООпродажа на реатмцню4 01.03.2000 ДЕСС-ЛаблмшерэПриход по обмену;5,01.03.2000 Розжчная продажаПродажа с предоплатой !缨01.03.2000.Точка. МГИЭМПродажа на реалшцию :7 01 .G3.2000 ОООИ5двтепьство',Нолиджв ГЪхтавка на реалпмцию8 01.03.2000 ПродалнтЪПрОАЗха на реализацию'9 01.G3.2000 Илитапродажа на реализацкк);10 01.03.2000 000 Издательство "Нолидж" Поставка ма реализациюЬ00;550,00:IJM; 335,92:‘0,5?…*或而; 1,00; 6 782,00| i,w^ гз4,оо;-Liq; гз28(7о;ЬОО ; 15S610,00;0,75: 2 767,50;0,75;855,00;LOO; 155 610#Х:0,М:550(00; 30.04.2000举尸?!Q,M^1-03.2000游;0,(Mi 10.04.20000(00-0,00 :01.03.2000moo; о.м'ог.оэ.гооо0,00: 2 326,70 >,04.200060 201,65- 95 40S,35':30.04.2000aoojо,м; a i.03.20000,00^O,M:3!.O3.2MQ0,00 f0,00:30.04.2000|Н£ЯШ1Й« /Автор /И»АвТ«ЛЬСТВО|Кол-во .Щене ' JR4S,10i 29,疝 M.ooi 57,20 ;4S,10i 29,疝 M.ooi 57,20 ;15 История жономимеосих учений /Бепоусов /Феникс16 История философим.Учебннс для студентов ВУЗов /Коханоеоснй /Феккс17 :История 5кс»ю«нки:Учвбник для еьгшей школы /Кокотопое /Ахааемический проект16 Философия.Учебник для XXI веке /Кан« /Погос15 История жономимеосих учений /Бепоусов /Феникс16 История философим.Учебннс для студентов ВУЗов /Коханоеоснй /Феккс17 :История 5кс»ю«нки:Учвбник для еьгшей школы /Кокотопое /Ахааемический проект16 Философия.Учебник для XXI веке /Кан« /Погос
:1Двтй -::: Тлйй* 工可瀉;•・.:
|Тйп»и»мада^;<^;::7^ |Кой^|опй^т^'-|бййрвт?;-' {фок- а
<
1 01.03.2000 Точка. Социальный университ<Продажа на реалимцию 2 Oi.03.2000 ЯноверПродажа с предоплатой ■
3 01.03.2000 ИКС ОООпродажа на реатмцню
4 01.03.2000 ДЕСС-ЛаблмшерэПриход по обмену;
5,01.03.2000 Розжчная продажаПродажа с предоплатой !
缨01.03.2000.Точка. МГИЭМПродажа на реалшцию :
7 01 .G3.2000 ОООИ5двтепьство',Нолиджв ГЪхтавка на реалпмцию
8 01.03.2000 ПродалнтЪПрОАЗха на реализацию'
9 01.G3.2000 Илитапродажа на реализацкк);
10 01.03.2000 000 Издательство "Нолидж" Поставка ма реализацию
Ь00;550,00:
IJM; 335,92:
‘0,5?…*或而; 1,00; 6 782,00| i,w^ гз4,оо;
-Liq; гз28(7о;
ЬОО ; 15S610,00;
0,75: 2 767,50;
0,75;855,00;
LOO; 155 610#Х:
0,М:550(00; 30.04.2000
举尸?!Q,M^1-03.2000
游;0,(Mi 10.04.2000
0(00-0,00 :01.03.2000
moo; о.м'ог.оэ.гооо
0,00: 2 326,70 >,04.2000
60 201,65- 95 40S,35':30.04.2000
aoojо,м; a i.03.2000
0,00^O,M:3!.O3.2MQ
0,00 f0,00:30.04.2000
|Н£ЯШ1Й« /Автор /И»АвТ«ЛЬСТВО
|Кол-во .Щене ' JR
:1Двтй -::: Тлйй* 工可瀉;•・.:
|Тйп»и»мада^;<^;::7^ |Кой^|опй^т^'-|бййрвт?;-' {фок- а
<
1 01.03.2000 Точка. Социальный университ<Продажа на реалимцию 2 Oi.03.2000 ЯноверПродажа с предоплатой ■
3 01.03.2000 ИКС ОООпродажа на реатмцню
4 01.03.2000 ДЕСС-ЛаблмшерэПриход по обмену;
5,01.03.2000 Розжчная продажаПродажа с предоплатой !
缨01.03.2000.Точка. МГИЭМПродажа на реалшцию :
7 01 .G3.2000 ОООИ5двтепьство',Нолиджв ГЪхтавка на реалпмцию
8 01.03.2000 ПродалнтЪПрОАЗха на реализацию'
9 01.G3.2000 Илитапродажа на реализацкк);
10 01.03.2000 000 Издательство "Нолидж" Поставка ма реализацию
Ь00;550,00:
IJM; 335,92:
‘0,5?…*或而; 1,00; 6 782,00| i,w^ гз4,оо;
-Liq; гз28(7о;
ЬОО ; 15S610,00;
0,75: 2 767,50;
0,75;855,00;
LOO; 155 610#Х:
0,М:550(00; 30.04.2000
举尸?!Q,M^1-03.2000
游;0,(Mi 10.04.2000
0(00-0,00 :01.03.2000
moo; о.м'ог.оэ.гооо
0,00: 2 326,70 >,04.2000
60 201,65- 95 40S,35':30.04.2000
aoojо,м; a i.03.2000
0,00^O,M:3!.O3.2MQ
0,00 f0,00:30.04.2000
|Н£ЯШ1Й« /Автор /И»АвТ«ЛЬСТВО
|Кол-во .Щене ' JR
4S,10i 29,疝 M.ooi 57,20 ;
4S,10i 29,疝 M.ooi 57,20 ;
15 История жономимеосих учений /Бепоусов /Феникс
16 История философим.Учебннс для студентов ВУЗов /Коханоеоснй /Феккс
17 :История 5кс»ю«нки:Учвбник для еьгшей школы /Кокотопое /Ахааемический проект
16 Философия.Учебник для XXI веке /Кан« /Погос
15 История жономимеосих учений /Бепоусов /Феникс
16 История философим.Учебннс для студентов ВУЗов /Коханоеоснй /Феккс
17 :История 5кс»ю«нки:Учвбник для еьгшей школы /Кокотопое /Ахааемический проект
16 Философия.Учебник для XXI веке /Кан« /Погос
Рис. 4-7. Окно работающей программы
Структура строки связи
Создаваемая тем или иным способом строка связи несет в себе множество (не менее двух) параметров, отделенных друг от друга точкой с запятой. Собственно в технологии dbGo.NET используются лишь четыре из них, остальные нужны для идентификации пользователя при доступе к серверным БД и для настройки некоторых параметров ODBC-драйверов.
Формирование строки связи
При щелчке на кнопке с многоточием в строке свойства Connectionstring компонента TAdoConnection или компонентов-наборов появляется окно, показанное на рис. 4.8.
У программиста есть две возможности: сослаться на специальный связной файл в первой строке или сформировать описание связи во второй. В первом случае можно использовать один и тот же(|)айл сразу для нескольких соединений, поэтому изменение файла отразится на многочисленных связях, причем, возможно, не в одной программе. Изменение содержимого во второй строке окна влияет только на соответствующий компонент-набор или только на те компоненты, которые будут ссылаться на данный связной компонент и только внутри одной программы.
Рис. 4.8. Диалоговое окно для формирования соединения с объектом ADOРис. 4.8. Диалоговое окно для формирования соединения с объектом ADO
Рис. 4.8. Диалоговое окно для формирования соединения с объектом ADO
Рис. 4.8. Диалоговое окно для формирования соединения с объектом ADO
Установка переключателя Use Data Link File делает доступно!! кнопку Browse, щелчок на которой открывает окно, показанное на рис. 4.9.
.■ Папка: j t^ Data Links闻 D6DEM8 I.■ Папка: j t^ Data Links闻 D6DEM8 IНедавние документыНедавние документыРабочий столРабочий столМой компьютерМой компьютер国一」…Сетевое :二 ЦмяфаШ : ск^ужти^ :Iwi Файлов;:国一」…Сетевое :二 ЦмяфаШ : ск^ужти^ :Iwi Файлов;:[歸[Файлы связи с даннь№Ш (H.udl)[歸[Файлы связи с даннь№Ш (H.udl)з机电d齒・з机电d齒・::Пт«РМГь::Пт«РМГь::三@0用а:::三@0用а:3"23"2
.■ Папка: j t^ Data Links
闻 D6DEM8 I
.■ Папка: j t^ Data Links
闻 D6DEM8 I
Недавние документы
Недавние документы
Рабочий стол
Рабочий стол
Мой компьютер
Мой компьютер
国一」…
Сетевое :二 ЦмяфаШ : ск^ужти^ :
Iwi Файлов;:
国一」…
Сетевое :二 ЦмяфаШ : ск^ужти^ :
Iwi Файлов;:
[歸
[Файлы связи с даннь№Ш (H.udl)
[歸
[Файлы связи с даннь№Ш (H.udl)
з机电d齒・
з机电d齒・
::Пт«РМГь
::Пт«РМГь
::三@0用а:
::三@0用а:
3
"2
3
"2
! Выберите файл связи с данными (Microsoft^ описывающий источник : .匸 деннь«« с которым нужно устаноай^ом^;.
Рис. 4.9. Окно выбора связного файла
Упаковка переключателя Use Connection String позволяет с помощью кнопки Build воспользоваться специальным диалоговым окном. Вначале рассмотрим диалого- Buii способ формирования связи.
Диалоговый способ формирования связи
Для дна-погового формирования связи установите переключатель Use Connection String и щелкните на кнопке Build. На экране появится диа.поговое окно с четырьмя
вкладками. Вкладка Поставщик данных (см. рис. 4.5) используется для выбора механизма, которьп! будет непосредственно взаимодействовать с данными, получая их от клиента и посылая их ему. Фактически в списке этой вкладки отображается состав провайдеров OLE DB, установленных на вашей машине. Выбор провайдера является определяющим фактором. Для разных типов данных должны использоваться только строго определенные провайдеры. Например, в фаил-серверных БД должен использоваться провайдер Microsoft OLE DB Provider for ODBC driver с: предварительной iiacrpoincoH соответствующего драйвера. Для работы с БД Access выбирается провайдер Microsoft Jet 4.0 OLE DB Provider. Если применяется сервер Oracle или MS SQL Server. БД работает совместно, соответственно, с провайдером Microsoft OLE DB Provider for Oracle пли Microsoft OLE DB Provider for SQL Server и т. д. Некоторые типы баз данных (например, БД InterBase iujii Informix SQL Server) не имеют провайдеров и поэтому (пока на будут созданы нужные провайдеры) не могут использоваться в технологии dbGo.NET. Поскольку большинство других связных параметров зависят от провайдера, содержимое трех других вкладок также определяется этим фактором Здесь описывается содержимое вкладок при выборе провайдера Microsoft OLE DB Provider for ODBC driver.
Вкладка Подключение определяет необходимые связные параметры для выбранного провайдера (рис. 4.10).
■: ;;'Псхтёвци^ данные Псшлюче#* | Дополнигесънс1:| Все j :
Для пежлочения пан»^ых ODBC укажите следукхцее:-
: \ 1. Источник данных::■:“
I.佇 1^спо;и)Эйварз1<4Я источника данных :
:[Paradox files^^' 三「О^цо^игь |”:
:Т Исгюльэоет строку подключения :
•二:二二◎亨今)с「-」 …俘£:•::..
Я^ Д^вшаесерв^ис^
;чПользоввгвль: J
Пар* : I:
j : Г Пд@дй пароль :「Р«орш^гь со^анение перстя
3- Введите начальный кеггалап
I3 ,
Рис. 4.10. Вкладка Подключение окна настройки связи с провайдеромMicrosoft OLE DB Provider for ODBC driver
220 Глава 4 • Технология dbGo.NET
Раскройте список Использовать имя источника данных и выберите в нем нужный источник данных. В качестве дополнительной информации на этой вкладке указываются входное имя пользователя и пароль. Для простейшего варианта связи с Microsoft OLE DB Provider for ODBC driver этих параметров вполне достаточно, поэтому с помощью кнопки Проверить подключение можно протестировать созданную связь. Для других провайдеров может потребоваться задать ряд дополнительных параметров, например имя используемой базы данных, входное имя и пароль для доступа к серверу БД и т. п.
Вкладка Дополнительно позволяет задать некоторые дополнительные свойства связи (рис. 4.11).
務蹲窗務蹲窗
務蹲窗
務蹲窗
Пм^амци^дмъм] Падкл1оче^ Дополнительно | Все |
лПар«иепрысеп<
内尸产俨,;Г tHJ*ft 3::-К/
:■■ Apifoe ■ ■■:"
8Mмя 8khr前ня подм»?чеяия 伍 секундах):
;Црам доступе;Црам доступеp0p0Read Rsc^Vnte Share Deny None Share Deny ReadRead Rsc^Vnte Share Deny None Share Deny Read"讖"讖□ Sh«e Der^i Wiite 口 Share Exclusive□ Sh«e Der^i Wiite 口 Share ExclusiveОтменаОтмена
;Црам доступе
;Црам доступе
p0
p0
Read Rsc^Vnte Share Deny None Share Deny Read
Read Rsc^Vnte Share Deny None Share Deny Read
"讖
"讖
□ Sh«e Der^i Wiite 口 Share Exclusive
□ Sh«e Der^i Wiite 口 Share Exclusive
Отмена
Отмена
Рис. 4.11. Вкладка Дополнительно окна настройки связи с провайдеромMicrosoft OLE DB Provider for ODBC driver
Для большей части провайдеров на этой вкладке доступны только флажки в списке Права доступа, определяющие права доступа к данным, и строка Время ожидания подключения, с помощью которой можно задать максимальную паузу ири установлении связи между провайдером и клиентом. С помощью флажков можно задать любую комбинацию режимов доступа:
Read — только чтение;
ReadWrite — чтение и запись;
Share Deny None — режим совместной работы невозможен;
Share Deny Read — нельзя совместно использовать данные, открытые в режиме чтения;
Share Deny Write — нельзя совместно использовать данные, открытые в режиме записи;
Share Exclusive — нельзя совместно использовать данные» открытые в режиме чтения и/или записи;
Write — только запись.
На вкладке Все приводятся все параметры связи — как заданные явно, так и назначенные по умолчанию (рис. 4.12). Щелкнув на кнопке Изменить значение, можно отредактировать значение любого параметра.
Hoctmiumcддйшх j Подключение | ^Дополнигельма 出в |
:;Инициа/мжий свойств для этого тила данньвс. Для ■■: 疝%绅ниябучения выберите свойство инфкь^гс кнопку.
Extended Propwties
GenerN Timeout
1加闾 Catalog
Locale Identrfier1049
Location
Mode
Passvxnd
Petsisl. Security Info False
User ID
Of ] (Ьмена :[: Спра^б?
Рис. 4.12. Вкладка Все окна настройки связи с провайдеромMicrosoft OLE DB Provider for ODBC driver
После щелчка на кнопке ОК диалоговое окно формирования параметров связи будет закрыто, и в нижнеп строке окна формирования соединения с объектом ADO появится соответствующий текст (см. рис. 4.8).
Формирование связного файла
Создать и отредактировать связной файл можно с помощь Проводника Windows (в нерусггфинированной версии — Windows Explorer). Вызовите Проводник, выберите панку, в которой будет размещаться связной файл, щелкните на
содержимом папки правой кнопкой мыши и в подменю Создать контекстного меню выберите команду Microsoft Data Link. К сожалению, в ряде систем эта команда недоступна (у меня, например, ее нет в Windows 2000/ХР). В этом случае можно порекомендовать не совсем корректный прием. Дело в том, что для демонстрационных целей с Delphi поставляется связной файл DBDEMOS.udl, который по умолчанию располагается в папке Program Files\Common Files\System\ole db\Data Links. Этот файл рассчитан на связь с демонстрационной БД DBDEMOS.mdb, работающей с СУБД Access. Скопируйте этот файл в нужную папку, переименуйте и отредактируйте так, чтобы он описывал связь с вашей БД. Для редактирования связного файла используется окно, показанное на рис. 4.9: дважды щелкните на файле — и вы увидите диалоговое окно с уже знакомыми вкладками (см. рис. 4.10).
ПРИМЕЧАНИЕ
Поскольку dbGo.NET активно использует технологию ActiveX, обмен текстовыми данными с объектами dbGo.NET возможен только в формате wideString (но два байта на каждый символ) — именно в таком формате создан связной файл DBDEMOS.udl.
Особенности использования компонентов dbGo.NET
Базовые объекты ADO
При описании особенностей технологии dbGo.NET я часто буду употреблять термины базовые объекты ADO и компоненты dbGoNET. Базовые объекты произведены корпорацией Microsoft и входят в комплект поставки Delphi.
Базовых объектов семь: Connection, Recordset, Command, Parameter, Field, Error и Property. Компоненты dbGo.NET в палитре компонентов Delphi представляют собой надстройки над базовыми объектами, экспонируя большинство их свойств, методов и событий в привычном для Delphi виде.
Базовые объекты обычно сопровождаются коллекциями связанных с ними объектов. Например, с объектом Connection может быть связан один или несколько объектов Error, фиксирующих ошибки установления связи; с объектом Recordset — набор объектов Field, каждый из которых определяет единственное поле результирующего набора данных; с объектом Command — один или несколько объектов Parameter, конкретизирующих выполнение метода Execute этого объекта, и коллекция объектов Error и т. д. В связи с этим говорят об основных (Connection^ Recordset, Command) и вспомогательных (Error, Field, Parameter, Property) объектах ADO.
Объект Connection предназначен для установления соединения с данными — это его главная задача. Кроме того, объект поддерживает механизм транзакций. На него может ссылаться произвольное количество объектов Command it Recordset. В этом случае Connection управляет транзакциями этих объектов* С объектом связан набор объектов Error, в котором фиксируются все ошибки, связанные с работой объекта Connection.
Объект Recordset представляет собой текущий набор данных. Он может быть получен только после выполнения метода Execute какого-либо объекта Command. С объектом автоматически связывается набор объектов Field, в которых описываются все поля НД. Объект Recordset способен хранить нужные записи, перемещаться по ним, добавлять, удалять и редактировать записи как в обычном (при одновременном изменении физических ТБД), так и в ла- кетном режиме (то есть при кэшировании данных). При создании объекта автоматически создается и связанный с ним курсор, обеспечивающий просмотр, редактирование w изменение записей.
С помощью объекта Command пользователь может выполнить над данными любую SQL-команду. С ним может быть связан набор объектов Parameter, в котором описываются соответствующие параметры, необходимые для выполнения запроса. Характерной особенностью объекта является возможность асинхронного выполнения связанной с ним команды. При обнаружении ошибки с объектом связывается своя коллекция объектов Error.
ПРИМЕЧАНИЕ
Объекту Command соответствуют целых четыре компонента Delphi: TADOCommand, TADOQuery, TADOTable и TADOStoredProc. Сделано это в целях унификации с компонентами категории BDE, хотя даже н этом случае возможности TADOCoiranand нельзя считать уникальными ио сравнению с возможностями TADOQuery и наоборот.
Объект Parameter определяет едкнетвенный параметр, который будет использоваться при выполнении метода Execute объекта Command, — его (параметра) тип, размер и способ применения (входной, выходной, входной и выходной или только для чтения). При необходимости с объектом Command можно связать коллекцию объектов Parameter для указания множества параметров.
Коллекция объектов Error хранит все ошибки, связанные с работой остальных объектов, и прежде всего объектов Connection, Command и Recordset.
Объект Field хранит всю необходимую информацию об одном поле НД. Поскольку обычно НД содержит несколько полей, с объектом Recordset связана коллекция объектрв Field. С любым полем Field можно связать произвольную коллекцию объектов Property, определяющих индивидуальные характеристики поля.
Объект Property может быть связан с любым другим объектом ADO, кроме объектов Connection и Error. Он может хранить как статические, так и динамические свойства. Статических (то есть заранее заданных) свойств у объекта всего четыре: Name, Type, Value, Attributes. Остальные свойства динамические и создаются в ходе выполнения программы. В объекте Property задаются некоторые индивидуальные характеристики связанного с ним объекта ADO.
Связной компонент TADOConnection
Компонент TADOConnect ion осуществляет связь остальных компонентов с данными. Для этих целей у него имеется свойство Connectionstring. После того
как с помощью этого свойства связь с данными установлена, на компонент могут ссылаться другие компоненты dbGo.NET, разделяя установленную им связь.
Однако роль компонента TADOConnec t i on может быть гораздо шире, чем просто концентрация соединений. С помощью своих свойств и методов он может осуществлять точную настройку соединения, обеспечивать необходимый уровень изоляции транзакций» управлять транзакциями и т. д.
Для установления связи нужно с помощью свойства Conncetionstring сформировать связные параметры и затем установить значение True в свойство Active или вызвать метод Open. Для разрыва связи выполняется метод Close компонента или в его свойство Active устанавливается значение False.
Компонент содержит в свойстве ConnectionObj ect ссылку на базовый ADO- объект, с помощью которого и работает сам компонент. Это свойство открывает возможности детального управления связью, если, разумеется, программист хорошо знаком с техникой ADO,
В свойствах Commandcount и DataSetCount содержится количество соответствующих объектов, которые обслуживаются данным компонентом. В сочетании со свойствами Commands и DataSets программист может получить доступ к любому интересующему его объекту. Например:
vax
i: Integer;
begin
for i := 0 to ADOConnectionl.DataSetCount - 1 do
ADOConnectionl.DataSets[i].Open;
end;
С помощью методов GetProcedureNames и Ge t Tabi eName s можно получить список всех хранимых процедур и таблиц. Например:
AdoConnect i onl.Open;
AdoConnec t i on1.GetTableNames(ListBoxl.Items)
Важной особенностью компонента является возможность управления с его помощью транзакциями (подробнее о транзакциях см. главу 1). Для этого в состав компонента добавлены соответствующие методы и события.
С помощью метода BeginTrans стартует новая транзакция, методы CommitTrans и RollbackTrans подтверждают или откатывают транзакцию. Разрешается произвольная глубина вложенности транзакций, то есть после старта одной транзакции может немедленно стартовать следующая и т. д. Уровни разграничения транзакций (свойство IsolationLevel) несколько отличаются от аналогичных уровней BDE.NET и в некоторых случаях могут не поддерживаться сервером БД. Транзакция, стартующая с помощью компонента TADOConect i on, разделяется всеми дру- шми связанными с ним компонентами. С помощью свойства InTransaction программа может определить, завершилась ли ранее начатая транзакция.
В следующем разделе работа с транзакциями в технологии dbGo.NET рассматривается более подробно.
Работа с транзакциями
Как уже отмечалось, механизм транзакций существенно защищает целостность и непротиворечивость данных в условиях многопользовательской работы. Этот механизм практически бесполезен, если используется файл-серверная БД. Наоборот, все современные серверы поддерживают транзакции, поэтому для иллюстрации особенностей работы с транзакциями в технологии dbGo.NET нам понадобится клиент-серверная БД. Использовавшаяся в предыдущих главах БД《Книголюб» имеется в варианте для сервера InterBase, однако в рамках технологии этот сервер не поддерживается.
Вспомним, что с Delphi 2005 поставляется мощный сервер MS SQL Server. Я прекрасно понимаю — чтобы детально описать его, потребуется отдельная толстая книга. Тем не менее далее описываются некоторые приемы работы с этим сервером. Возможно, этого окажется достаточно для того, чтобы вы смогли самостоятельно создать и наполнить данными собственную БД для этого сервера.
Итак, прежде всего убедитесь в том, что сервер запущен: в системной области панели задач {aystray) должен быть значок с зеленым треугольником, всплывающая подсказка которого содержит такую строку:
Runnung - \\CompName 一 MSSQLSBrvs匚
Здесь CompName — имя вашего компьютера.
Если значок вместо зеленого треугольника содержит красный квадратик (в этом случае всплывающая подсказка начинается словом Stopping), щелкните на нем правой кнопкой мыши н выберите в контекстном меню команду MSSQLServer — Start. Вся дальнейшая работа нлет с утилитой SQL Server Enterprise Manager.
Щелкните на кнопке Пуск н в левой части появившегося меню выберите команду Enterprise Manager, открывающую окно утилиты SQL Server Enterprise Manager (рис, 4.13).
X Зак. 449
Рис. 4.13. Окно утилиты SQL Server Enterprise Manager
ПРИМЕЧАНИЕ
При установке сервера в главное меню Windows обычно записывается ссылка на утилиту SQL Server Enterprise Manager. Если 3Toii ссылки нет, ищите ее в группе Все программы ► MS SQL Server.
В левой части окна последовательно раскройте узлы MS SQL Servers ► SQL Server Group ► (local) (Windows NT) ► Databases. Вы увидите стандартные БД, поставляемые вместе с сервером (рис, 4,14).
Рис 4.14. Стандартные базы данных
Большая часть этих БД служебные, но две — Northwind и pubs — демонстрационные. В главном меню утилиты выберите команду Действие ► New Database, открывающую окно определения новой БД (рис. 4.15).
В этом окне необходимо определить имя создаваемой БД. Введите в поле Name имя DebCred и щелкните на кнопке ОК.
В левом списке появится имя вновь созданной БД, Раскройте связанный с ней узел, щелкните правой кнопкой мыши на пункте Tables, после чего в контекстном меню выберите команду New Table для определения полей таблицы (рис. 4.16). Новая таблица будет содержать два поля: NCount типа int и Summa типа money. В нервом ноле будем хранить номера счетов, во втором — суммы на этих счетах. Заполните столбцы таблицы так, как показано на рис. 4.16, закройте окно щелчком на кнопке закрытия и в новом диалоговом окне щелкните на кнопке Да, чтобы сохранить новую таблицу. В следующем окне введите имя таблицы Deb и закройте окно щелчком на кнопке ОК.
Точно таким же образом создайте л сохраните на диске таблицу с кредиторскими счетами Cred.
^bebCrtd"…"^bebCrtd"…"SS@信11 Data Filej ] T lansaction Log j
^bebCrtd"…"
^bebCrtd"…"
f..。№触5 •隔E启
:Ddtabsse ■
:Status:
/Owner:' ■
Datecre^ledi.:
::$i風?「
■ ;:'<SpaceeveWbte;: ■ / ' ■
; Mumbe< dUsw« .
.:;Laet datable Ьасклф:
" Last lran$acbon log backup
■M«hler>ance plarr .
(Unknown):.:[Unknown): ■ (Unknown) (Unknown) (Unknown!:(Unknown):.:[Unknown): ■ (Unknown) (Unknown) (Unknown!:NoneNoneNoneNoneHServet default]HServet default]Отмена j СправкаОтмена j Справкаj .CoUtionhatfnei :
(Unknown)
:.:[Unknown): ■ (Unknown) (Unknown) (Unknown!:
(Unknown)
:.:[Unknown): ■ (Unknown) (Unknown) (Unknown!:
None
None
None
None
HServet default]
HServet default]
Отмена j Справка
Отмена j Справка
228 Глава 4 • Технология dbGo.NET
Для наполнения вновь созданных таблиц данными щелкните на пункте Tables в левом списке, а затем — правой кнопкой мыши в правом окне на имени таблицы Cred. В контекстном меню выберите команду Open Table ► Return all rows. Заполните таблицу так, как показано на рис. 4.17, п закройте окно. Такими же данными заполните таблицу Deb.
ROHCODb 20Ю ■■ УКМВКЙROHCODb 20Ю ■■ УКМВКЙ好一三車豆占声?诲歹外г *屛匕好一三車豆占声?诲歹外г *屛匕NCount; •…「“ JSumma :NCount; •…「“ JSumma :2 32 3100020003000100020003000脸 t 3*沁何 kuQ/0《kf尊笛ft S<3i. SfiiW^ASiA. ScrwrGnjUp'lffGCiil} ^Wlndc^i NJ iU)etrtba^£^«ffeC(sJ\>;ib4o.脸 t 3*沁何 kuQ/0《kf尊笛ft S<3i. SfiiW^ASiA. ScrwrGnjUp'lffGCiil} ^Wlndc^i NJ iU)etrtba^£^«ffeC(sJ\>;ib4o.rwdFurrwdFur岗 svsindexes ^jysbdexteys 雪 sysmembers岗 svsindexes ^jysbdexteys 雪 sysmembersSystem System SystemSystem System System05.03,2005 10:20:47 05,03.2005 16:15:26 05.03,2005 17;52:4 5 06.08.2000 1:29;12 06.08.2000 1:29:12 06.06.2000 1:29:12 06.06.2000 1:29:12 06.08.2000 1:29:12 06.08.2000 1;29;12 06,08,2000 1:2 9.12 06,08.2000 1:29:12 06,08.2000 1:29:12 06.08.2000 1:29:12 06.08.20001:29:12 06.08,2000 1;29"205.03,2005 10:20:47 05,03.2005 16:15:26 05.03,2005 17;52:4 5 06.08.2000 1:29;12 06.08.2000 1:29:12 06.06.2000 1:29:12 06.06.2000 1:29:12 06.08.2000 1:29:12 06.08.2000 1;29;12 06,08,2000 1:2 9.12 06,08.2000 1:29:12 06,08.2000 1:29:12 06.08.2000 1:29:12 06.08.20001:29:12 06.08,2000 1;29"2
ROHCODb 20Ю ■■ УКМВКЙ
ROHCODb 20Ю ■■ УКМВКЙ
好一三車豆占声?诲歹外г *屛匕
好一三車豆占声?诲歹外г *屛匕
NCount; •…「“ JSumma :
NCount; •…「“ JSumma :
2 3
2 3
1000
2000
3000
1000
2000
3000
脸 t 3*沁何 kuQ/0《kf尊笛ft S<3i. SfiiW^ASiA. ScrwrGnjUp'lffGCiil} ^Wlndc^i NJ iU)etrtba^£^«ffeC(sJ\>;ib4o.
脸 t 3*沁何 kuQ/0《kf尊笛ft S<3i. SfiiW^ASiA. ScrwrGnjUp'lffGCiil} ^Wlndc^i NJ iU)etrtba^£^«ffeC(sJ\>;ib4o.
rwdFur
rwdFur
岗 svsindexes ^jysbdexteys 雪 sysmembers
岗 svsindexes ^jysbdexteys 雪 sysmembers
System System System
System System System
05.03,2005 10:20:47 05,03.2005 16:15:26 05.03,2005 17;52:4 5 06.08.2000 1:29;12 06.08.2000 1:29:12 06.06.2000 1:29:12 06.06.2000 1:29:12 06.08.2000 1:29:12 06.08.2000 1;29;12 06,08,2000 1:2 9.12 06,08.2000 1:29:12 06,08.2000 1:29:12 06.08.2000 1:29:12 06.08.20001:29:12 06.08,2000 1;29"2
05.03,2005 10:20:47 05,03.2005 16:15:26 05.03,2005 17;52:4 5 06.08.2000 1:29;12 06.08.2000 1:29:12 06.06.2000 1:29:12 06.06.2000 1:29:12 06.08.2000 1:29:12 06.08.2000 1;29;12 06,08,2000 1:2 9.12 06,08.2000 1:29:12 06,08.2000 1:29:12 06.08.2000 1:29:12 06.08.20001:29:12 06.08,2000 1;29"2
Рис. 4.17. Наполнение таблицы данными
Осталось определить имя пользователя н пароль для новой БД. Закройте узел Databases в левом списке, раскройте узел Security и щелкните на пункте Logins. В правом окне появятся два предопределенных пользователя: Администраторы и sa. Воспользуемся последним: дважды щелкните на нем и в новом окне введите пароль 123 (поле Password), в списке Database выберите БД DebCred, а в списке Language — пункт Russian, как показано на рис. 4.18 (последнее делать необязательно, так как наша БД не содержит таблиц с кириллическими полями).
На этом работа с утилитой SQL Server Enterprise Manager заканчивается — закройте окно утилиты.
Начните новый VCL-проект (см. проект Ch04\TransDemo\TransDemo/dpr) и поместите на форму компонент TADOConnect i on (категория dbGo). В инспекторе объектов щелкните на кнопке с многоточием в строке свойства Connectionstring. В появившемся диалоговом окне щелкните на кнопке Build. В окне Свойства связи с данными (рис. 4.19) выберите провайдер Microsoft OLE DB Provider for SQL Server и щелкните на кнопке Далее.
На вкладке Подключение укажите имя пользователя sa, пароль 12 3, установите флажок Разрешить сохранение пароля, раскройте список Выберите базу данных на сервере и выберите БД DebCred (рис. 4.20),
Особенности использования компонентов dbGo.NET 229
Л:?^;.;:;Г,-yj<:S-<SЛ:?^;.;:;Г,-yj<:S-<S
Л:?^;.;:;Г,-yj<:S-<S
Л:?^;.;:;Г,-yj<:S-<S
G 三ij Лг,"”!:” •l Specif the &Uut knguege diabase fa thin bg*Qalabi匿jDebCredjjj:[T ок ]旧吧^ I p^^G 三ij Лг,"”!:” •l Specif the &Uut knguege diabase fa thin bg*Qalabi匿jDebCredjjj:[T ок ]旧吧^ I p^^Рис- 4.18. Имя пользователя и пароль для новой БДРис- 4.18. Имя пользователя и пароль для новой БД
G 三ij Лг,"”!:” •
l Specif the &Uut knguege diabase fa thin bg*
Qalabi匿jDebCredjjj
:[T ок ]旧吧^ I p^^
G 三ij Лг,"”!:” •
l Specif the &Uut knguege diabase fa thin bg*
Qalabi匿jDebCredjjj
:[T ок ]旧吧^ I p^^
Рис- 4.18. Имя пользователя и пароль для новой БД
Рис- 4.18. Имя пользователя и пароль для новой БД
Поставши<данных j Поаключенме) Дополнительно | Все/ 8 呼е0игеподк^очвеные 叫性挝:Поставши<данных j Поаключенме) Дополнительно | Все/ 8 呼е0игеподк^очвеные 叫性挝:ПЬсгаешики OLE DB •MeiiaCalalogDB OLE DB Piovider MediaCatalogMeigedDB OLE 00 Ptovidei MediaCalabgWebDB OLE D8 Piovider Microjoh ISAM 1 1 OLE DB Providw Miciosoft Jei 4.0 OLE DB ProvidetПЬсгаешики OLE DB •MeiiaCalalogDB OLE DB Piovider MediaCatalogMeigedDB OLE 00 Ptovidei MediaCalabgWebDB OLE D8 Piovider Microjoh ISAM 1 1 OLE DB Providw Miciosoft Jei 4.0 OLE DB Providet二二飞二二飞МюмоИ OLE DB Provider For Data Mining Services Miaosclt OLE DB Provider for DTS Packages MicrosoJt OLE DB Piovkter lor Indexing Service Microsoft OLE 00 Provider for Internet Publishing Microscrfl OLE DB Provider for ODBC Dfivers Microsoft OLE DB Piovidef for Olap 5eivice$ 8.0 Miciosofl OLE DB Piovidei tor Sade Micfosoft OLE DB Piovidef for Outlook SearchМюмоИ OLE DB Provider For Data Mining Services Miaosclt OLE DB Provider for DTS Packages MicrosoJt OLE DB Piovkter lor Indexing Service Microsoft OLE 00 Provider for Internet Publishing Microscrfl OLE DB Provider for ODBC Dfivers Microsoft OLE DB Piovidef for Olap 5eivice$ 8.0 Miciosofl OLE DB Piovidei tor Sade Micfosoft OLE DB Piovidef for Outlook SearchMicrosoft OLE DB Simple PiovidwMSDataShapeSQL Servei Replication OLE OB Provdef lor DTSMicrosoft OLE DB Simple PiovidwMSDataShapeSQL Servei Replication OLE OB Provdef lor DTS工^90 »工^90 »
Поставши<данных j Поаключенме) Дополнительно | Все
/ 8 呼е0игеподк^очвеные 叫性挝:
Поставши<данных j Поаключенме) Дополнительно | Все
/ 8 呼е0игеподк^очвеные 叫性挝:
ПЬсгаешики OLE DB •
MeiiaCalalogDB OLE DB Piovider MediaCatalogMeigedDB OLE 00 Ptovidei MediaCalabgWebDB OLE D8 Piovider Microjoh ISAM 1 1 OLE DB Providw Miciosoft Jei 4.0 OLE DB Providet
ПЬсгаешики OLE DB •
MeiiaCalalogDB OLE DB Piovider MediaCatalogMeigedDB OLE 00 Ptovidei MediaCalabgWebDB OLE D8 Piovider Microjoh ISAM 1 1 OLE DB Providw Miciosoft Jei 4.0 OLE DB Providet
二二飞
二二飞
МюмоИ OLE DB Provider For Data Mining Services Miaosclt OLE DB Provider for DTS Packages MicrosoJt OLE DB Piovkter lor Indexing Service Microsoft OLE 00 Provider for Internet Publishing Microscrfl OLE DB Provider for ODBC Dfivers Microsoft OLE DB Piovidef for Olap 5eivice$ 8.0 Miciosofl OLE DB Piovidei tor Sade Micfosoft OLE DB Piovidef for Outlook Search
МюмоИ OLE DB Provider For Data Mining Services Miaosclt OLE DB Provider for DTS Packages MicrosoJt OLE DB Piovkter lor Indexing Service Microsoft OLE 00 Provider for Internet Publishing Microscrfl OLE DB Provider for ODBC Dfivers Microsoft OLE DB Piovidef for Olap 5eivice$ 8.0 Miciosofl OLE DB Piovidei tor Sade Micfosoft OLE DB Piovidef for Outlook Search
Microsoft OLE DB Simple Piovidw
MSDataShape
SQL Servei Replication OLE OB Provdef lor DTS
Microsoft OLE DB Simple Piovidw
MSDataShape
SQL Servei Replication OLE OB Provdef lor DTS
工^90 »
工^90 »
QK: J: ОтменаQK: J: Отмена:Справка:Справка
QK: J: Отмена
QK: J: Отмена
:Справка
:Справка
Рис. 4.20. Установление параметров связи
Закрывайте все диалоговые окна, щелкая на кнопке ОК.
Поместите и свойство Connected связного компонента значение True — появится окно с предложением ввести пароль. Введите 123. Чтобы в дальнейшем окно запроса пароля не возникало, установите значение False в свойство LoginPrompt. Поместите на форму две таблицы ТADOTable (категория dbGo), два источника TDataSource (категория Data Access) и две сетки TDBGrid (категория Data Controls). В свойства Connection таблиц поместите ссылки на компонент ADOConnect ionl, свяжите одну из них с ТБД Deb, другую — с ТБД Cred и откройте таблицы. Назовите компоненты DEB и CRED (по именам связанных с ними ТБД). Создайте для них объекты-поля.
Свяжите один источник с компонентом DEB, второй — с CRED. Свяжите сетки с источниками. Сетки должны наполниться данными.
Поместите на форму компоненты TSpinEdit (категория Samples) и TButton (категория Standard). Вид формы к этому моменту показан на рис. 4.21.
Напишите такие обработчики событий OnAct ivate формы и OnClick кнопки:
procedure TForml.FormActivate(Sender: TObject);
// Передает фокус ввода s поле ^pinEdiU? в момент активизации формы begin
Spin Ed it: 1. SeuFocus;
end;
Рис. 4.21. Вид формы на этапе конструирования
procedure TForml. ButtonlClick (Sender : TObject.);
// Осуществляет перевод суммы под защитой транзакции var
Com: TADOCommand;
ComStr: String;
Sum: Integer;
begin
/ / Проверяем сумму перевода:
if SpinEditl.Value <=0 then
Exit;// Нет ввода шш сумма отрицательная
if SpinEditl.Value > DEBSumma.Value then
begin/ / Слишком большая сумма
SpinEditl.Value := Round(DEBSumma.Value);
SpinEditl.SetFocus;
Exit ;
end;
Sum := SpinEdicl.Value;
// Создаем объект TADOCommand;
Com :二 TADOCommand.Create(Self);
/ / Указываем ему связной компонент :
Com.Connection := AdoConnectionl;
// Формируем строку для снятия денег;
ComStr := Format('UPDATE DEB SET SUMMA=%d WHERE NCOUNT=%d'(
[Round(DEBSumma.Value - Sum), DEBNCount.Value]);
/ / Помещаем ее в ADOConunand:
Com.CommandText :二 ComStr;
// Формируем строку для на числения денег:
ComStr := Format ( 'UPDATE CRED SET SUMMA=%d WHERE N8UNT=*d\
[Round(CREDSumma.Value 十 Sum), CREDNCount.Value]); ADOConnectionl.BeginTrans;// Стартуем транзакцию
try
Com.Execute;// Снимаем деньги с дебиторского счета
Com.CommandText :二 ComStr; // Изменяем команду
Сеял.Execute;// Начисляем на кредиторский счет
AdoConnectionl.CommitTrans; // Подтверждаем транзакцию
except/ / Ошибка I
AdoConnectionl.RollbackTrans; // Откатываем транзакцию ShowMessage('No!');
end;
II Обновляем наборы данных:
DEB.Active := False;
DEB.Active := True;
CRED.Active := False;
CRED.Active := True;
// Готовим поле ввода:
SpinEditl.Value := 0;
SpinEditl.SetFocus;
end;
Компонент TADOCommand
Компонент TADOCortunand предназначен в основном для реализации SQL-запросов, не возвращающих никаких данных. К предложениям DDL (Data Definition Language — язык определения данных) относятся практически все запросы, которые не начинаются зарезервированным словом SELBCT.
ПРИМЕЧАНИЕ
Хотя конкретная реализация транслятора SQL зависит от выбранного провайдера, в целом компоненты dbGo.NET следуют промышленному стандарту SQL92.
Исполнение подобного рода запросов идет несколько иначе, чем запросов SELECT. В BDE-ориентированных компонентах TQuery для реализации запросов SBI*ECT используется метод Open (или свойство Active), в то время как DDL-запросы выполняются методом ExecSQL. В dbGo.NET для этих целей выделен специальный компонент. Хотя, как мы увидим дальше, он способен при некоторых обстоятельствах возвращать наборы данных, а компонент TADOQuery имеет в своем составе метод ExecSQL, позволяющий ему выполнять DDL-запросы. Иными славами, одни и те же запросы в рамках dbGo.NET можно выполнять с помощью двух разных компонентов, TADOCommand и TADOQuery, вернее, даже трех компо* нентов, поскольку рассмотренный ранее связной компонент TADOConnect i on также способен выполнять команду, например:
procedure TForml.ButtonlClicktSender: TObject);
begin
AdoConnectionl.Connectionstring :=
'Provider=Microsoft.Jet.OLEDB.4.0; Data Source='+
'C:\Program Files\Common Files\Borland Shared\DATA\dbdemos,mdb*; AdoConnectionl.Connected := True;
AdoDataSetl.Recordset :=
AdoConnectionl.Execute!'SELECT * FROM CUSTOMER') end;
Особенности использования компонентов dbGo.NET 233
Текст исполняемой команды хранится в свойстве CommandText компонента. Компонент способен за один прием исполнять одну и только одну команду. Особенностью компонента TADOCommand является специализированный тексто- ный редактор, с помощью которого можно сформировать команду (рис. 4.22). Этот редактор вызывается щелчком на кнопке с многоточием в строке свойства CommandText инспектора объектов.
SELECT * FROM BOOKSSELECT * FROM BOOKSFIRMSMoves NAKLS PAYMENTSFIRMSMoves NAKLS PAYMENTS
SELECT * FROM BOOKS
SELECT * FROM BOOKS
FIRMS
Moves NAKLS PAYMENTS
FIRMS
Moves NAKLS PAYMENTS
取編,J;取編,J;BookIDBAuthor BPubfch BYear BPages BISBN BStandBookIDBAuthor BPubfch BYear BPages BISBN BStand
取編,J;
取編,J;
BookID
BAuthor BPubfch BYear BPages BISBN BStand
BookID
BAuthor BPubfch BYear BPages BISBN BStand
id Nd to %Lid Nd to %L
id Nd to %L
id Nd to %L
Рис. 4.22. Редактор свойства CommandText компонента TADOCommand
Все окно редактора разделено на три части. В левой верхней части отображается список таблиц БД, с которой связан компонент, в нижней левой — список полей для выделенной таблицы, всю остальную часть занимает собственно текстовый редактор. Справочные окна в левой части лишь облегчают набор текста, который в основном формируется вручную в правом поле. Например, необходимо вручную ввести слово SELECT, выделить в нижнем списке строку * и щелкнуть на кнопке Add Field to SQL. Затем вновь вручную вводится слово FROM, в верхнем списке выделяется таблица BOOKS, выполняется щелчок на кнопке Add Table to SQL и т.几
Как уже упоминалось, компонент TADOCommand способен возвращать записи. Для атого в него включены целых три реализации метода Execute, две из которых как раз и предназначены для создания наборов записей. Использовать возвращаемый НД можно с помощью компонента-посредника TADODataSet по следующей схеме:
AdoDataSetl. P.ecordSet : = AdoCommandl. Execute;
Для создания НД множество Executeoptions не должно содержать значения eoExecuteNoRecords.
Свойства, методы и события компонентов-наборов
Общие с компонентами BDE свойства
В состав компонентов dbGo.NET входят 4 компонента-набора: TADODataSet,
TADOTable, TADOQuery и TADOStoredProc. Как и аналогичные BDE-ориен
тированные компоненты, они имеют общего родителя — абстрактный класс
Рис 4.23. Фрагмент иерархии наследования компонентов-наборовРис 4.23. Фрагмент иерархии наследования компонентов-наборовTDataSet, следовательно, большую часть своих методов, свойств и событий они унаследовали от этого класса и разделяют их со своими BDE-аналогами (рис. 4.23).
Рис 4.23. Фрагмент иерархии наследования компонентов-наборов
Рис 4.23. Фрагмент иерархии наследования компонентов-наборов
Например, для доступа к данным компоненты dbGo.NET используют те же свойства, что и компоненты BDE.NET. Следующие операторы аналогичны по функциональности (предполагается, что поле Company — второе по счету
в массиве Fields и для него создан объект AdoTablelCompany):
Caption := AdoTablel.Fieldvalues['Company *];
Caption := AdoTablel['Company *];
Caption := AdoTablel.FieldByName('Company').AsString;
Caption := AdoTablel.Fields[1]-Value;
Caption := AdoTablelCompany.AsString;
Разумеется, к моменту использования этих операторов компонент AdoTablel должен быть связан через провайдер с физической таблицей БД и открыт.
Модификация данных и навигация по ним также не отличаются от описанных ранее:
AdoTablel.Edit;
AdoTablelCoinpany.Value : = 1 Новая компания•;
AdoTablel.Post;
Или:
AdoTablel.Open;
while not AdoTablei.EOF do
begin
AdoTablel.Next
end;
Наборы dbGo.NET визуализируют данные так же, как ВВЕ.ЫЕТ-ориентирован- ные наборы: через компоненты-посредники TDataSource (категория Data Access) и компоненты категории Data Controls палитры компонентов Delphi.
Специфические свойства
Наборы dbGo.NET имеют непосредственного родителя TCustomAdoDataSet, от которого они унаследовали многие специфические свойства. Здесь дается общий обзор особенностей наборов dbGo.NET, а также описываются наиболее важные свойства, методы н события класса TCustomADODataSet.
Прежде всего — это свойства Connection и ConnectionString, с помощью которых набор dbGO.NET может самостоятельно связаться с источником данных, С помощью свойства BlockReadSize программист может организовать такой режим работы, когда навигация по данным не приводит к изменениям в связанных с набором визуализирующих компонентах. Для этого в свойстве BlockReadSize следует поместить любое ненулевое значение. В этом случае свойство State автоматически примет значение dsBlockRead, и навигация по НД пойдет значительно быстрее. Чтобы отменить этот режим, достаточно поместить в свойство BlockReadSize значение 0.
В отличие от BDE.NET, наборы dbGo.NET могут создавать курсоры двух типов: на стороне клиента и на стороне сервера (свойство Cursorconnection). В сочетании со свойством CursorType это дает программисту гибкий инструмент влияния на скоростные качества передачи данных и разграничение доступа к данным.
С помощью свойства EnabledBCD программист может заменить вещественные данные форматом двоично-десятичных данных (BCD). Этот формат позволяет избежать ошибок округления вещественных чисел.
Новым по сравнению с BDE.NET-ориентированными компонентами является также свойство LockType, позволяющее повысить скорость работы в многопользовательской среде за счет учета специфики БД.
С помощью свойства Marshaloptions можно несколько снизить нагрузку на сеть при создании курсора на клиентской машине.
Важным отличием является то, что компоненты dbGo.NET имеют свойство Recordset, содержащее ссылку на одноименный базовый объект. Если программист хорошо знаком с базовыми объектами ADO, он может напрямую обратиться к этому свойству для более гибкого доступа к данным.
Компоненты dbGo.NET способны работать с кэшированными данными, но делают это по-своему. Во-первых, в терминологии dbGo.NET вместо термина «кэширование данных» используется понятие «пакетная обработка данных» f после завершения которой все сделанные в пакете изменения либо подтверждаются, либо отвергаются. Для работы в пакетном режиме набор dbGo.NET должен:
в свойстве CursorType содержать значение ctKeySet, заданное по умолчанию, или значение ctstatic;
в свойстве LockType содержать значение 1 tBatchOpt imist ic.
Кроме того, сами данные должны быть получены с помощью SQL-запроса SELECT.
Вот как, например» готовится компонент TADODataSet к работе в пакетном режиме:
with ADODataSetl do
begin
CursorLocation := clUseServer;
CursorType := ctKeyset;
LockType := ltBatchOptimistic;
CommandType :二 cmdText;
CommandText :二'SELECT * FROM Books';
Open;
end;
Замечу, что, поскольку компонент TADOTable не имеет свойств CommandType и CommandText, его перевод в режим пакетной обработки данных имеет свою специфику:
AdoTablel.LockType := ItBatchOptimistik;
AdoTablel.Open;
В пакетном режиме можно по этой же схеме выполнять кэшированные изменения в хранимых процедурах, которые возвращают набор записей:
AdoStoredProcl.ProcedureName := 'MyBatchQuery *;
AdoStoredProcl.LockType := ltBatchOptimistic;
AdoStoredProcl.Open;
После получения пакетного набора записей с помощью свойства Recordstatus можно проверить статус конкретной записи, а с помощью свойства FilterGroup — отфильтровать записи. Подтвердить изменения можно с помощью метода ир- dateBatch; прекратить режим пакетной обработки и отказаться от сделанных изменений — с помощью метода CancelBatch. При этом в передаваемых этим методам параметрах можно отменить или подтвердить изменения для всех или только для отфильтрованных записей.
Есть определенная специфика в механизме сортировки записей набора dbGo.NET. Для сортировки в свойство Sort помещают список полей сортировки, разделенных запятыми. Каждое поле может дополнительно снабжаться признаком ASCENDING (ASC) или DESCENDING(DESC)для указания, соответственно, восходящего или нисходящего порядка сортировки (если ни одно из этих слов не указано, реализуется восходящая сортировка), например:
ADOQueryl.Sort := 'LastName ASC, DateDue DESC';
Если в свойство Sort помещена пустая строка, записи не сортируются и предъявляются в том виде, в котором они получены из БД. Если для НД создан клиентский курсор и нет соответствующих индексов для сортировки, на клиентской машине создается временный индекс, который уничтожается при изменении свойства sort.
Методы класса TCustomADODataSet
Любопытной особенностью наборов dbGo.NET являются инкапсулированные в них методы SaveToFile и LoadFromFile. В dbGo.NET эти методы используются
в качестве одного из возможных механизмов обмена данными между разными компьютерами, а также для отложенной обработки данных. Перед вызовами методов набор dbGo.NET должен быть закрыт. После успепшого вызова LoadFromFile набор автоматически открывается в том состоянии, в котором он был сохранен методом SaveToFile.
Наборы dbGo.NET можно сортировать по закладкам (метод Fi 11 erOnBookmarks). Например:
procedure TForml* ButtonlClick(Sender: TObject);
var
BM1, BM2: TBookmarkStr;
begin
with ADODataSetl do
begin
BM1 :二 Bookmark;
MoveBy(3);
BM2 := Bookmark;
FiIterOnBookmarks([BMl, BM2]);
end; end;
Для работы в многопользовательском режиме может оказаться полезным метод Clone, с помощью которого уже созданный НД дублируется в вызывающий. Например:
AdoTablel .Open;// Создан исходный НД
AdoTable2.Clone(AdoTablel, ltReadOnly); // Создан дубликат в ВД
// AdoTable2
Для наборов dbGo.NET определен метод Requery, с помощью которого программист может обновить НД. Его действие фактически эквивалентно последовательному вызову методов Close и Open. Особенностью является то обстоятельство, что влияющие на НД свойства, такие как CursorLocation, CursotType, LockTable и т. п” остаются неизменными, в то время как в промежутке между использованием методов Close и Open эти свойства можно изменить и тем самым повлиять на результирующий НД.
Весьма необычным является метод Seek, осуществляющий поиск записи по заданному значению (значениям) ключевого поля (полей). В принципе, он реализует те же действия, что и метод Locate, но отличается от него несколькими важными особенностями. Во-первых, для Locate ие имеет значения, индексировано ли поле (поля), по которому (которым) ищутся записи. В то же время Seek ищет только по индексированным нолям, которые к тому же должны быть указаны в свойстве IndexNames или IndexFields. Далее, для Locate курсор не перемещается, если поиск неудачен, для seek — перемещается всегда в зависимости от указанного параметра SeekOption (если запись не найдена, курсор перемещается в начало НД, в его конецг в место непосредственно перед искомой записью или сразу за ней). И наконец, Seek не может вести поиск с игнорированием возможной разницы в регистре букв или по частичному совпадению поисковых
значений. К сожалению, многие провайдеры OLE DB не допускают установки значений свойства indexNames или IndexFields к, таким образом, не поддерживают метод Seek.
С помощью метода Supports можно проверить различные характеристики набора, в частности, поддерживает ли он метод Seek:
AdoTablel.Open;
i£ Supports([coSeek]) then
AdoTablel.Seek(90001,soAfterEQ) else
i£ Supports([coLocate]) then AdoTablel.Locate(*Number*,90001,[]);
События класса TCustomADODataSet
Некоторые события используют следующие типы данных, определяющие статус и смысл события:
type TEventStatus = (esOK, esErrorsOccured, esCantDeny, esCancel, esUnwantedEvent);
Здесь:
e esOK — нет ошибок;
esErrorsOccured — событие вызвало ошибки;
е esCantDeny — ожидаемую связь нельзя разорвать;
е esCancel — ожидаемую связь можно разорвать до ее активизации;
е е sUnwant edEvent — блокирует связанные события.
type TEventReason = (erAddNew, erDelete, erUpdate, erUndoUpdate, erUndoAddNew, erUndoDelete, erRequery, erResynch, erClose, erMove, erFirstChange, erMoveFirst, erMoveNext, erMovePrevious, erMoveLast);
Здесь:
erAddNew — добавлена запись;
e erDelete — удалена запись;
e erUpdate — запись изменена;
e erUndoUpdate — произошел откат изменений записи;
е erUndoAddNew — произошел откат вставки записи; '
е erUndoDelete — произошел откат удаления записи;
е erRequery — к НД был применен метод Requere;
е erResynch — к НД был применен метод Re sync;
erClose — НД был закрыт;
е erMove — курсор сместился к другой записи;
erFirstChange — произошло первое изменение НД;
erMoveFirst — курсор сместился к первой записи;
erMoveNext — курсор сместился к следующей записи;
erMovePrevious — курсор сместился к предыдущей записи;
erMoveLast — курсор сместился к последней записи.
Особенностью события OnEndOfRecordset является то, что оно предшествует событиям BeforeScroll и AfterScroll. В обработчике события нельзя проверить конец НД с помощью функции EOF, так как сам НД может быть частично не наполнен, если наполнение его записями идет в асинхронном режиме.
Обработчик события OnFetchProgressEvent обычно используется при длительном обращении к БД в асинхронном режиме для индикации процесса. Например:
procedure TForml.ADODataSetlFetchProgress(DataSet:
TCustomADODataSet; Progress, MaxProgress: Integer; var Eventstatus: TEventStatus);
begin
Caption := 'Процент выполнения: ' +
IntToStr(Trunc(Progress / MaxProgress * 100)) + '%1; Application.ProcessMessages;
end;
Компонент TADODataSet
Компонент TADODataSet обеспечивает доступ к одной или нескольким таблицам БД с помощью запроса типа SELECT. Компонент рассчитан на возвращение набора данных, поэтому его нельзя использовать для выполнения подмножества DDL-операторов. (В компоненте есть свойство CommandText, однако в него можно поместить только оператор SELECT. Для выполнения DDL-предложений языка SQL можно использовать метод Execute компонента TADOCommand или метод ExecSQL компонента TADOQuery.)
В отличие от компонента TADOTable, компонент TMODataSet может обращаться не только к одной, но сразу к нескольким таблицам. На рис. 4.24, например, показан результат такого запроса к двум таблицам, выполненного с помощью компонента ADODataSet.
^ч1
kompany」
Maua) Dh/e ShoppeI0L07J988 …
1221;Kauaf Dive Shoppe46,12.1994
1221 : Kauai Dh/e Shoppe
24.(B.1993
5
1221 Kauai Dh/e Shoppe
1221 Kauai Dh/e Shoppe
1221 Kauai DNe Shoppe
1231 Unisco
12315 Unisco
1231; Unisco
上i
26m华, 16.12.1994
28.02,1989
15.04.1989:
成U6]®L園
Рии 4.24. Связывание двух таблиц по полю CustNo
Текст запроса:
SELECT
c.CustNo, с.company# o.SaleDate
PROH
customer c, orders о
WHERE
о.CustNo=c.CustNo
Компонент TADODataSet — единственный компонент-набор, с помощью которого можно установить связь с удаленным источником данных TRDSConnact ion при создании трехзвенной архитектуры. Для этого у него определено следующее свойство:
property RDSConnection: TRDSConnection;
Если компонент связан с единственной таблицей, можно воспользоваться его методом Get IndexNames, чтобы получить список всех имен табличных индексов. Например:
AdoDataSetl.GetlndexNames(Memol.Lines);
Остальные свойства, методы и события компонент наследует от своих предков TCustomAdoDataSet и TDataSet.
Компонент TADOTable
Компонент TADOTable является прямым аналогом популярного компонента ТТаЫе технологии BDE.NET. Так же как ТТаЫе, он способен получать и обслуживать НД, состоящий из записей единственной физической таблицы БД, имя которой содержит его свойство ТаЫeName. Являясь, как и все остальные компоненты-наборы, надстройкой к базовому объекту Command, компонент TADOTable имеет свойство CommandText, которое недоступно программисту. Значение этого свойства у него формируется автоматически по имени связанной таблицы:
Command.Commandstring := •SELECT * FROM TableName';
Здесь TableName — имя связанной таблицы.
Это, однако, не мешает компоненту работать в режиме кэшированных изменений (в режиме пакетной обработки): свойство связанного с ним базового объекта CommandType у него всегда имеет значение cmdText, так что остается изменить лишь единственное свойство LockType (свойство CursorType у компонента автоматически имеет значение ctKeySet):
AdoTablel.LockType := ItBatchOptimistic;
AdoTablel.Open;
После этого компонент готов к режиму пакетной обработки.
Компонент TADOQuery
В отличие от компонента TADOComrnand, компонент TADOQuery преимущественно предназначен для получения набора записей из одной или нескольких таблиц БД. Фактически, он целиком повторяет функциональноаъ компонента TQuery, так как в него включен специфический метод ExecSQL, с помощью которого компонент может выполнять DDL-предложения языка SQL. Сам запрос формируется в свойстве SQL.
Единственным отличием от аналога технологии BDE.NET является следующее свойство, с помощью которого программист может узнать или указать максимальное количество обновлении, которое сделано (или разрешается сделать) при выполнении запроса:
property RowsAffected: Integer;
Так же как TQuery, компонент TADOQuery имеет свойство Datasource, позволяющее передать параметры запроса от одного компонента к другому.
Технология dbExpress.NETТехнология dbExpress.NET
Технология dbExpress.NET
Технология dbExpress.NET
Впервые введенная в Delphi 6, технология dbExpress обеспечивает прямой доступ к некоторым промышленным серверам (InterBase, MySQL, Oracle, Informix, MS SQL Server ii DB2) без BDE пли другого подобного механизма. Она реализуется в виде набора соответствующих драйверов, учитывающих специфику серверов и обеспечивающих клиенту единый формат взаимоде11ствия с ними. В Delphi 2005 она приспособлена к работе на платформе .NET и называется dbExpress.NET. Характерной особенностью технологии является создаваемый ее средствами од- ноиаправленный курсор НД, что является следствием специфики получения данных от сервера: фактически любой сервер возвращает данные по записям в цикле FOR...SUSPEND (см. главу 7), а двунаправленный курсор создается средствами BDE.NET (dbGO.NET, ADO.NET) путем буферизации записей.
Однонаправленный курсор обеспечивает более быстрый доступ к данным и экономит ресурсы клиента, но вместе с тем в большой части практически важных случаев менее удобен. Ниже перечислены ограничения, предъявляемые им к действиям клиента:
Навигация по НД возможна только от первой записи к последней. В НД могут использоваться только навигационные методы First и Next. Попытка обращения к любому другому методу (Prior, Last) вызывает исключение.
НД не могут сортироваться или фильтроваться (точнее, сортировка и фильтрация реализуются SQL-запросом, а не свойствами Filter, Filtered, IndexName НД).
Клкснт не может визуализировать данные в сетке TDBGrid.
НД нс могут редактироваться (их свойство CanModi fy всегда имеет значение False).
К НД нельзя присоединить подстановочные поля.
В НД запрещено использовать закладки и поиск записей методами Locate и Lookup.
Наконец, по результатам выборки нельзя создать отчет главный—детальный, используя технологию Rave Reports.
К счастью, разработчики Delphi создали компонент TSimpleDataSet, который буферизует получаемые от сервера данные и создает двунаправленный курсор. Наличие этого компонента практически снимает все перечисленные ограничения и делает технологию dbExpress.NET не менее удобной, чем BDE.NET или dbGo.NET.
Пример простой программы
В следующем примере (проект ChO5\Nakls\dbExpress.dpr) средствами технологии dbExpress.NET воспроизводится уже рассматривавшийся в одноименных разделах предыдущих глав пример отображения связи главный—детальный таблиц Nakls и Moves из БД «Книголюб»:
Начните новый VCL-проекг и поместите на форму три панели Т?апе1 и вешку разбивки TSplitter: две нижние панели и вешку разбивки разместите в нижней части формы (Align - alBottom), а верхнюю — в оставшемся пространстве формы (Align - alClient).
Разместите на форме компонент TSQLConnection> два компонент TSimple- DataSet, компонент TSQLQuery (категория dbExpress палитры компонентов) и два компонента TDataSource (категория Data Access). Компоненты TSimpleDataSet предназначены для отображения данных, связанных отношением главный—детальный, компонент TSQLQuery — для удаления данных из детальной таблицы.
Настройте компонент SQLConnectionl на работу с БД IB_Bibl.gdb: в списке свойства ConnectionName выберите значение IBConnection — при этом автоматически настроятся некоторые другие свойства компонента; в свойство Loginprompt поместите значение False. Щелчком на кнопке с многоточием откройте окно редактора свойства Params (рис. 5.1) и в строке Database укажите путь доступа к файлу БД (путь должен включать имя хоста, на котором размещен сервер InterBase; если сервер запущен на вашем компьютере, путь должен выглядеть так: localhost : с : \bibldata\ib_bibl .gdb).
Настройте свойства компонента TSimpleDataSet 1 (он представляет собой главный НД): Name = Nakls, SQLConnection = SQLConnectionl. Раскройте сложное свойство DataSet, щелчком на кнопке свойства CommandText откройте окно редактора свойства и разместите в нем следующий запрос (рис. 5.2):
SELECT
NakllD, NDate, FName, TName, NSum, NPayedSum, NCoeff, NRetSum
FROH
Nakls, Firms, TypeNakl
WHERE
FirmID=NFirm AND TypeID=NType
ORDER BY
NakllD
244 Глава 5 • Технология dbExpress.NET244 Глава 5 • Технология dbExpress.NETKey DriverName Dat 必ase RoleName Iteer^Neme Password ServerCharSet SQlGect ErrorResourceFlle LocafeCode BlobSlzeKey DriverName Dat 必ase RoleName Iteer^Neme Password ServerCharSet SQlGect ErrorResourceFlle LocafeCode BlobSlze:kx制host; c;出bldM8tlb_blMgdb:RoleName:;sysdba: •masSrkey:kx制host; c;出bldM8tlb_blMgdb:RoleName:;sysdba: •masSrkey33Рис. 5.1. Окно редактора свойства ParamsРис. 5.1. Окно редактора свойства ParamsSOU:SOU:FIRMS MOVES NAKLS PAYMENTSFIRMS MOVES NAKLS PAYMENTSSELECTNaWlD, NDate, FMame, TName, NSs, MPayedSum, NCoeff, NRetSum jFROMJMakfc, Firms, TypesIWHEREjFirmIDeNFirm AND TypelD-NType*ORDER BYI№МЮiSELECTNaWlD, NDate, FMame, TName, NSs, MPayedSum, NCoeff, NRetSum jFROMJMakfc, Firms, TypesIWHEREjFirmIDeNFirm AND TypelD-NType*ORDER BYI№МЮiAddT施国冲AddT施国冲EteWs:BAUTHOR 8I58N BNAME BOOKID BOPT SPAGE5 BPRICE BPU0LISHEteWs:BAUTHOR 8I58N BNAME BOOKID BOPT SPAGE5 BPRICE BPU0LISHAddF 比 gSQLAddF 比 gSQLCancelCancel
244 Глава 5 • Технология dbExpress.NET
244 Глава 5 • Технология dbExpress.NET
Key DriverName Dat 必ase RoleName Iteer^Neme Password ServerCharSet SQlGect ErrorResourceFlle LocafeCode BlobSlze
Key DriverName Dat 必ase RoleName Iteer^Neme Password ServerCharSet SQlGect ErrorResourceFlle LocafeCode BlobSlze
:kx制host; c;出bldM8tlb_blMgdb
:RoleName:
;sysdba: •
masSrkey
:kx制host; c;出bldM8tlb_blMgdb
:RoleName:
;sysdba: •
masSrkey
3
3
Рис. 5.1. Окно редактора свойства Params
Рис. 5.1. Окно редактора свойства Params
SOU:
SOU:
FIRMS MOVES NAKLS PAYMENTS
FIRMS MOVES NAKLS PAYMENTS
SELECT
NaWlD, NDate, FMame, TName, NSs, MPayedSum, NCoeff, NRetSum j
FROMJ
Makfc, Firms, TypesI
WHEREj
FirmIDeNFirm AND TypelD-NType*
ORDER BYI
№МЮi
SELECT
NaWlD, NDate, FMame, TName, NSs, MPayedSum, NCoeff, NRetSum j
FROMJ
Makfc, Firms, TypesI
WHEREj
FirmIDeNFirm AND TypelD-NType*
ORDER BYI
№МЮi
AddT施国冲
AddT施国冲
EteWs:
BAUTHOR 8I58N BNAME BOOKID BOPT SPAGE5 BPRICE BPU0LISH
EteWs:
BAUTHOR 8I58N BNAME BOOKID BOPT SPAGE5 BPRICE BPU0LISH
AddF 比 gSQL
AddF 比 gSQL
Cancel
Cancel
Рис. 5.2. Окно редактора свойства CommandText
Откройте НД, создайте для него объекты-поля и свяжите с ним компонент DataSourcel.
Поместите н2 верхнюю панель сетку TDBGrid. В ее свойстве Align укажите значение alClient, а в свойстве BataSource сошлитесь на компонеиг DataSourcel. Сетка должна наполниться данными из главного НД.
Настройте свойства второго НД SimpleDataSet2: Name = Moves, Connection =SQLConnectionl. Раскройте сложное свойство DataSet н с помощью редактора введите в подсвойство CommandText такЗ; запрос:
SELECT
MBook, BName, BAuthor, EPublish, MQuan, MP匸:icc, McklFD
FROM
Books, Moves
WHERE
NakllD =: NakllD AND Book工D 二 MBook
ORDER BY BName
В подсвойстве Datasource свойства DataSet сошлитесь на компонент DataSourcel. Обратите внимание: на следующем шаге мы еще раз свяжем детальный НД с главным.
В свойство Mastersource НД Moves поместите ссылку на источник Data- Sourcel, вызовите редактор свойства MasterField и установите реляционную связь по столбцам Мак丄工D и NakllD (рис. 5.3).
Рис. 5.3. Установление реляционной связи
Свяжите с компонентом источник DataSource2, откройте НД и создайте для него объекты-поля.
Поместите на среднюю панель сетку TDBGrid, укажите в ее свойстве Align значение alClient, а в свойстве DataSource сошлитесь на источник Data- Source2, Сетка должна наполниться данными из детального НД.
Для отображения сумм в денежном формате напишите соответствующие обработчики OnGetText для объектов-полей. Например:
procedure TForml.NaklsNSUMGetText(Sender: TField;
var Text: String;
DisplayTexc: Boolean);
begin
Text :二 FloacToScrF(NaklsNSum.Value, ffCurrency, 15, 2)
end;
Для «листания» накладных разместите на нижней панели компонент TDBNavi- gator и свяжите его с источником DataSourcel.
Чтобы продемонстрировать, как можно удалять и искать записи в НД с однонаправленным курсором* создайте два контекстных меню: одно с командой Искать, второе с командой Удалить книгу. Свяжите первое с верхней сеткой, а второе —с нижней. Напишите такие обработчики OnCl ick выбора команд меню:
procedure TForml.NIClick(Sender: TObject);
/ / Удаление книги
begin
If MessageDlg(1 Вы действительно хотите удалить из накладной 1 + NaklsNaklXD.AsString+
'книгу ' + MoveBNAME'. Value* • ? * , mtWarning, [mbYes, mbNo], 0) = mrYes then with DeiBook do begin
Params[6].Aslnteger := NaklsNAXLID.AsInteger;
Params[1].Aslnteger := MovesMBook,Value;
ExecSQL;
Moves.Refresh
end
end;
procedure TForml.N3Click(Sender: TObject);
// Поиск накладной по номеру
var
Number: String;
N: Integer;
begin
if inputQuery(1Поиск накладной*,
1 Введите номер накладной*,Number) then
with Nakls do
begin
try
N := SttToInt(Number);
except
ShowMessage £ * Ошибка в записи числа *);
Exit
end;
DataSourcel.Enabled := False;
Locate(•NakllD*, N,[]);
DataSourcel.Enabled := True
end end;
Чтобы реализовать удаление книги, измените следующим образом свойства оставшегося в модуле данных компонента TSQLQuery:
о Name = DeiBook;
о SQLConnection = SQLCormect i onl;
O SQL:
DSLBTB PROM Moves
WHERE NakllD = :ID AND MBook = :Book
Создайте для компонента два параметра:
餾МАКСАТЕ •: •£ ]降 J,|тЙ1Йакпадн^. 4'(сппата ■■ InreTslm ;|Ь?фф11 01.03.2000 Точка. Социальный унгаерситет^Продажа на реализацию 550,00:0,00550,001,002.01.03.2000 »«еер^Продажа с предоплатой '3^92 :335,92:0,001”3 01.03.2000 ИКС ООО:Продажа на реакоац-о 45 337,50 ■0,001000,75!^^Ш 01.03-2000 ДЕСОПаб/^шерз■Приход по обмену6 782,000.000,001.005 01.03,2000 Розни*«я гродажа^Продажа с премглатой234,00234,000,001.СМ-6:01.0Э.2000 Точка. МГИЭМ^Продажа на реализацию 2 328」70.0,002 328,701,10Р7 61.032000 000 Издательство "Нолидж"^Поставка на реализацию 155 610,00'60 201.6595 408.351,00餾МАКСАТЕ •: •£ ]降 J,|тЙ1Йакпадн^. 4'(сппата ■■ InreTslm ;|Ь?фф11 01.03.2000 Точка. Социальный унгаерситет^Продажа на реализацию 550,00:0,00550,001,002.01.03.2000 »«еер^Продажа с предоплатой '3^92 :335,92:0,001”3 01.03.2000 ИКС ООО:Продажа на реакоац-о 45 337,50 ■0,001000,75!^^Ш 01.03-2000 ДЕСОПаб/^шерз■Приход по обмену6 782,000.000,001.005 01.03,2000 Розни*«я гродажа^Продажа с премглатой234,00234,000,001.СМ-6:01.0Э.2000 Точка. МГИЭМ^Продажа на реализацию 2 328」70.0,002 328,701,10Р7 61.032000 000 Издательство "Нолидж"^Поставка на реализацию 155 610,00'60 201.6595 408.351,00Params.ID.DataType = ftlntegerParams.Book.DataType 二 ftlnteger17. Вид окна работающей программы показан на рис. 5.4.Params.ID.DataType = ftlntegerParams.Book.DataType 二 ftlnteger17. Вид окна работающей программы показан на рис. 5.4.:54,00 :65,00:54,00 :65,004 Excel :практичесюе руюводство /Гехтов /Десс4 ноеейпии самоупель работы на компьютере /Симонович /Двсс4 Excel :практичесюе руюводство /Гехтов /Десс4 ноеейпии самоупель работы на компьютере /Симонович /Двсс4 программ^хзеание на яэъме QBas* для школьнкое и студентов бобровом /Деес 40,004 программ^хзеание на яэъме QBas* для школьнкое и студентов бобровом /Деес 40,00483056483056Рис. 5.4. Окно работающей программыРис. 5.4. Окно работающей программы
餾
МАКСАТЕ •: •£ ]降 J,
|тЙ1Йакпадн^. 4'(сппата ■■ InreTslm ;|Ь?фф1
1 01.03.2000 Точка. Социальный унгаерситет
^Продажа на реализацию 550,00:
0,00
550,00
1,00
2.01.03.2000 »«еер
^Продажа с предоплатой '3^92 :
335,92:
0,00
1”
3 01.03.2000 ИКС ООО
:Продажа на реакоац-о 45 337,50 ■
0,00
100
0,75
!^^Ш 01.03-2000 ДЕСОПаб/^шерз
■Приход по обмену6 782,00
0.00
0,00
1.00
5 01.03,2000 Розни*«я гродажа
^Продажа с премглатой234,00
234,00
0,00
1.СМ-
6:01.0Э.2000 Точка. МГИЭМ
^Продажа на реализацию 2 328」70.
0,00
2 328,70
1,10
Р
7 61.032000 000 Издательство "Нолидж"
^Поставка на реализацию 155 610,00'
60 201.65
95 408.35
1,00
餾
МАКСАТЕ •: •£ ]降 J,
|тЙ1Йакпадн^. 4'(сппата ■■ InreTslm ;|Ь?фф1
1 01.03.2000 Точка. Социальный унгаерситет
^Продажа на реализацию 550,00:
0,00
550,00
1,00
2.01.03.2000 »«еер
^Продажа с предоплатой '3^92 :
335,92:
0,00
1”
3 01.03.2000 ИКС ООО
:Продажа на реакоац-о 45 337,50 ■
0,00
100
0,75
!^^Ш 01.03-2000 ДЕСОПаб/^шерз
■Приход по обмену6 782,00
0.00
0,00
1.00
5 01.03,2000 Розни*«я гродажа
^Продажа с премглатой234,00
234,00
0,00
1.СМ-
6:01.0Э.2000 Точка. МГИЭМ
^Продажа на реализацию 2 328」70.
0,00
2 328,70
1,10
Р
7 61.032000 000 Издательство "Нолидж"
^Поставка на реализацию 155 610,00'
60 201.65
95 408.35
1,00
Params.ID.DataType = ftlnteger
Params.Book.DataType 二 ftlnteger
17. Вид окна работающей программы показан на рис. 5.4.
Params.ID.DataType = ftlnteger
Params.Book.DataType 二 ftlnteger
17. Вид окна работающей программы показан на рис. 5.4.
:54,00 :65,00
:54,00 :65,00
4 Excel :практичесюе руюводство /Гехтов /Десс
4 ноеейпии самоупель работы на компьютере /Симонович /Двсс
4 Excel :практичесюе руюводство /Гехтов /Десс
4 ноеейпии самоупель работы на компьютере /Симонович /Двсс
4 программ^хзеание на яэъме QBas* для школьнкое и студентов бобровом /Деес 40,00
4 программ^хзеание на яэъме QBas* для школьнкое и студентов бобровом /Деес 40,00
48
30
56
48
30
56
Рис. 5.4. Окно работающей программы
Рис. 5.4. Окно работающей программы
Подведем некоторые итоги. Важнейшим отличием компонента TSimpleDataSet от НД технологий BDE.NET н dbGo.NET является буферизация (кэширование) отображаемых им данных. Если вы попробуете с помощью навигатора удалить или изменить любую запись в верхней сетке, будут изменены данные в буфере, но никак не в БД! Реальное изменение данных возможно лишь с помощью соотвег- стБ)тощего параметрического запроса TSQLDataSet, как это сделано б примере для удаления данных о книге из накладной.
Разумеется, технология dbExpress.NET требует от программиста несколько больших усилий, чем рассмотренные ранее технологам BDE.NET и dbGo.NET. Однако б ряде последних заявлений представителей Borland отчетливо прозв)^1ала мысль, что в будущем эта технология станет доминирующей, так как именно она создает «легкое» клиентское место (без фомоздкого аппарата BDE и/или необходимости распространения вместе с приложением базовых объектов ADO).
Компоненты для реализации технологии
В основе технологии dbExpress.NET лежат три компонента: связной компонент TSQLConnection, универсальный НД TSQLDataSet и клиентский НД TSimpleDataSet. Компоненты-наборы TSQLQuery, TSQLTable и TSQLStsored- Ргос лишь повторяют свойства аналогичных компонентов других технологии, но нс решают главной проблемы — не создают двунаправленных курсоров.
248 Глава 5 • Технология dbExpress.NET
Компонент TSQLConnection
Компонент TSQLConnection решает две основные проблемы: выбирает нужный драйвер для связи с сервером и указывает путь доступа к файлу БД. Созданное с его помощью соединение может разделяться многочисленными НД( если поместить в их свойство SQLConnection ссылку на этот компонент.
Компонент использует два настроечных файла: dbdrivers.ini и dbconnections.ini, которые по умолчанию располагаются в папке Program Files\Common Files\Borland Shared\DBExpress. Первый содержит список установленных в системе драйверов для серверов БД (InterBase, Oracle и т. д.), а также библиотек DLL, в которых они располагаются, и параметры подключений, заданные по умолчанию. Второй настроечный файл содержит конфигурации параметров подключений. Вы можете использовать параметры из второго файла, чтобы установить связь с сервером, либо создать собственные параметры связи. Для этого нужно дважды щелкнуть на компоненте и заполнить поля в окне построителя соединений (рис. 5.5).
Jtl-zj -d 〃◎[
0rhyNW声哄出隔望0rhyNW声哄出隔望' ASACornectlon:■ ASEConnectlonD82Connection .InformbcConnection■ MSSQLConnection MySQLConnecaon OracteConnection' ASACornectlon:■ ASEConnectlonD82Connection .InformbcConnection■ MSSQLConnection MySQLConnecaon OracteConnectionOm^ion^tUng$ 讨15-DrlverName Datmase RoleNameOm^ion^tUng$ 讨15-DrlverName Datmase RoleNameUser_NarnBUser_NarnBPasswordPasswordServerCbarSetSQLDialect ErrorResourceFUeServerCbarSetSQLDialect ErrorResourceFUe卜 alueInter Ge卜 alueInter GeC:\BIBLDATA\IB_BIBL12S RoleName ■ sysdba : 'msterkeyC:\BIBLDATA\IB_BIBL12S RoleName ■ sysdba : 'msterkey
0rhyNW
声哄出隔望
0rhyNW
声哄出隔望
' ASACornectlon
:■ ASEConnectlon
D82Connection
.InformbcConnection
■ MSSQLConnection MySQLConnecaon OracteConnection
' ASACornectlon
:■ ASEConnectlon
D82Connection
.InformbcConnection
■ MSSQLConnection MySQLConnecaon OracteConnection
Om^ion^tUng$ 讨15-
DrlverName Datmase RoleName
Om^ion^tUng$ 讨15-
DrlverName Datmase RoleName
User_NarnB
User_NarnB
Password
Password
ServerCbarSet
SQLDialect ErrorResourceFUe
ServerCbarSet
SQLDialect ErrorResourceFUe
卜 alue
Inter Ge
卜 alue
Inter Ge
C:\BIBLDATA\IB_BIBL12S RoleName ■ sysdba : 'msterkey
C:\BIBLDATA\IB_BIBL12S RoleName ■ sysdba : 'msterkey
Рис. 5.5. Окно построителя соединений
Свойства компонента TSQLConnection перечислены в табл. 5.1.
Таблица 5.1. Свойства компонента TSQLConnection
property ActiveStatements :
Содержит общее количество активных за-
Cardinal;
просов для данного подключения. Аюгивиым запрос станови тся после установления в его свойство Prepared значения True или в момент выполнения неподготовленного запроса. Значение этою свойства не может превышать значения сво11ства MaxStmcsPerConn, если AutoClone = False
Свойство
Описание
Компоненты для реализации технологии 249
Свойство
Описание
property AutoClone: Boolean;
property Connected: Boolean;
property ConnectionName: String;
type TConnectiofiState =
(csStateClosed, csStateOpen, csStateConnecting, csStateExecuting, csStateFetching, csStateDisconnecting);
property Connectionstate: TConnectionState;
property DataSetCount : Integer;
property DataSets [Index: Integer]: TCustomSQLDataSet;
property DriverName: String;
property GetDriverFunc : String;
property InTransaction: Boolean;
property KeepCorinection: Boolean;
property LibraryNaine : String;
property LoadParamsOnConnect: Boolean;
type TLocaleCode = Integer;
property LocaleCode: TLocaleCode;
property LoginPrompt: Boolean;
Раэрешает/запрещает автоматически создавать новые соединения, если исчерпано количество активных соединений, указанное в свойстве MaxStmts PerConn
Открывает/закрывает связь с сервером
Определяет имя конфигурации параметров соединения
Определяет состояние соединения: csState- Closed — соединение установлено; csSta- teOpen — соединение разорвано; csScate- Connecting — компонент устанавливает соединение; csStateExecuting — компонент передает серверу запрос; csState- Fetchin — компонент получает информацию от сервера; csStateDisconnecting — компонент разрывает связь, но остались незавершенные запросы
Указывает количество обслуживаемых компонентом НД
Открывает индексированный доступ ко всем НД, разделяющим данное соединение
Определяет имя драйвера для связи с сервером БД
Определяет имя функции, возвращающей интерфейс dbExpress верхнего уровня. Как правило, это свойство содержит имя функции, которое определено в файле dbxdrfversJni Содержит True, если стартовавшая транзакция не завершена
Если содержит True, соединение с сервером сохраняется, даже если закрыты все обслуживаемые компонентом НД
Содержит имя DLL с драйвером
Определяет, загружает ли компонент конфигурацию, указанную в свойстве Соп- nectionName, непосредственно перед соединением с сервером
Определяет язык локализации (для России —1049)
Указывает, будет ли появляться диалоговое окно перед установкой соединения с БД
Таблица 5,1 (продолжение)
Свойство
Описавие
property MaxStmts PerConn: Cardinal;
Определяет максимальное количество активных запросов на одно соединение
property Params: TStrings;
Содержит список параметров соединения
property ParamsLoaded: Boolean;
Если содержит True, параметры соединения будут загружаться из файла dbxconnectionsJnl
property SQLHourGlass: Boolean;
Если содержит True, форма курсора будет изменяться во время длительных операций
Type TTableScope = (tsSynonym, tsSysTable, tsTable, tsView); TTableScopes 二 set o£ TTableScope;
property TableScope : TTableScopes ;
Определяет тип таблиц, которые будут отображаться при выполнении метода GetTab- 1 eNames: tsSynonym — синонимы, tsSys- ТаЫе — системные таблицы, tsTable — обычные таблицы, tsView — представления
property TransactionsSupported:
LongBool;
Указывает, будет ли сервер базы данных поддерживать транзакции
property VendorLib: String;
Содержит имя библиотеки DLL, созданной производителем сервера для поддержки клиентов
Методы компонента TSQLConnection перечислены в табл. 5.2.
Таблица 5.2. Методы компонента TSQLConnection
Метод
Описание
function CloneConnection:
TSQLConnection;
Создает копию соединения
procedure CloseDataSets;
Закрывает все обслуживаемые компонентом НД, но не разрывает связь с сервером
procedure Commit (TransDesc: TTransact i onDesc);
Подтверждает изменения, сделанные в транзакции TransDesc, и закрывает ее
function Execute (const SQL:
String; Params: TParams): Integer;
Выполняет на сервере SQL-команду без использования каких-либо НД. Если в команде не требуются параметры, удобнее использовать метод ExecuteDirect
function ExecuteDirect (const
SQL: String ) : Integer;
Выполняет на сервере SQL-команду без параметров
procedure GetFieldNames (const
Tabi eName : String; List: TStrings);
Заполняет список List именами столбцов таблицы TableName
procedure Ge11ndexNames (const
Та bl eName: String; List : TStrings);
Заполняет список List именами индексов таблицы TableName
Метод
Описание
procedure Ge t Proc edureName s (List: TStrings);
Заполняет список List именами хранимых процедур
procedure GetProcedvreParams (ProcedureName: String; List: TList);
Заполняет список List именами параметров хранимой процедуры ProcedureNawe
procedure Rol Iback (TransDesc: TTransactionDesc);
Отменяет измененияг сделанные в транзакции TransDesc, и закрывает ее
procedure SetTraceCallbackEvent
(Event: TSQLCallbackEvent;
IClientlnfo:Integer);
Связывает с соединением функцию обратного вызов% которая будет вызываться при каждом обмене информацией между клиентом и сервером
procedure
StartTransaction(TransDesc: TTransactionDesc);
Стартует транзакцию
В листинге 5.1 показан пример использования метода Execute для ввода данных о новой книге в таблицу Books.
Листинг 5.1. Использование метода Execute для ввода данных о новой книге
procedure TForml.ButtonlClick(Sender: TObject); var
SQLstmt: String;
stmtParams: TParams;
begin
stmtParams := TParams.Create; try
SQLConnectionl.Connected := True;
stmtParams.CreateParam(ftString, 'Name', ptInput);
stmtParams. ParamByName (' Name' ) . AsString : = edName. Text ; stmtParams.CreateParam(ftString, 'Author', ptXnput); stmtParams.ParamByName('Author *)•AsString := edAuthor.Text; stmtParams.CreateParam(ftString, •Publish', ptinput);
stmtParams.ParamByName('Publish').AsString := edPublish.Text;
stmtParams.CreateParam(ftString, 'Year*, ptlnput);
stmtParams.ParamByName('Year').AsString := edYear.Text; stmtParams.CreateParam(ftstring, 'Pages', ptlnput); stmtParams.ParamByName{'Pages').AsString := edPage.Text; stmtParams.CreateParam(ftstring, 'ISBN', ptlnput);
stmtParams.ParamByName('ISBN').AsString := edlSBN.Text;
SQLstmt := * INSERT INTO Books ' +
'(BName, BAuthor, ВPublish, bYear, BPages, BISBN) ' +
'VALUES (:Name, :Author, :Publish, :Year, :Pages, :ISBN)1; SQLConnectionl.Execute(SQLstmt# stmtParams);
fixially
stmtParams.Free; end
end;
Для демонстрации механизма транзакций создадим проект, в котором деньги с дебиторского счета переводятся на кредиторский (проект Ch05\TransDemo\TransDemo.dpr). В качестве таблиц счетов используем таблицы DEB и CRED БД IB_BIBL.GDB.
На рис. 5.6 показано окно формы на этапе конструирования.
Рис. 5.6. Окно формы на этапе конструирования
На форме располагается связной компонент SQLConnect ionl, настроенный на связь с БД IB_BIBL:
ConnectionName = IBConnection;
DriverName = Interbase;
Params.Database = localhost:C:工BLDATA、工B_B工BL.GDB;
LoginPrompt = False;
Connected = True.
Компоненты DEB и CRED — НД класса TSimp 1 eDataSet, связанные с соединением SQLConnectionl н соответствующ!imи таблицами БД. Оба НД открыты, и для них созданы объекты-поля. Сетки DBGridl и DBGrid2 через источники DataSourcel и DataSource2 связаны с НД DEB и CRED соответственно,
В нижней части формы располагается поле ввода класса TSpinEdit (категория Samples) и кнопка Buttonl.
В листинге 5.2 показаны обработчики событий OnActivate формы и OnClick кнопки.
Листинг 5.2. Использование транзакций для перевода денег
procedure TForml.FormActivate(Sender: TObject);
// Передает фокус ввода полю SpinEditl в момент активизации окна begin
SpinEditl.SetFocus;
end;
procedure TForml.ButtonlClick(Sender: TObject);
// Осуществляет перевод суммы под защитой транзакции var
Com: TSQLQuery;
ComStr: String;
Sum: Integer;
TD: TTransactionDesc;
begin
// Проверяем допустимость введенной суммы:
if SpinEditl,Value <= 0 then
Exit;// Нет ввода
if SpinEditl.Value > DEBSumm.Value then
begin// Слишком большая сумма
SpinEditl.Value := Round(DEBSumm.Value);
SpinEditl.SetFocus; .
Kxit;
end;
Sum : = SpinEditl.Value; // Сумма перевода
// Создаем л настраиваем компонент TSQLQuery:
Com := TSQLQuery.Create(Self);
Com.SQLConnection := SQLConnectionl;
〃 Команда снятия денег co счета :
ComStr := Format('UPDATE DEB SET SUMM=%d WHERE NCOUNT=%d',
(Round {DEBSxinun.Value - Sum), DEBNCount .Value]);
Com•CommandText := ComStr;
// Команда начисления яа кредиторский счет:
ComStr := Format('UPDATE CRED SET SUMM=%d WHERE NCOUNT=%d',
[Round(CREDSunun.Value + Sum), CREDNCount.Value]);
TD.TransactionlD := 1;
SQLConnec t ionl.StartTransaction(TD);
try
Com.ExecSQL;
Com.CommandText := ComStr;
Com.ExecSQL;
SQLConnec t i on1.Commi t(TD);
except
SQLConnec t ion1.Ro1Iback(TD);
ShowMessage(*Мо!1);
end;
// Обновляем данные а сетках:
DEB.Active :='False;
DEB.Active := True;
CRED.Active := False;
CRED.Active := True;
〃 Готовим поле ввода ;,
SpinEditl.Value := 0;
SpinEditl.SetFocus; end;
Характерной особенностью транзакций в технологии dbExpress.NET является возможность вложения транзакций. Для этого каждая транзакция снабжается уникальным идентификатором и набором дополнительных параметров в экземпляре записи следующего класса:
type TTransact ionDesc = packed record
TransactionlD : LongWOrd; // Идентификатор транзакции
GloballD: Longword; // Идентификатор транзакции
IsolationLevel : TTransIsolationLevel; // уровень изоляции CustomIsolation : Longword; / / Умалчиваемый уровень изоляции end;
Поле Transat ionlD определяет уникальный идентификатор транзакции для всех серверов, кроме Oracle, который для этих целей использует поле GloballD. Поле IsolationLevel устанавливает уровень изоляции транзакции:
type TTransIsolationLevel = (xi1READCOMMITTEDr xilREPEATABLEREAD, xilDIRTYREAD, xilCUSTOM);
Если это поле имеет значение xilCUSTOM, изоляция транзакции определяется полем CustomIsolation, однако не все серверы поддерживают это значение. При вызове метода StartTransaction в транзакцию передается ее уникальный идентификатор в поле Transaction工D (или GloballD для сервера Oracle). Это позволяет указывать, какую именно транзакцию подтверждает или откатывает программа.
Помимо событии, связанных с установкой и разрывом соединения (AfterConnect, Af terDisconnect, BeforeConnect, BeforeDisconnect), для компонента TSQLConnection определено следующее событие, возникающее перед установкой соединения и до события BeforeConnect, если свойство LoginPrompt имеет значение True:
type TSQLConnectionLoginEvent 二 procedure(
Database: TSQLCormection; LoginParams: TStrings) of object; property OnLogin: TSQLConnectionLoginEvent;
В обработчике программа может указать параметры Username, Password и Database.
Компонент TSQLDataSet
Компонент TSQLDataSet определяет набор данных с однонаправленным курсором или команду обновления данных, в зависимости от содержимого его свойства CommandText.
Компонент унаследовал от класса TDataSet многие свойства, методы и события, типичные для наборов данных BDE.NET (см. главу 3). В этом разделе рассматриваются только специфические для компонента свойства, методы и события. Свойства компонента TSQLDataSet перечислены в табл. 53.
Таблица 5.3. Свойства компонента TSQLDataSet
Свойство
Описание
property CommandText: String;
Содержит текст SQL-запроса к серверу БД
type TSQLCommandType = (“Query, ctTable, ctStoredProc);
property CommandType: TSQLCoirunandType;
Определяет тип запроса: ctQuery — обычный SQL-запрос; сtTable — запрос, возвращающий все записи из единственной таблицы; ctStoredProc — обращение к хранимой процедуре
Кз
^поненты для реализации технологии 255
Свойство
Описание
property DataSource: TDataSource;
Сдержит ссылку на главный НД в отношении главный—детальный
property DesignerData: String;
Не имеет определенного назначения. Может использоваться в специализированн ых наследниках
property IndexDefs: Tlndexoefs;
Содержит описания всех индексов, определенных для данного НД
propertyMaxBlobSize: Integer;
Определяет максимальный размер буфера (в байтах), в который будут считываться данные из BLOB-столбцов
property NoMetadata: Boolean;
Если содержит True, компонент не ползает от сервера снязанных с НД метаданных (индексов), что может повысить производительность работы. Однако для отношении главный—детальный, для редактирования записей и в некоторых других случаях это свойство должно иметь значение False, заданное по умолчанию
property ParamCheck: Boolean;
Если содержит False, компонент не будет автоматически обновлять свойство Params при изменении содержимого свойства ConunandText
property Params : TParams;
Содержит параметры запроса
property Prepared: Boolean;
Если содержит True, компонент требует от сервера подготовить выполнение запроса. Выделенные для этого ресурсы сервера будут осообождены при установке в свойство значения False
property RecordCount : Integer;
Содержит количество записей в НД. Чтение этого свойства вызовет исключение, если компонент реализует обращение к хранимой процедуре, выполняет параметрически!! запрос или объединяет данные из нескольких таблиц
property SortFieldNames: String;
Содержит перечень столбцов сортировки, если свойство ConunandType имеет значение ctTable
property SQLConnection:
Содержит ссылку на связной объект TSQL-
TSQLCormect ion;
Connection
property Transact ionLevel :
Указывает уровень транзакции» в которой
Smalllnt;
будет выполняться запрос. Только InterBase разрешает вложенные транзакции. Серверы Oracle и DB2 не допускают вложение транзакций, а сервер MySQL их не поддерживает
В табл. 5.4 перечислены лишь наиболее важные методы компонента TSQLDataSet.
Таблица 5.4. Методы компонента TSQLDataSet
Метод
Описание
type TBlobStreamMode = (bmRead, bmWrite, bmReadWrite);
Создает поток данных для доступа к BLOB- столбцам
function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; override;
function ExecSQL (ExecDirect :
Boolean 二 False) : Integer;
override;
Выполняет запрос, который не возвращает НД. Параметр ExecDirect определяет, будет ли запрос подготавливаться сервером перед его исполнением '
type TBlobByteData = array of Byte;
function GetBlobFieldData (FieldNo: Integer; var Buffer: TBlobByteData): Integer; override;
Читает в буфер Buffer данные из BLOB- столбца текущей записи
function ParamByName (const Value: String): TParam;
Открывает доступ к параметру по его имени
type TSchemaType = (stNoSchema, stTables, stSysTables, stProcedures, stColumns, stProcedureParams, stIndexes );
Управляет схемой отображаемых данных (см, далее)
procedure Setschemainfo ( SchemaType: TSchemaType; SchemaObjectName, SchemaPattern: String );
Элементы типа TSchemaType:
stNoSchema — данные отображаются по запросу в свойстве CommandText;
stTables — отображается информация о таблицах БД;
stSysTables — отображается информация о системных таблицах БД;
stProcedures — отображается информация о хранимых процедурах;
stColumns — отображается информация о столбцах таблицы, имя которой содержит параметр SchemaObj ectName;
stProcedureParams — отображается информация о параметрах хранимой процедуры, имя которой содержит параметр SchemaObj ectName;
st Indexes — отображается информация об индексах таблицы БД, имя которой содержит параметр SchemaObj ес tName.
Параметр SchemaPattern метода SetSchemalnfo определяет SQL-маску отображаемой информации. Отображаемая запись должна соответствовать маске или она не будет отображаться. В маске используются два специальных символа %
(на месте этого символа может находиться произвольная строка) и 一 (на месте этого символа может находиться любой одиночный символ).
Компонент TSQLDataset не имеет специфических событий по сравнению с событиями, рассмотренными в главе 3.
Компонент TSQLQuery
Класс TSQLQuery является непосредственным потомком класса TSQLDataSet и наследует от него большинство свойств и методов. «Своими» у компонента являются cBoiicTBa SQL и Text. Первое определяет текст многострочного запроса, второе — однострочного. Метод ExecSQL выполняет запрос, не возвращающий записи, а метод Preparestatment готовит запрос к выполнению.
Подобно своему родителю, компонент возвращает набор данных с однонаправленным курсором.
Компонент TSQLTable
Компонент TSQLTable используется для доступа к одной таблице БД. Он имеет свойства Mas terSource и MasterFields, с помощью которых можно установить реляционную связь главный—детальный. Свойства IndexFields н IndexNames позволяют подключать к НД нужный индекс и тем самым сортировать данные. Свойство Tab! eName определяет имя отображаемой таблицы БД.
Компонент TSQLMonitor
Компонент TSQLMonitor используется для отладки программы: он перехватывает все сообщения, которыми обмениваются соединение и сервер, и помещает их в текстовый список или сохраняет в файле.
Примеры перехваченных сообщений:
INTERBASE - isc_attach_database
INTERBASE - isc_dsql_allocate_.statement
INTERBASE - isc_start—transaction
SELECT * FROM TypeNakl
INTERBASE - isc_dsql_prepare
INTERBASE - isc_dsql_describe_bind
INTERBASE - isc__dsql__execute
INTERBASE - isc_dsql_allocate_statement
SELECT 0, ' ' , ,A.RDB$RELATION_NAME( A.RDB$INDEX_NAME#
В.RDB$FIELD_NAME, В.RDB$FIELD_POSITION, 1 1, 0, A.RDB$TNDEX_TYPE, 'I A.RDB$UN工QUE—FLAG, C.RDB$CONSTRAINT_NAME, C.RDB$CONSTRAINT_TYPE FROM RDB$INDICES A, RDB$INDEX-SEGMENTS В FULL OUTER JOIN RDB$RELAT工ON_CONSTRA工NTS C ON A.RDB$RELATION_NAME =
C.RDB$RELATION_NAME AND C.RDB$CONSTRAINT_TYPE 二'PRIMARY KEY'
WHERE (A.RDB$SYSTEM_FLAG о 1 OR A.RDB$SYSTEM_FLAG IS NULL) AND (A.RDB$INDEX_NAME 二 В.RDB$INDEX_NAME) AND (A.RDB$RELATION_NAME = UPPER('TypeNakl'J) ORDER BY RDB$INDEX_NAME INTERBASE - isc„dsql_prepare
9 Зак, 449
INTERBASE - isc_dsql^describe_bind
INTERBASE - i sc_dsql_execute
INTERBASE - isc_dsql_fetch
INTERBASE - isc_dsql_fetch
INTERBASE - isc_commit_retaining
INTERBASE - isc_dsql_free_statement
INTERBASE - isc_dsql_free_statement
INTERBASE - isc^dsql^fetch
INTERBASE - isc_dsql~allocate_statement select count(*) from TypeNakl
INTERBASE - i s c_dsql_prepare
INTERBASE - is c_dsql_describe_bind
INTERBASE - isc_dsql_execute
INTERBASE 一 isc_dsql^allocate_statement
Свойства компонента TSQLMonitor перечислены в табл. 5.5.
Таблица 5.5. Свойства компонента TSQLMonitor
Свойство
Описание
property Active : Boolean;
Включает/выключает работу компонента
property AutoSave : Boolean;
Если содержит True, все перехваченные сообщения помещаются в файл, указанный свойством FileName
property FileNatne: String;
Содержит имя файла> возможно, с путем доступа, В этом файле сохраняются все перехваченные ксшповентом сообщения, если свойство AutoSave содержит True. Если AutoSave = False, файл является Пеле- вым файлом, заданным по умолчанию для методов LoadFromFile и SaveToFile
property MaxTraceCount: Integer;
Содержит максимальное количество сохраненных сообщений. Если содержит -1, ограничений нет, если 0, компонент не перехватывает сообщения. Переустановка значения этого свойства в работающей программе влияет только на новые сообщения и не влияет на уже сохраненные
property SQLConnection: TSQLConnection;
Содержит ссылку на связной компонент
property TraceCount: integer;
Указывает количество сохраненных сооб- щеггий
property TraceList : TStrings ;
Хранилище сообщений
Компонент TSQLMonitor имеет два специфических метода, с помощью которых программа может загрузить из файла или сохранить в файле протокол сообщеиий:
procedure LoadFromFile(AFileName: String);
procedure SaveToFile{AFileName: String);
Если при обращении к любому из этих методов указана пустая строка AFileName, используется имя файла из свойства FileName.
Для компонента TSQLMonitor определены два события. Первое событие:
type
SQLTRACEDesc = packed record
pszTrace : array [0..1023] of Char;
eTraceCat : TRACECat;
uTotalMsgLen : Word;
end;
TTraceLogEvent = procedure (Sender: TObject;
var CBInfo: SQLTRACEDesc) of object;
property OnLogTrace: TTraceLogEvent;
Второе событие:
type TTraceEvent = procedure(Sender: TObject;
var CBInfo: SQLTRACEDesc;
var LogTrace: Boolean) of object; property OnTrace: TTraceEvent;
Первое событие возникает сразу после того, как очередное сообщение помещено в список TraceLi st, но до сохранения его в файле, если AutoSave = True. Второе событие возникает непосредственно перед сохранением сообщения в списке или файле.
Параметр CBInfo определяет запись типа SQLTRACEDesc со следующими полями:
pszTrace — текст сообщения;
eTraceCat — категория сообщения;
uTotalMsgLen — длина сообщения в буфере pszTrace.
Если в параметр LogTrace обработчика OnTrace поместить значение False» сообщение не будет сохранено в списке (файле).
Компонент TSimpleDataSet
Компонент TSimpleDataSet буферизует записи и создает двунаправленный курсор, Он имеет две особенности. Во-первых, с помощью свойства Connect ionName он может создать собственное соединение с сервером БД. Во-вторых, только с его помощью в технологии dbExpress можно кэшировать изменения.
Следует заметить, что создавать с помощью компонента TSimpleDataSet собственное соединение с сервером следует лишь в исключительных случаях, так как это соединение нельзя разделить с другими компонентами, а количество одновременно создаваемых соединений с сервером обычно лимитируется условиями лицензионного соглашения (например, поставляемый с Delphi 2005 сервер InterBase 7.5 ограничивает количество соединений пятью).
Наиболее важные свойства компонента представлены в табл. 5.6.
Таблица 5.6. Свойства компонента TSimpleDataSet
Свойство
Описание
property AutoCalcFields: Boolean;
Если содержит True, будет возбуждаться событие OnCalcFields
property Connection:
Содержит ссылку па связной компонент или
TSQLConnec t i on;
property DataSet : TDataSet ;
описывает собственное соединение с БД
Содержит ссылку на внешний НД или описывает собственный SQL-запрос
property DisableStringTrim: Boolean;
Если содержит True, будут отсекаться ведомые пробелы при подтверждении изменений в столбцах
property FetchOnDemand: Boolean;
Если содержит True (по умолчанию), данные кэшируются по мере надобности (например, при прокрутке сетки отображения)
property FileName: string;
Содержит имя файла, в котором сохраняются данные (см. далее)
property MasterFields : string;
Содержит ссылку на столбцы, реализующие реляционную связь главный — детальный
property Mastersource:
Содержит ссылку на главный НД в связи
TDataSource;
property PacketRecords: Integer;
главный—детальный
Указывает количество записей, получаемых компонентом из БД в одном пакете. Если содержит 0, компонент получает из БД метаданные
property Params : TParams;
Аналогично одноименному свойству компонента TQuery (см. раздел ^Запросы» в главе 3)
Свойство FileName компонента позволяет сохранять данные из буфера в дисковом файле н читать из файла в буфер. Таким способом реализуется отложенная обработка записей. Пользователь с помощью ноутбука подключается к локальной сети, переписывает интересующие его данные в файл и затем отправляется на удаленную презентацию, конференцию, деловую встречу или распродажу. Там он оперирует файловыми данными, вносит в них необходимые изменения. После возвращения на предприятие он вновь подключается к сети и подтверждает сделанные им изменения в БД. Если свойство содержит правильный маршрут доступа к файлу, компонент автоматически записывает в него данные при закрытии НД и так же автоматически читает из файла при его открытии.
Чтобы проиллюстрировать технику отложенной обработки, внесем в пример, рассмотренный в начале этой главы (см. раздел «Пример простой профаммы»), следующие изменения:
Поместите на нижнюю панель две кнопки и диалоговые окна TOpenDialog и TSaveDialog. Назовите кнопки (свойства Caption) В файл и Из файла.
Напишите такие обработчики событий OnClick кнопок:
procedure TForml.ButtonlClick(Sender: TObject);
// Сохранение данных в файле begin
if SaveDialogl.Execute then
begin
Nakls.FileName := SaveDialogl.FileName;
Screen.Cursor := crHourGlass;
DataSourcel.Enabled := False;
Nakls,Close;
Nakls.Open;
DataSourcel.Enabled := True;
Screen.Cursor := crDefault
end end; procedure TForml.Button2Click(Sender: TObject); // Чтение данных из файла begin
if OpenDialogl.Execute then
begin
DataSourcel.Enabled := False;
Screen.Cursor := crHourGlass;
Nakls.Close;
Nakls.FileName := OpenDialogl.FileName;
Nakls.Open;
DataSourcel.Enabled := True;
Screen.Cursor := crDefault
end exid;
Замечу, что для связи главный—детальный нужно создавать два файла. Если бы в нашем примере мы попытались сохранить детальный НД, были бы сохранены данные только по одной накладной. Чтобы данные по всем накладным были сохранены в файле, нужно предварительно разорвать связь главный—детальный, затем сохранить данные в файле, после чего восстановить реляционную связь.
Наиболее важные методы компонента TS imp 1 eDa t aSet перечислены в табл. 57
Таблица 5.7. Методы компонента TSimpleDataSet
Метод
Описание
procedure Addindex (const Name, Fields: String; Options: TlndexOptions; const DescFields: String = 1 ' ; const CaselnsFields : String = ' '; const GroupingLevel : Integer = 0 );
Создает новый индекс (см. далее)
procedure AppendData (const Data:
OleVariant; HitEOF: Boolean);
Добавляет данные Data к существующему локальному НД. Вместо этого метода обычно используется GetNextPacket
Таблица 5.7 (продолжение)
Метод
Описание
procedure Apply Range;
Включает механизм учета диапазона фильтрации записей
function ApplyUpdates (MaxErrors : Integer); Integer;
Обновляет записи в БД: MaxErrors — максимально допустимое количество ошибок. Возвращает истинное количество ошибок
function BookmarkValid (Bookmark: TBookmark): Boolean;
Возвращает True» если закладка Bookmark содержит правильную ссылку
procedure Cancel; override;
Откатывает все неподтвержденные изменения текущей записи
procedure CancelRange;
Отменяет режим фильтрации по ключевым столбцам
procedure Cancelupdates;
Отменяет все неподтвержденные изменения из пакета Delta
procedure Clonecursor (Source : TCustomClientDataSet; Reset: Boolean; KeepSettings: Boolean = False);
Позволяет разделять данные двумя и более компонентами (см. далее)
function CompareBookmarks (Bookmarkl, Bookmarks: TBookmark):Integer;
Сравнивает две закладки и возвращает -1, 0 или +1, если первая закладка, соответственно, меньше, равна или больше второй
function ConstraintsDisabled:
Boolean;
Разрешает или запрещает компоненту учитывать ограничения на значения столбцов
function CreateBlobStream (Field:
TField; Mode: TBlobStreamMode):
TStream; override;
Создает поток данных для BLOB-столбца: Field — имя столбца; Mode — режим потока: для чтения (bmRead), записи (bmWrite) или обновления (bmReadWrite) данных
procedure CreateDataSet;
Создает пустой набор данных с параметрами по умолчанию
procedure Deletelndex (const
Name: String);
Удаляет иядекс с именем Name
procedure DisableConstraints;
Временно прекращает действие ограничений, наложенных на значения столбцов
procedure EditKey;
Переводит НД в режим dsEditKey и сохраняет поисковый буфер. Этот метод полезно вызывать для комплексного индекса, когда между двумя поисками меняются лишь некоторые столбцы (см. далее примечание)
procedure EditRangeEnd;
Переводит НД в режим редактирования нижней границы диапазона фильтрации
procedure EditRangeStart;
Переводит НД в режим редактирования верхней границы диапазона фильтрации
Компоненты для реализации технологии 263
Метод
Описание
procedure EmptyDataSet;
Очищает буфер от всех записей
procedure EnableConstraints ;
Отменяет режим, установленный методом
DisableConsttaints
procedure Execute; virtual;
Выполняет запрос из свойства CommandText
procedure FetchBlobs ;
Получает от сервера приложений текущий BLOB-столбец
procedure FetchDetails;
Получает от сервера приложений вложенную таблицу Oracle
function FetchParams ;
Получает от сервера приложений текущие параметры компонентов TQuery или TSto- redProc
function FindKey (const Key Values : array of const) : Boolean?
Аналог одноименного метода ТТаЫе (см. далее примечание)
procedure FindNearest (const Keyvalues: array o£ const);
Аналог одноименного метода ТТаЫе (см. далее примечание)
functionGetCurrentRecord (Buffer: IntPtr): Boolean; override;
Копирует текущую запись в буфер Buffer
function GetFieldData (Field:
TField; Buffer:IntPtr):
Boolean; override;
Копирует столбец Field текущей записи в буфер Buf fer
type TGroupPosInd = {gbFirst # gbMiddle, gbbast);
TGroup PosInds = set of TGroupPosInd;
function GetGroupState (Level : integer) : TGroupPoslnds;
Возвращает положение текущей записи в группе агрегирования Level: gbFirst — первая в группе минимум из двух записей; gbMiddle — ни первая, ни последняя; gbLast — последняя в группе минимум из двух записей
procedure Getlndexlnfo (indexName: String);
Возвращает информацию об индексе с именем IndexName
function GetNextPacket: Integer;
Требует от сервера приложений передать следующий пакет записей. Длииа пакета определяется свойством PacketRecords. Функция возвращает количество записей^ добавленных в свойство Data
function GetOptionalParam (const
PararnName: String) : OleVariant;
Возвращает из пакета данных пользовательскую информацию с именем ParamName, которая помещена туда методом SetOpti- onalParam
procedure GotoCurrent (DataSet :
TClientDataset);
Синхронизирует курсор текущего набора с курсором набора Dataset
Таблица 5.7 (продолжение)
Метод
Описание
function GotoKey: Boolean;
Ищет запись, определенную предварительным вызовом SetKey или EditKey с последующим вызовом FieldByName, и возвращает True, если запись найдена (см. далее примечание)
procedure GotoNearest;
Ищет запись, либо точно соответствующую поисковому значению, либо следующую за ней в порядке индекса. Поисковое значение задается методом SetKey или EditKey с последующим вызовом FieldByName (см. далее примечание)
procedure LoadFromFile (const
Загружает набор данных из файла Filename.
Fil eName : String = ' * );
Совместно с SaveToFile дает возможность отложенного обновления данных
procedure LoadFromStream (Stream:
TStream);
Загружает набор данных из потока Stream
type TLoc at eOpt i on =
Ищет запись по значениям KeyValues столб-
(loCaselnsensitive,
цов KeyFields и возвращает True в слу-
loPartialKey); TLocateOptions =
чае успеха. Параметр Option уточняет ус-
set of TLocateOption;
ловия поиска: loCaselnsensitive — игно-
function Locate (const KeyFields:
рировать разницу в регистре букв; loPart-
String; const Keyvalues: Variant;
Options: TLocateOptions):
Boolean; override;
ialKey — искать по части ключа
function Lookup (const KeyFields :
Ищет запись по значениям Key Values столб-
String; const Keyvalues : Variant;
цов KeyFields и возврашдет значения столб-
const ResultFields : String):
цов ResultFields найденной записи в слу-
Variant; override;
чае успеха
procedure MergeChangeLog;
Объединяет данные из протокола изменений с реальными данными вызовом Арр lay- Updates
procedure Post; override;
Подтверждает изменения в текущей записи
function Reconcile (const
Вызывается методом ApplayUpdat еs про-
Results: OleVariant): Boolean;
вайдера в случае возникновения ошибки Results — пакет ошибочных записей Метод возбуждает событие OriReconc i 1 eError доя каждой записи пакета Results (см. далее)
procedure RefreshRecord;
Обновляет текущую запись, считывая ес у провайдера. Протокол изменений записи не меняется
procedure RevertRecord;
Восстанавливает текущую запись по протоколу ее изменений
procedure SaveToFile (conet
FileName: String ='');
Сохраняет НД в файле FileName
Компоненты для реализации технологии 265
Метод
Описание
procedure SaveToStream
(Stream: TStream; Format:
TDataPacketFormat = dfBinary);
Сохраняет данные в потоке
procedure SetAltRecBuffees
Устанавливает новые значения в столбцы
{Old, New, Cur: PChar);
OldValue, NewValue и CurValue текущей записи
procedure SetKey ;
Переводит НД в режим dsSetKey для установки нового поискового значения, которое задается следующим вызовом FieldByName (см. далее примечание)
procedure SetOptionalParamt conet Помещает в пакет данных пользовательскую
ParamName: String; conet Value:
информацию: ParamName — имя данных;
OleVariant; IncludelnDelta:
Value — данные; IncludelnDelta содержит
Boolean 二 False);
True, если данные помещаются в пакет Delta
procedure SetRange (const
Устанавливает диапазон поиска по ключам
StartValues, EndValues:
array of const);
(см. далее примечание)
procedure SetRangeEnd;
Устанавливает нижнюю границу диапазона поиска (см. далее примечание)
procedure SetRangeStart ;
Устанавливает верхнюю границу диапазона поиска (см. далее примечание)
function UndoLastChange
Отменяет последнюю операцию изменения,
(FollowChange: Boolean):
удаления или вставки записи. Если Follow-
Boolean;
Change = True, после отмены текущей становится восстановленная запись
function UpdateStatus :
Возвращает статус обновления текущей за-
TUpdateStatus; override;
писи
ПРИМЕЧАНИЕ
Подробнее об индексном поиске с помощью методов SetKey, EditKey, Set Range и т. п. см. в главе 3.
Параметры метода Addindex перечислены ниже:
Name — имя индекса;
Fields — список индексных столбцов;
Options — может включать 0, 1 или 2 флага ixDescending (сортировка по убыванию) “ ixCaselnsensitve (сортировка с учетом регистра букв); остальные значения типа TIndexOptions вызовут исключение;
DescFields — список столбцов, сортируемых по убыванию; игнорируется, если установлен флаг ixDescending;
CaselnsFields — список столбцов, сортируемых с учетом регистра букв; игнорируется, если установлен флаг ixCaselnsensitve;
GroupingLevel — уровень вложенности индекса, заданный по умолчанию.
С помощью метода CloneCursor компонент переводится в режим совместного владения данными с другим компонентом, ссылку на который содержит параметр Source. Параметры Reset и KeepSettings определяют, как будут использоваться следующие свойства:
Filter, Filtered, Filteroptions, OnFilterRecord;
IndexName;
Mastersource, MasterFields;
Readonly.
Эти свойства влияют на совместное владение данными: если оба параметра имеют значение False, перечисленные свойства у текущего компонента будут такими же, как у компонента Source; если Reset = True, свойства очищаются, а если Reset = False и KeepSettings = True, сохраняют те значения, которые они имели до обращения к методу. Поскольку оба компонента владеют одной и той же копией данных» изменения, сделанные в копии одним компонентом, тут же становятся видны другому компоненту.
Метод Reconcile для каждой ошибочной записи генерирует связанное с компонентом специфическое событие:
type
TReconcileAction = (raSkip, raAbort, raMerge,
raCorrect, raCancel, raRefresh);
TReconcileErrorEvent = procedure(DataSet: TClientDataSet;
E: EReconci1eError;
UpdateKind: TUpdateKind;
var Action: T Rec one i1eAc t i on) of object;
property OnReconcileError: TReconcileErrorEvent;
Здесь:
DataSet — клиентский НД, содержащий ошибочные записи (текущая запись этого набора и является ошибочной);
Е — объект исключения;
UpdateKind — характер обновления ошибочной записи;
Action — в этом параметре обработчик должен вернуть одно из следующих значений:
о raSkip — пропустить ошибочную запись;
о raAbort — прекратить режим корректировки;
о raMerge — выполнить конкатенацию ошибочной записи с исходной;
о raCorrect — запись была скорректирована в обработчике;
о raCancel — восстановить запись по протоколу изменений;
о raRefresh — восстановить запись, считав ее из БД.
Обработчик может использовать значения OldValue, NewValue и CurValue для каждого столбца записи, но он не должен изменять текущее положение курсора НД.
События компонента TSimpleDataSet перечислены в табл. 5.8.
Таблица 5.8. События компонента TSimpleDataSet
Событие
Описание
type TRemoteEvent = procedure
(Sender: TObj ес t ; var OwnerData:
OleVariant) of object;
Возникает после подтверждения изменений, но перед событием OnReconcileError
property AfterApplyUpdates : TRemoteEvent;
property AfterExecute :
TRemoteEvent;
Возникает после получения НД в результате выполнения метода Execute
property Af terGet Params :
TRemoteEvent;
Возникает после получения от провайдера Значений параметров в результате выполне* ния метода FetchParams
property AfterGetRecords: TRemoteEvent;
Возникает после получения от провайдера пакета данных
property AfterRowRequest : TRemoteEvent;
Возникает после получения компонентом детальной мнформацим о текущей записи
property BeforeApplyUpdates : TRemoteEvent;
Возникает перед подтверждением изменений
property BeforeExecute : TRemoteEvent;
Возникает перед выполнением метода Execute
property BeforeGet Params : TRemoteEvent;
Возникает перед выполнением метода Fet- chParams
property BeforeGetRecords :
TRemoteEvent ;
Возникает перед получением пакета данных от провайдера
property Be f oreRowReque st :
TRemoteEvent;
Возникает перед получением компонентом детальной информации о текущей записи
type TReconcileAction = (raSkip, raAbort, raMerge, raCorrect, raCancel, raRefresh);
Это событие генерируется методом Reconcile для каждой ошибочной записи (см. ранее описание метода Reconcile)
type TReconcileErrorEvent = procedure (DataSet: TCustomClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction) of object;
property OnReconcileError : TReconcileErrorEvent;
События BeforeXXX-AfterXXX сопровождаются параметром Owner Dat а, которым программа может распоряжаться по своему усмотрению.
Технология IBX.NET
Технология IBX.NET (1ВХ — InterBase eXpress) рассчитана на создание «облегченного» клттента. С этой целью она предоставляет программисту средства непосредственного обращения к промьппленному серверу InterBase версии 5.5 н выше без использования машины баз данных BDE или других подобных средств доступа к данным. Delphi не запрещает и традиционную архитектуру с BDE, однако, если вы собираетесь создавать клиент-ссрвсрную СУБД на основе сервера InterBase 5.5 и выше, вряд ли вы откажетесь от более компактных и быстрых средств IBX.NET, описываемых в этой главе.
ПРИМЕЧАНИЕ
Все компоненты технологии IBX.NET сосредоточены в категории InterBase палитры компонентов. В списке категорий, раскрывающемся после щелчка на кнопке Categories, эта категория обычно не ыиша, так как она следует за категорией Internet Для доступа к категории InterBase используете полосу прокрутки п списке категорий.
Пример простой программы
Перед выполнением этого примера (проект Ch06\Nakls\IBXDemo.dpr) на вашей машине (или в доступном вам сетевом окружении) должен быть развернут и запущен сервер InterBase 5.5 или выше (с Delphi 2005 поставляется InterBase 7.5).
Характерно!! особенностью иснользовання технологии IBX.NET яв.яяется необходимость создания соединения с БД, что достигается с помощью двух компонентов: TIBDatasase и TIBTransaction. Только после размещения на форме этих компонентов и их настройки могут получить доступ к данным другие компоненты IBX. 1. Начните новый VCL-проект и разместите на форме компоненты TlBDatabase, TIBTransact ion, два компонента TIBTable (все компоненты располагаются в категории InterBase палитры компонентов) и два компонента TDataSource (категория Data Access).
Раскройте список свойства DatabaseName компонента IBDatabasel и с его помощью установите ссылку на фа"л БД IB_BIBL.GDB (он размещается в папке C:\BIBLDATA).
Раскройте редактор свойства Params компонента IBDatabasel и введите регистрационное имя и пароль:
USER_NAME = SYSDBA
PASSWORD 二 mascerkey
ПРИМЕЧАНИЕ
При использовании технологии IBX.NET параметр USER_NAME пишется с символом подчеркивания. Если используются другие технологии (BDE.NET, dbGo.NETF dbExprcss.NET), вместо подчеркивания можно стаппть пробел.
Установите в свойство LoginPrompt компонента IBDar.^basel значение False.
С помощью списка свойства DefaultDatabase свяжите компонент IBTrans- actionl с компонентом IBDatabasel.
Поместите в свойство Database компонента IBTablel ссылку на компонент IBDatabasel. В списке свойства TableName выберите таблицу NAKLS. Установите в свойство Name компонента значение Nakls. Откройте таблицу (поместите True в свойство Active). При этом автоматически активизируются компоненты IBDatabaselиIBTransactionl.
Компонент 1ВТаЫе2 свяжите с компонентом IBDatabasel и таблицей MOVES, укажите для него имя Moves.
Таблицы NAKLS (накладные) и MOVES (списки книг) связаны отношением г.чаиная—детальная по полям NakllD. Для реализации связи в свойство Mastersource компонента MOVES помееп-пе ссылку на источник DataSourcel, раскроете редактор свойства MasterFields и укажите связь по полямКакИБ (рис. 6.1). Откройте НД MOVES.
Рис. 6.1. Установление связи по полям NakllD
270 Глава б • Технология IBX.NET
Поместите на форму три панели TPane 1 (категория Standard). В свойстве Align двух из них укажите значение alBottomr а в третьей — значение alClient.
Поместите на верхнюю панель сетку TDBGrid (категория Data Control), в свойстве Align сетки укажите значение alClient и сошлитесь на источник DataSourcel в ее свойстве DataSource. Сетка наполнится записями из главной таблицы.
Поместите на среднюю панель еще одну сетку TDBGrid и настройте ее на отображение записей детальной таблицы (Align = alClient, DateSource DataSource2).
Разместите на нижней панели навигатор TDENavigator (категория Data Control) и свяжите его с верхней сеткой (поместите в свойство DataSource значение DataSourcel).
Вид окна работающей программы для этого момента показан на рис. 6.2.
•用浊后:|М%ЕТОДТ61NTVP£ (NOCfiFF |Й5ЦМ |NPA^DSUM)NR£TSUM |№ШМ ( £1 О1.О3.2СХЮ30.04.20001-L550□ ■550 :5<汕2 01,03,200031.03,20007:1,M:335,919335,919:01013 01.03,200010.М.20001.0,73.45337,5□ ;□24 ог.оз.ахю01.03.2СХЮ4:16782□ :□355 01.03.200002.03.20007l,0<234234;0:586 01.03,200030,04.2000ij1.1: 2329,6990i 2328,699;5S7 01.03.200030,04.20000:1:15561060201,652: 95406,348;ВВ 01.03.200031,03.20001:0,75;2767,5□:0;329 01,03.200031.03.20001:0,75 i855□:0:4210 01.03,200030,04,20000:lj 155610□ i□В .11 01.03.2СХЮ31,D3,2tX30li口内Z64600:0:7212 01.ОЗ.ЙМО01.03.20003ili 2358,9□:0;56•用浊后:|М%ЕТОДТ61NTVP£ (NOCfiFF |Й5ЦМ |NPA^DSUM)NR£TSUM |№ШМ ( £1 О1.О3.2СХЮ30.04.20001-L550□ ■550 :5<汕2 01,03,200031.03,20007:1,M:335,919335,919:01013 01.03,200010.М.20001.0,73.45337,5□ ;□24 ог.оз.ахю01.03.2СХЮ4:16782□ :□355 01.03.200002.03.20007l,0<234234;0:586 01.03,200030,04.2000ij1.1: 2329,6990i 2328,699;5S7 01.03.200030,04.20000:1:15561060201,652: 95406,348;ВВ 01.03.200031,03.20001:0,75;2767,5□:0;329 01,03.200031.03.20001:0,75 i855□:0:4210 01.03,200030,04,20000:lj 155610□ i□В .11 01.03.2СХЮ31,D3,2tX30li口内Z64600:0:7212 01.ОЗ.ЙМО01.03.20003ili 2358,9□:0;56
•用浊后:
|М%ЕТОДТ61
NTVP£ (NOCfiFF |Й5ЦМ |
NPA^DSUM)NR£TSUM |№ШМ ( £
1 О1.О3.2СХЮ
30.04.2000
1-L550
□ ■550 :5<汕
2 01,03,2000
31.03,2000
7:1,M:335,919
335,919:0101
3 01.03,2000
10.М.2000
1.0,73.45337,5
□ ;□2
4 ог.оз.ахю
01.03.2СХЮ
4:16782
□ :□35
5 01.03.2000
02.03.2000
7l,0<234
234;0:58
6 01.03,2000
30,04.2000
ij1.1: 2329,699
0i 2328,699;5S
7 01.03.2000
30,04.2000
0:1:155610
60201,652: 95406,348;В
В 01.03.2000
31,03.2000
1:0,75;2767,5
□:0;32
9 01,03.2000
31.03.2000
1:0,75 i855
□:0:42
10 01.03,2000
30,04,2000
0:lj 155610
□ i□В .
11 01.03.2СХЮ
31,D3,2tX30
li口内Z6460
0:0:72
12 01.ОЗ.ЙМО
01.03.2000
3ili 2358,9
□:0;56
•用浊后:
|М%ЕТОДТ61
NTVP£ (NOCfiFF |Й5ЦМ |
NPA^DSUM)NR£TSUM |№ШМ ( £
1 О1.О3.2СХЮ
30.04.2000
1-L550
□ ■550 :5<汕
2 01,03,2000
31.03,2000
7:1,M:335,919
335,919:0101
3 01.03,2000
10.М.2000
1.0,73.45337,5
□ ;□2
4 ог.оз.ахю
01.03.2СХЮ
4:16782
□ :□35
5 01.03.2000
02.03.2000
7l,0<234
234;0:58
6 01.03,2000
30,04.2000
ij1.1: 2329,699
0i 2328,699;5S
7 01.03.2000
30,04.2000
0:1:155610
60201,652: 95406,348;В
В 01.03.2000
31,03.2000
1:0,75;2767,5
□:0;32
9 01,03.2000
31.03.2000
1:0,75 i855
□:0:42
10 01.03,2000
30,04,2000
0:lj 155610
□ i□В .
11 01.03.2СХЮ
31,D3,2tX30
li口内Z6460
0:0:72
12 01.ОЗ.ЙМО
01.03.2000
3ili 2358,9
□:0;56
Рис. 6.2. Промежуточный вариант окна работающей программы
Для создания подстановочных полей разместите на форме еще три компонента TlBTable, свяжите их с соединением IBDatabasel и с таблицами FIRMS, BOOKS И TYPES.
Для таблиц NAKLS и MOVES создайте объекты-поля.
В объекты-поля НД NAKLS добавьте подстановочные поля Firms и Types, связав их с полями FName и TName одноименных НД.
В объекты-поля НД MOVES добавьте подстановочные поля Name, Author и Publish, связав их с полями BName, BAuthor и BPublish НД BOOKS.
Создайте объекты-столбцы для сеток DBGridl и DBGrid2, указав в них подстановочные поля вместо ключевых.
Напишите обработчики событий OnGetText для всех вещественных полей, чтобы данные были отформатированы нужным образом. Например:
procedure TForml.NAKLSNCOEFFGetText(Sender: TField;
var Text: string;
DisplayText: Boolean);
begin
Text := FloatToStrF(NAKLSNCoeff.Value, ffNumber( 10, 2);
end;
Вид окна работающей программы в окончательном варианте показан на рис. 6.3.
觸
ав 帘 цтвямш 曲 MitK*i?伊:ис1Шйы£ць
койй^п^т Ь
NO |Дита. |nw»p
:ямв ]
兩в诵Jc|g<;::隰:
1 ;01.(И.2(ХХ]:Точка. Социальный университет
吋 аажа нз реализацию
550,00
1,000.00;
550,00:30.04.200(
2Ю1.О3.2ООО;Я<звер
Г^оджа с предоппатой
335,92
LN; 335,92:
500 31,03.200(
3ioi.a3.200oiMKcooo
;Г^одажа на реалюацио
45 337,50
乌 75;0,00 г
0(00:Ю-СМ.200(
璃01.03.2000 :ДЕСС-Пабгииерэ
ПрихоА по обмену
6 782,00
1,000,00 ■
охю@.оэ.2оа
5 :01.0Э.2000 ^Розничная продажа
gaaxa с предсплдтой
234,00
lg 234,00;
0,00:02.03.2ОК:а-
6:01.0Э.2000^Точка. МГИЭМ
Г^одажа нз реализацию
2 32S(70
1Д0:'6g
2 328,70 ;Х.04.200(
7 S ,03,2000 000 Издательство *Hom4 Y
Поставка на реализацию
15S 610,00
1,00: 60 201,65:
95 4 06,35 HHM.200С
8 01.ОЭ.2ООО ;Г^ода^пЪ>
9;01.03.2000!ИЛ4та
ГХюА 次 а на реалюацмо
2 767,50
0,75.SOD
G,DO :31.03.20(Х
Продажа на реализацию
855,00
0,750,00
О,ОО:31.О3.2Оа
4
遂
№ (HaawwfrZAewAWwfcCTBO .у.、:::.:、
■ kw Ikwwu. I必
>
4:Новейший самоучитель работы нз кшгъютере /Сиоювии ^««м
65,00
30修
4 :中ограммкроеанке на язью QBasc дпл шфлымсв и студентов /Бобровса 自ном
4D,D0
56
А :Ехсв1 ;праюичеоа» рукаводс^во ДЮпов ^ином
54,CO
幅瀛
*4."а阳小1/ J ?/
二r-fi畢冷j
Рис. 6.3. Окончательный вариант окна работающей программы
Компоненты для реализации технологии
Как уже говорилось» особенностью технологии является обязательное использование в ней компонентов TIBDatabase и TIBTransaction. Эта компоненты имеют общий родительский класс TIBBase, с рассмотрения свойств которого мы м начинаем.
Класс TIBBase
Класс TIBBase инкапсулирует свойства (табл. 6.1), методы (табл, 6.2) н события (табл. 6,3), общие для компонентов TIBDatabase л TIBTransaction.
Таблица 6.1. Свойства класса TIBBase
СвойствоОписание
property Database : TIBDatabase; Содержит ссылку на связанный компонент
TIBDatabase
Таблица 6.1 (продолжение)
Свойство
Описание
property DBHandle: IntPtr;
Содержит дескриптор базы данных
property Owner : TObject;
Содержит ссылку на владельца объекта
property Transaction: TIBTransaction;
Содержит ссылку на связанный компонент TIBTransaction
property TRHandle: IntPtr;
Содержит дескриптор транзакции
Таблица 6.2. Методы класса TIBBase
Метод
Описание
procedure CheckDatabase;
Проверяет связь с БД и ее активность
procedure CheckTransaction;
Поверяет связь с транзакцией и ее активность
Таблица 6.3. События класса TIBBase
Событие
Описание
property
OnA f t erDat aba s eDi sconnec t: TNotifyEvent;
Возникает после отсоединения от БД
property
OnBeforeDatabaseDisconnect: TNotifyEvent;
Возникает перед отсоединением от БД
property OnDatabaseFree: TNotifyEvent;
Возникает после выгрузки объекта TIBDatabase из памяти
property OnAfterTransactionEnd: TNotifyEvent;
Возникает после окончания транзакции
Property OnBe f oreTransact ionEnd : TNotifyEvent;
Возникает перед окончанием транзакции
property OnTransactionFree : TNotifyEvent;
Возникает после выгрузки объекта TlBTrans- action из памяти
Компонент TIBDatabase
Компонент TIBDatabase создает соединение с БД InterBase. Свойства компонента TIBDatabase перечислены в табл. 6.4.
Таблица 6.4. Свойства компонента TIBDatabase
Свойство
Описание
property DatabaseName: String;
Указывает имя физической БД, с которой связан компонент (см. далее)
property DBParamByDPB: [const Idx: Integer]: String;
Позволяет проверить или установить заново какой-либо параметр БД
Компоненты для реализации технологии 273
Свойство
Описание
property DBSQLDialect : Integer;
Содержит диалект языка SQL, который используется БД
property Def aultTransaction:
TIBTransaction;
Содержит ссылку на транзакцию, заданную по умолчанию
property Handle : IntPtrj
Содержит дескриптор соединения. Используется для прямого обращения к API-функциям InterBase
property HandlelsShared : Boolean;
Содержит True, если используется разделяемый дескриптор соединения
property IdleTimer: Integer;
Указывает время в миллисекундах, по истечении которого автоматически разрывается соединение с БД, если за это время к ней не было обращения
property isReadOnly : Boolean;
Содержит True, если БД работает только в режиме чтения
property Params: TStrings;
Содержит список параметров, которые передаются серверу в момент соединения
property SQLDialect : Integer;
Содержит диалект языка SQL, который используется компонентом
property SQLObjectCount:
Integer;
Содержит количество SQL-объектов, связанных с данным соединением. К SQL-объектам относятся IBSQL и BLOB наборов данных InterBase
property SQLObjects [ Index: Integer]: TIBBase;
Открывает индексированный доступ к SQL- объектам
property TraceFlags : TTraceFlags;
Содержит флаги, определяющие различные состояния БД, которые должны прослеживаться в SQL-мониторе (см. далее)
property TransactionCount:
Integer;
Указывает количество транзакций, связанных в данный момент с компонентом
property Transactions [ Index:
Integer]: TIBTransaction;
Открывает индексированный доступ к связанным с компонентом транзакциям
Свойство DatabaseName для локального сервера содержит имя файла ЕД. При связи с удаленной БД формат имени следующий:
по протоколу TCP/IP:
имя_сервера : имя_файла_ВД
по протоколу NetBIOS:
\\имя_сервера\имя_файла_БД
по протоколу SPX:
имя_сервера@имя_файла_ВД
Компонент может управлять несколькими транзакциями одновременно. Свойство DefaultTransaction ссылается на транзакцию, которой компонент управляет в данный момент.
Определение типа для свойства TraceFlags:
type TTraceFlag = (tfQPrepare, tfQExecute, tfQFetch, tfError, tfStmt, tfConnect, tfTransact, tfBlob, tfService, tfMisc);
TTraceFlags = set of TTraceFlag;
Здесь перечислены следующие флаги:
tfQPrepare — готовится вьшолнение запроса;
tfQExecute — запрос выполняется;
tfQFetch — идет наполнение набора данных;
tfError — возникла ошибка при выполнении запроса;
tfStmt — мониторинг всех SQL-предложений;
tfConnect — устанавливается связь с БД;
tfTransact — мониторинг начала, подтверждения и отката транзакций;
tfBlob — мониторинг операций над данными типа BLOB;
tfService — мониторинг служебных операций;
tfMisc — мониторинг любых других предложений, не перекрывающихся этими флагами.
Методы компонента TlBDatabase перечислены в табл. 6.5.
Таблица 6.5. Методы компонента TlBDatabase
Метод
Описание
function AddTransaction(TR:
TIBTransaction): Integer;
Устанавливает связь между компонентом и новой транзакцией
procedur* Apply Updates (const DataSets: array of TIBCustomDataSet);
Подтверждает кэшированные изменения
procedure CheckActive;
Проверяет активность компонента и возвращает ошибку, если связь не установлена
procedure CheckDatabaseName;
Возбуждает ошибку, если свойство DatabaseName не заполнено
procedure Checkinactive;
Возбуждает ошибку, если связь с БД установлена
procedure Close;
Разрывает соединение с БД и закрывает все связанные с компонентом НД. Повторное открытие компонента не открывает заново НД
procedure CloseDataSets;
Закрывает все связанные с компонентом наборы данных, но в отличие от метода Close» не разрывает связь с сервером и БД
Метод
Описание
procedure CreateDatabase;
Создает новую БД, используя свойство Params как перечень параметров новой БД
procedure DropDatabase;
Удаляет существующую БД
function FindTransaction (TR:
TIBTransaction): Integer;
Возвращает индекс указанной транзакции
procedure ForceClose;
Закрывает БД, даже если в результате операции возникла ошибка
procedure GetFieldNaines (const Tabi eName: String; List : TStrings);
Возвращает список имен всех столбцов указанной таблицы. К моменту обращения к методу связь с БД должна быть установлена
procedure GetTableNanies (List :
TStrings; SystemTables: Boolean = False);
Возвращает сшгсок всас таблиц БД. Если параметр SystemTables имеет значение True, список дополняется именами системных таблиц
function IndexOfDBConst (st : String):Integer;
Возвращает индекс параметра по его имени (если возвращается -1, параметр с нужным именем не найден)
procedure Open;
Устанавливает связь с БД
procedure RemoveTransaction (Idx: Integer);
Отсоединяет указанную транзакцию от компонента
procedure RemoveTransactions;
Отсоединяет все транзакции от компонента
procedure SetHandle;
Устанавливает дескриптор для БД
procedure TestConnected: Boolean;
Проверяет связь с БД и возвращает True, если связь установлена
С помощью метода CreateDatabase можно создать новую базу данных. Для этого в свойство DatabaseName помещается информация о месторасположении (компьютер, маршрут доступа) и имя файла создаваемой БД, а в набор Params — параметры БД, например, такие:
USER "SYSDBA*
PASSWORD "masterkey"
PAGE_SIZE=4096
DEFAULT CHARACTER SET WIN1251
После выполнения метода будет создана полноценная БД с файлом по адресу, указанному в свойстве DatabaseName.
События компонента TIBDatabase перечислены в табл. 6.6.
Таблица 6.6. События компонента TIBDatabase
Событие
Описание
property
OnDia1ес t Downgradewarning: TNotifyEvent;
Возникает в момент открытия БД, если номер используемой в ней версии диалекта SQL меньше указанного в свойстве SQLDialect
Таблица 6.6 (продолжение)
Событие
Описание
property OnldleTimer :
Возникает, если время «простоя* БД превы-
TNotifyEvent;
TDa t aba в eLogi nEven t = procedure (Database: TIBDatabase;
LoginParams: TStrings) of obj ect;
property OnLogin :
сит указанное в свойстве IdleTimer
Возникает, если свойство Loginprompt содержит True. В обработчике события регистрационное имя и пароль необходимо поместить во временный список LoginParams
TDatabaseLoginEvent;
Компонент TIBTransaction
Для установления связи с InterBase в технологии IBX.NET хотя бы один компонент TIBTransaction должен быть связан с компонентом TIBDatabase. В многозвенных приложениях каждый SQL-запрос исполняется в отдельной транзакции.
Свойства компонента TIBTransaction перечислены в табл* 6.7.
Таблица 6.7. Свойства компонента TIBTransaction
Свойство
Описание
property Active: Boolean;
Содержит True, если компонент активен
property Databasecount : Integer;
Содержит количество БД, обслуживаемых в данной транзакции
property Databases [ Index :
Integer]: TIBDatabase;
Дает индексный доступ к БД, обслуживаемым транзакцией
type TTransactionAction = (taRollback, taCommit, taRollbackRetaining, taCommitRetaining);
property DefaultAction: TTransactionAction;
Указывает способ завершения транзакции по истечении времени, заданного в свойстве TdleTimer: taRollback — откатить транзакцию; taCommit — подтвердить транзакцию; taRollbackRetaining — откатить транзакцию, но сохранить ее контекст (для InterBase версии 6 и выше); taCommitRetaining — подтвердить транзакцию, но сохранить ее контекст
property- DefaultDatabase: TIBDatabase;
Содержит текущую БД
property Handle: IntPtr;
Содержит дескриптор транзакции
property HandlelsShared : Boolean;
Содержит True, если дескриптор транзакции разделяемый
property- IdleTimer: Integer;
Указывает, сколько времени в миллисекундах должно пройти перед автоматическим выполнением свойства DefaultAction
Компоненты для реализации технологии 277
Свойство
Описание
property InTransaction: Boolean;
Указывает, находится ли БД в состоянии незавершенной транзакции
property Params: TStrings;
Содержит набор параметров для компонента
property SQLObjectCount: Integer;
Содержит количество обслуживаемых транзакцией активных SQL-компонентов (наборов данных JBSQL BLOB)
property SQLObjects [Index: Integer]: TIBBase;
Открывает индексный доступ к обслуживаемым транзакцией SQL-компонентам
property TPB: IntPtr ;
Содержит ссылку на буфер параметров транзакции (только в режиме чтения). Для записи параметров служит свойство Params
Property TPBLength : Short;
Указывает длину буфера параметров компонента
Методы компонента TlBTransaction перечислены в табл. 6.8.
Таблица 6.8. Методы компонента TlBTransaction
Метод
Описание
function AddDatabase (db:
TIBDatabase):Integer;
Добавляет к компоненту новый компонент
TIBDatabase
procedure CheckDatabasesInList;
Проверяет список связанных компонентов TIBDatabase. Если список пуст, возбуждается исключение
procedure checklnTransaction;
□ровняет акги&ность транзакции и список обслуживаемых ею компонентов TIBDatabase. Если транзакция неактивна или список пуст, возбуждается исключение
procedure CheckNot InTransac t ion;
Проверяет активность транзакции и список об* служиваемых ею компонентов TIBDatabase. Если транзакция активна или список не пуст, возбуждается исключение
procedure Commit;
Подтверждает текущую транзакцию и завер* шает ее
procedure CommitRetaining;
Аналогичен методу Commit, но сохраняет контекст транзакции
function FindDatabase (db: TIBDatabase): Integer;
Возвращает индекс связанного компонента TIBDatabase
procedure Remov eDat abase (Idx: Integer);
Удаляет компонент TIBDatabase с индексом Idx из списка связанных с компонентом TlBTransaction
Таблица 6.8 (продолжение)
Метод
Описание
procedure RemoveDatabases;
Удаляет все компоненты TIBDatabase из списка связанных с компонентом TIBTrans- action
procedure Rollback;
Осуществляет откат текуи(ей транзакции
procedure RollbackRetaining;
Аналогичен методу Rollback, но сохраняет контекст транзакции
Procedure StartTransaction;
Начинает очередную транзакцию
В момент открытия компонента TIBTransation автоматически стартует связанная с ним транзакция. Пример неправильного кода:
procedure TForml.FormAct ivate(Sender: TObject);
begin
Nakls.Open;
IbTransactionl.StartTransact ion; // Ошибка/
// Транзакция уже стартовала/
end;
В момент открытия НД Nakls автоматически открывается и компонент IBTransactionl, поэтому во втором операторе делается попытка открыть вложенную транзакцию, что недопустимо. В листинге 6.1 (проект Ch06\TransDemo\ TransDemo.dpr) приводится правильное решение классической задачи перевода денег с дебиторского счета на кредиторский (рис. 6.4).
Рис. 6.4. Окно программы с примером использования транзакции
Листинг 6.1. Программа перевода денег с дебиторского счета на кредиторский
procedure TForml.FormActivate(Sender: TObject);
/ / Передает фокус ввода полю SpinEdi tl в момент активизации формы begin
SpinEditl.SetFocus;
end;
procedure TForml-ButtonlClick(Sender: TObject);
〃 Осуществляет перевод суммы под задаток транзакции var
Com: TlBQuery;
ComStr: String;
Sum: Integer;
begin
// Проверяем сумм/ перевода :
if SpinEditl.Value <= 0 then
Exit;// Нет ввода
if SpinEditl.Value > DEBSumm.Value then
begin// Слишком большая сумма
SpinEdi11,Value := Round(DEBSumm.Value);
SpinEditl.SetFocus;
Exit;
end;
Sum := SpinEditl.Value;〃 Сумма перевода
// Создаем и настраиваем компонент класса TIBQuery:
Com := TIBQuery.Create(Self);
Com.Database := IBDatabasel;
Com.Transaction := IBTransactionl;
// Формируем команду снятия денег с дебиторского счета:
ComStr := FormatC*UPDATE DEB SET SUMM=%d WHERE NCOUNT=%d* #
[Round(DEBSumm.Value - Sum), DEBNCount-Value]);
Com.Text := ComStr;
// Формируем команду начисления на кредиторский счет:
ComStr := Format ( * UPDATE CRED SET SUMM=%d WHERE NCOUNT=%d',
[Round(CREDSumm.Value + Sum), CREDNCount-Value]);
try
Com.ExecSQL;// Снимаем деньги
Com- Text := ComStr;
Com. Exec SQL;/ / Начисляем деньги
IBTransactionl.Commit;//Подтв^ждаем транзакцию
except/ / Ошибка J
IBTransactionl.Rollback; // Откатываем транзакцию
ShowMessage(1NoI');
end;
// Обновляем данные в сетках;
DEB.Active := False;
DEB,Active : = True; // Одновременно стартует новая транзакция CRED.Active := False;
CRED.Active := True;
// Готовим поле для нового ввода;
SpinEditl.Value := 0;
SpinEditl.SetFocus;
end;
Обратите внимание: при открытии любого НД автоматически стартует новая транзакция, поэтому в приведенном примере нет команды
IBTahsactionl.StartTransaction;
С компонентом связано единственное событие, которое возникает после завершения транзакции по истечении времени, указанного в свойстве IdleTimer:
property OnldleTimer: TNotifyEvent;
Компонент TIBTable
Компонент TIBTable повторяет в функциональном отношении компонент TTable технологии BDE.NET, поэтому их основные свойства, методы, события, а также приемы работы с ними аналогичны (см. главу 3). В табл. 6.9 описываются лишь специфические для компонента свойства.
Таблица 6.9. Свойства компонента TIBTable
Свойство
Описание
property Bufferchunks: Integer;
Указывает, на сколько записей будет увеличиваться буфер таблицы по мере его наполнения
propertyUniDirectional: Boolean;
Если содержит False, с таблицей связывается двунаправленный курсор и навигация по ней разрешается как сверху вннз, так н снизу вверх. Если содержит True, навР1гация по таблице разрешается только сверху вниз
property UpdateObject;
Ссылается на объект, который будет реализовывать изменения в таблицах, открытых только для чтения
В отличие от своего аналога из технологии BDE.NET, компонент TIBTable может создавать однонаправленный курсор (компонент TTable всегда создает двунаправленный курсор). Однонаправленные курсоры экономят ресурсы компьютера и реализуют более быструю навигацию по записям. Свойство UniDirectional объявлено в секции publish^ а не в секции published, поэтому его нет в окне инспектора объектов, и программист не может изменить его на этапе разработки программы (но может — при прогоне программы). Если таблица с однонаправленным курсором отображается в сетке TDBGrid, перемещение курсора вверх возможно только в пределах сетки. Перед изменением свойства UniDirectional компонент должен быть закрыт.
В документации сказано, что компонент может отображать не только реальные таблицы БД, но и представления (view). Это действительно так, только при ссылке на таблицу не стоит искать представление в раскрывающемся списке свойства Tabi eName, а следует просто вручную записать имя представления в это свойство. Поскольку представления могут быть необновляемыми (например, они могут содержать записи из нескольких таблиц), в компоненте появилось свойство UpdateObj ect. В это свойство чаще всего помещается имя компонента TIBUpdateSQL, с помощью которого реализуются изменения отображаемых данных, если представление «не живое».
Компонент не имеет специфических по сравнению с компонентом ТТаЫе методов и событий.
Компонент TIBQuery
Компонент TIBQuery является функциональным аналогом компонента TQuery, описанного в главе 3. В этом разделе представлены только специфические для компонента свойства (табл. 6.10).
Таблица 6.10. Свойства компонента TIBQuery
Свойство
Описание
property GenerateParamNames :
Если содержит True, компонент создает спи-
Boolean;
сок параметров запроса (в компоненте TQuery этот список создается всегда)
property StmtHandle : IntPtr;
Дескриптор БД, который можно использовать при непосредственном обращении к API-функциям InterBase
По-моему, свойству Generate ParamNames трудно найти практическое применение, разве что оно дает программисту возможность немного сэкономить ресурсы компьютера* Кроме того, мне не удалось найти разницу в поведении компонента при изменении значения этого свойства. Например, в следующем фрагменте список ListBoxl всегда наполнялся именами параметров независимо от значения свойства GenerateParamNames:
procedure TForml.FormCreate(Sender: TObject);
var
k: Integer;
begin
IBQueryl.GenerateParamNames := False;
for k := 0 to IBQueryl.Params.Count-1 do
ListBoxl.Items.Add(IBQueryl.Params[k].Name); end;
Компонент не имеет специфических методов и свойств.
Компонент TIBDataSet
Компонент TIBDataSet предназначен для просмотра и модификации набора записей, указанного в его свойстве SelectSQL. Особенностью компонента является то обстоятельство, что НД не становится обновляемым до тех пор, пока не определены модифицирующие его SQL-операторы в его строковых свойствах InsertSQL, DeleteSQL и Modify SQL. Если, например, в его свойстве Insert SQL записан правильный оператор INSERT, НД будет способен вставлять записи, но только так, как определено в этом операторе. Точно так же, если в свойстве DeleteSQL определен оператор DELETE, НД будет способен удалить запись или записи, определенные в этом операторе, и т. д. Действия пользователя являются своеобразным
^спусковым крючком», заставляя компонент автоматически выполнить нужный оператор. При этом если эти действия не совпадают с действиями, определенными дополнительными SQL-операторами, они отвергаются. Например, пусть в свойстве Modi fySQL записан следующий оператор:
UPDATE Credit SET Summ=l WHERE N_Count=2
При наличии этого оператора какие бы изменения в какие бы записи ни вносил пользователь, фактически один раз будет выполнен указанный выше оператор и запись (записи) из таблицы БД Credit со значением столбца N_Count = 2 получит в столбце Summ значение 1. Причем в сеткег отображающей НД, изменения будут видны так, как они сделаны пользователем, но фактически в таблице БД изменения окажутся другими — они «проявятся» после повторного открытия НД. Замечу, что, если в свойство RefreshSQL поместить такой же оператор, как и в основное свойство SelectSQL, все изменения в реальных данных станут видимыми немедленно, поэтому в сетке пользователь увидит не свои изменения, а те, что фактически сделаны соответствующими SQL-операторами.
Свойства компонента TlBDataSet перечислены в табл. 6.11.
Таблица 6.11. Свойства компонента TlBDataSet
Свойство
Описание
property Bufferchunks: Integer;
Указывает, на сколько записей будет увеличиваться буфер компонента по мере его наполнения
property Database: TIBDatabase;
Содержит ссылку на связанный компонент
TIBDatabase
property DBHandle : IntPtr;
Содержит дескриптор набора данных
property DeleteSQL: TStrings;
Содержит SQL- предложение для удаления записей. Если свойство содержит пустую строку, в НД нельзя удалять записи
property InsertSQL: TStrings;
Содержит SQL-предложение для вставки записей. Если свойство содержит пустую строку, в НД нельзя вставлять записи
property Modi fySQL : TStrings;
Содержит SQL-предложение для изменения записей. Если свойство содержит пустую строку, в НД нельзя редактировать записи
property Params: TIBXSQLDA;
Содержит параметры для параметрического запроса
property Prepared: Boolean;
Если содержит True, осуществляется подготовка перед исполнением запроса
property QDelete: TIBSQL;
Содержит ссылку на объект, который инкапсулирует предложение delete
property QInsert: TIBSQL;
Содержит ссылку на объект, который инкапсулирует предложение INSERT
Компоненты для реализации технологии 283
Свойство
Описание
property QModify: TIBSQL;
Содержит ссылку на объект» который инкапсулирует предложение UPDATE
property QRefresh : TIBSQL;
Содержит ссылку на объект, который инкапсулирует предложение REFRBSHSQL
property QSelect: TIBSQL;
Содержит ссылку на объект, который инкапсулирует предложение SBLBCT
property Ref reshSQL : TStrings;
Содержит SQL-предложение, позволяющее обновить НД. Обычно оно просто совпадает с предложением SelectSQL
property SelectSQL: TStrings;
Содержит предложение SBLECT, создающее НД
property StatementType: TIBSQLTypes;
Содержит тип SQL-предложения (см. далее)
property Transaction:
TIBTransaction;
Содержит ссылку на связанный компонент
TIBTransaction
property TRHandle: IntPtr;
Содержит дескриптор транзакции
property UpdateObj ect :
TIBDataSetUpdateObject;
Содержит ссылку на компонент TIBUpdate- SQL, с помощью которого можно обновить НД только для чтения
type TI BUpda teRecordTypes = set of (cusModified, cuslnserted, cusDeleted, cusunmodi fied, cusUninserted);
property Upda t eRe cordType s : TIBUpdateRecordTypes;
Указывает, какие записи в кэшированном наборе видны при обновлении: cusModified — модифицированные записи; cuslnserted — вставленные записи; cusDeleted — удаленные записи; cusUnmodifled — только неизмененные записи; cusUninserted — только не вставленные записи
property UpdatesPending : Boolean;
Указывает, содержит ли буфер обновления записи
Определение типа для свойства Statementiype:
type TIBSQLTypes = set of (SQLUnknown, SQLSelect, SQLInsert, SQLUpdate, SQLDelete, SQLDDL, SQLGetSegment, SQLPutSegment, SQLExecProcedure, SQLStartTransaction, SQLCoinmit, SQLRollback, SQLSelectForUpdate, SQLSetGenerator);
Здесь:
SQLUnknown — тип неизвестен;
SQLSelect — предложение SBLBCT;
SQLInsert — предложение 工N8HRT;
SQLUpdate — предложение BDATE; е SQLDelete — предложение DBLBTE;
SQLDDL — предложение на языке DDL;
SQLGetSegment — читает часть открытого BLOB-столбца;
SQLPutSegment — записывает часть BLOB-столбца;
SQLExecProcedure — выполняет хранимую процедуру;
SQLStartTransaction — стартует новую транзакцию;
SQLCommit — подтверждает транзакцию;
SQLRollback — откатывает транзакцию;
SQLSelectForUpdate — хранимая процедура представляет собой набор предложений для обыовления данных;
SQLSetGenerator — устанавливает новое значение для генератора.
Специфические методы компонента TIBDataSet перечислены в табл. 6.12.
Таблица 6.12. Методы компонента TIBDataSet
Метод
Описание
procedure ApplyUpdates;
Переписывает изменения кэшированных данных в таблицу БД, но не завершает транзакцию
type TCachedUpdateStatus = (cu sUnmodi f ied, cusModified, cuslnserted, cusDeleted, cusUninserted);
function CachedUpdateStatus: TCachedUpdateStatus;
Возвращает статус кэишрованных изменений: cusUrimodif ied — данные не редактировались; cusModif ied — данные редактировались; cuslnserted — были вставлены записи; cusDeleted — были удалены записи; cusUninserted — записи не вставлялись
procedure Cancelupdates ;
Очищает буфер изменений
procedure FetchAll;
Получает все записи от текущей до конца файла и сохраняет их локально
function GetFieldData (FieldNo:
Integer; Buffer: IntPtr):
Boolean;
Читает в буфер Buffer данные из столбца по его номеру FieldNo или из объекта-гюля Field
function GetFieldData (Field:
TField; Buffer: IntPtr) : Boolean;
function LocateNext (const KeyFields: String; const KeyValues: Variant; Options: TLocateOpt ions): Boolean
Позиционирует курсор на запись ниже текущей: KeyFields — имя ключевого столбца; KeyValues — искомое значение; Options — дополнительные условия поиска
procedure Prepare;
Подготавливает компонент к выполнению запроса
procedure UnPrepare ;
Освобождает ресурсы, занятые при выполнении метода Prepare
В отличие от стандартного метода Locate, который, как и Lookup, доступен компоненту, метод LocateNext ищет запись от текущей к концу НД.
Специфические события компонента TIBDataSet перечислены в табл. 6.13.
Таблица 6.13. События компонента TIBDataSet
Событие
Описание
property Dat aba s eDi s connected : TMotifyEvent;
Возникает после разрыва соединения с БД
property DatabaseDisconnecting:
TNotifyEvent;
Возникает перед разрывом соединения с БД
property DatabaseFree :
Возникает при разрушении связанного ком-
TNotifyEvent;
понента TIBDatabase
Компонент TIBSQL
Компонент TIBSQL предназначен для выполнения SQL-запросов с минимальными затратами времени. Он не может быть связан с компонентом TDataSource н, следовательно, с визуализирующими компонентами. В отличие от других компонентов-наборов; компонент TIBSQL происходит непосредственно от компонента TComponent, поэтому все его свойства, методы и события ссвои», хотя многие из них в функциональном отношении повторяют одноименные свойства, методы и события других компонентов-наборов.
Для ускорения доступа к данным компонент использует специальные классы записей и полей. Он создает однонаправленный курсор, так что перемещение по НД возможно только сверху вниз. Наконец, он лишен многочисленных событий AfterXXXX, BeforXXXX, а также OnCalcField, так что в НД нельзя создать вычисляемые поля или реализовать бизнес-правила на основе обработчиков этих событий.
Специфические свойства компонента TIBSQL перечислены в табл. 6.14.
Таблица 6.14. Свойства компонента TIBSQL
Свойство
Описание
property Bof : Boolean;
Содержит True, если курсор стоит перед первой записью НД
property Database: TIBDatabase;
Содержит ссылку на связанный компонент TIBDatabase
property DBHandle: IntPtr;
Содержит дескриптор БД
property Eof : Boolean;
Содержит True, если курсор стоит после последней записи НД
property Fieldindex: [FieldName: String]: Integer;
Возвращает индекс столбца по его имени
property Fields [const Idx:
Открывает индексный доступ к столбцам НД
Integer]: TIBXSQLVAR;
в формате TIBXSQLVAR (см. далее)
Таблица 6.14 (продолжение)
Свойство
Описание
property GenerateParamNames:
Если содержит True, компонент создает име-
Boolean;
property
GoToFirstRecordOnExecute:
на параметров для параметрического запроса Если содержит True, курсор сразу после открытия НД устанавливается на его первую
Boolean;
property Handle: IntPtr;
property Open : Boolean;
property ParamCheck: Boolean;
запись
Содержит дескриптор запроса
Содержит True, если НД открыт
Если содержит True, параметры параметрического запроса проверяются перед его выполнением
property Params: TIBXSQLDA;
Содержит параметры запроса в формате TIBXSQLDA (см. далее)
property Plan: String;
Содержит план выполнения запроса после его подготовки
property Prepared: Boolean;
Содержит True, если запрос был подготовлен методом Prepare
property Recordcount : Integer;
property RowsAf fected: Integer;
Содержит количество записей в запросе Возвращает количество записей, которые были изменены в результате выполнения запроса
property SQL : TStrings;
Содержит текст запроса
property SQLType: TIBSQLTypes read FSQLType;
Содержит тип запроса (тип TIBSQLTypes см. в описании свойства StatexnentType компонента TlBDataSet в разделе <Компонент TIBDataSet»)
property Transaction:
Содержит ссылку на связанный компонент
TIBTransaction;
property TRHandle: IntPtr;
TIBTransaction
Содержит дескриптор транзакции
property UniqueRelationName:
String;
Используйте это свойство, чтобы указать уникальное реляционное имя для запроса, касающегося одной таблицы
Тип tibxsqlvar содержит практически те же методы приведения типов ASXXXY, как и《обычный» тип TField, а его свойство Value имеет тип Variant. Таким образом, работа со значениями столбцов компонента TIBSQL практически не отличается от работы со значениями столбцов других компонентов-наборов. Это же замечание относится к типу TIBXSQLDA и работе со значениями параметров. Указанные типы поддерживают специфику скоростной работы компонента.
Методы компонента TIBSQL перечислены в табл. 6.15.
Таблица 6<15. Методы компонента TIBSQL
Метод
Описание
procedure Batchinput
Выполняет параметрический запрос для объ-
(Inputobject: TIBBatchlnput);
екта Inputobject
procedure Batchoutput
Выполняет параметрический запрос для объ-
(Outputobject : TIBBatchOutput);
екта Outputobject
procedure CheckClosed;
Возбуждает исключение, если запрос не закрыт
procedure CheckOpen;
Возбуждает исключение, если запрос закрыт
procedure CheckValidStatement;
Возбуждает исключение, если SQL-предложение ошибочно
procedure Close;
Закрывает запрос
function Current: TIBXSQLDA;
Возвращает дескриптор текущей записи
procedure ExecQuery;
Выполняет запрос
function FieldByName [FieldName:
String]: TIBXSQLVAR;
Возвращает столбец по его имени
procedure FreeHandle;
Освобождает ресурсы InterBase, связанные с запросом
function Next: TIBXSQLDA;
Смещает курсор к следующей записи
procedure Prepare;
Готовит запрос к выполнению
Нетрудно обнаружить, что единственным навигационным методом является метод Next* Таким образом» последовательный просмотр записей НД возможен только от начала набора к его концу.
Компонент имеет единственное событие, которое возникает при изменении SQL-запроса:
property OnSQLChanging: TNotifyEvent;
Компонент TIBDatabaselnfo
Компонент TIBDatabaselnfo предназначен для предоставления программе дополнительной служебной информации о присоединенной базе данных. Компонент не имеет специфических методов и событий. Свойства компонента TIBDatabaselnfo перечислены в табл. 6Л6.
Таблица 6.16. Свойства компонента TIBDatabaselnfo
Свойство
Описание
property Allocation: Longlntlnt;
Возвращает количество распределенных в памяти страниц БД
property BackoutCount:
Возвращает количество удаленных версий
TStringList;
страниц
288 Глава 6 • Технология IBX.NET
Таблица 6.16 (продолжение)
Свойство
Описание
property BaseLevel : Smalllnt;
Возвращает 2-байтный номер версии БД
property CurrentMemory: Longlntlnt;
Возвращает объем памяти (в байтах)» используемый сервером
property Database: TIBDatabase;
Содержит ссылку на связанный компонент
TIBDatabase
property DBFileName: String;
Возвращает имя БД
property DBlmplementationClass: Integer;
Возвращает номер реализуемого класса БД
property DBlrnp 1 ementat i onNo : Integer;
Возвращает номер реализации БД
property DBSiteName: String;
Возвращает имя сайта БД (обычно совпадает с именем компьютера, на котором она расположена)
property DBSQLDialect: Integer;
Возвращает используемый в БД диалект SQL
property DeleteCount : TStringList;
Всивращает список БД, которые былн удалены с момента последнего присоединения к ней пользователя
property ExpungeCount: TStringList;
Возвращает количество удаленных записей
property Fetches: Integer;
Возвращает количество записей, прочитанных в локальный буфер
property ForcedWrites : Integer;
Возвращает номер режима записи в БД: 0 — асинхронный режим; 1 — синхронный режим
property Insertcount: TStringList;
Возвращает количество вставленных записей
property Marks : Integer;
Возвращает количество записей в буфер кэша
propertyMaxMemory: Integer;
Возвращает максимальный объем памяти в байтах, который использовался с момента первого присоединения к БД
property NoReserve : Integer ;
Указывает, резервировалась ли память для сохранения устаревших записей (0 — резервировалась)
property NumBuf fers: Integer;
Возвращает количество распределенных бу- ф^юв кэша
property PageSize: Integer;
Возвращает размер страницы в байтах
property Sweepinterval : Integer;
Указывает, сколько транзакций должно успешно завершиться до момента ароматической чистки страниц БД от ненужных версий записей
property UserNames: TStringList;
Содержит список имен всех пользователей, присоедипештых к БД
Компонент TIBSQLMonitor
Компонент TIBSQLMonitor предназначен для создания отладочного инструментария. С помощью этого инструментария программист может осуществлять мониторинг всех SQL-предложений, которыми обмениваются клиент и сервер. Для мониторинга следует установить нужные флаги в свойство TraceFlags связанного компонента TIBDatabase (см. раздел «Компонент TIBDatabase»).
Компонент TIBSQLMonitor не имеет собственных свойств и методов. Единственное событие возникает, если клиент передал серверу SQL-предложение, тип которого выбран флагами TraceFlags:
TSQLEvent = procedure(EventText: String) of object; property OnSQL: TSQLEvent;
В этом случае обработчик события в параметре EventText может прочитать соответствующее сообщение.
Компонент TIBExtract
Компонент TIBExtract впервые появился в версии 7 Delphi. Он предназначен для получения так называемых метаданпых — списков таблиц, индексов, хранимых процедур и тому подобных сущностей БД. Использовать его довольно просто. В свойства Database и Transact ion компонента нужно поместить ссылки на соответствующие связанные компоненты, после чего с помощью метода ExtractObj ect компонент может прочитать в свое свойство Items нужную информацию. Например, следующий обработчик покажет в многострочном текстовом поле список всех таблиц БД с указанием их определений:
procedure TForml.Buttoniclick(Sender: TObject); begin
IBDatabasel.Connected := True;
IBExtractl.Extractobject(eoTable);
Memol.Lines.Assign(IBExtractl.Items); end;
Метод Extractobject определен следующим образом:
procedure ExtractObject(ObjectType : TExtractObjectTypes;
ObjectName : String 二 1 ' ; ExtractTypes : TExtrace.Types 二[】);
Единственный обязательный параметр ObjectType определяет вид нужных метаданных и может иметь одно из следующих значений:
eoDatabase — получить список всех баз данных;
eoDomain — получить список доменов;
еоТаЫе — получить список таблиц;
eoView — получить список представлений;
eoProcedure — получить список хранимых процедур;
eoFunction — получить список внешних (пользовательских) функций;
10 Зак. 449
eoGenerator — получить список генераторов;
eoException — получить список исключений;
eoBLOBFilter — получить список BLOB-фильтров;
eoRole — получись ехшсок рол曲;
eoTrigger — получить список диггеров;
eoForeign — получить список внешних ключей;
eolndexes — получить список индексов;
eoChecks — получить список проверяемых ограничений;
eoData — получить все данные объекта Obj ectName.
Параметр ObjectName определяет имя сущности. Если он опущен, будет получена информация обо всех сущностях данного вида. Параметр ExtractTypes содержит набор уточншоших флагов.
Хранимые процедуры, триггеры и представления
Описываемые в этой главе механизмы типичны только для клиент-серверных БД. Они позволяют перенести на сервер реализацию части бизнес-правил и, таким образом, значительно снизить нагрузку на сеть.
Создание хранимых процедур
Хранимая процедура создается следующим оператором:
CRSATE PROCBDURB ИМЯПроцедурЫ
[(<входной_параметр> <тип_данных>
[,<входной_^араметр> <тип^данных> ..,])]
[RETURNS
(<вьлходнойвпараметр> <тигсдаиных>
[г<выходной_параметр> <тип_^анных> ...])]
AS
[<объявление локальных переменных>]
BSGIN
<оператор>;
[<оператор>;-..]
END
Входные параметры служат для передачи в процедуру значений из вызывающего приложения. Изменять значения входных параметров в теле процедуры бессмысленно —эти изменения будут потеряны после окончания работы процедуры. Выходные параметры служат для возвращения результирующих значений. Значения выходных параметров устанавливаются в теле процедуры и после окончания ее работы передаются в вызывающее приложение.
Как входные, так и выходные параметры могут быть опущены, если в них нет необходимости.
В следующем примере описывается хранимая процедура, которая по номеру накладной возвращает список связанных с ней книг:
CREATE PROCEDURE Books„For_Nakl (Nakl 工NT) RETURNS
(Name VARCHAR(150) , Quan SMALLXKT, Price FLOAT, Summa FLOAT)
AS
DECLARS VARIABLE Aut VARCHAK(40);
DECLARE VARIABLE Pub VARCHAR(40); BEGIN
FOR SBLBCT BName, BAuthorx BPublish, MQuan, MPrice, MQuan*MPrice FROM Books, Moves ИНВЙЕ NaklID=:Nakl AND BookID=MBook ORDER BY BName
INTO :Name, :Aut, :Pub, :Quan, :Price, :Summa DO
BEGIN
Name = Name II*/ 'I IAutI!1/ * I I Pub; SUSPEND;
BKD BND
Для вызова хранимой процедуры, возвращающей набор данных (как в представленном примере), используется компонент-запрос (TQuery, TIBQuery и т. п.). Покажем, как можно использовать хранимую процедуру BOOKS_FOR〜NAKL для вывода списков книг при просмотре накладных NAKLS:
С помощью утилиты IBConsoly или SQL Explorer создайте показанную ранее процедуру BOOKS_FOR_NAKL для БД IB__BIBL.
Начните новый VCL-проект и поместите на пустую форму компоненты TDatabase, TTable и TQuery (категория BDE).
С помощью свойства AliasName свяжите компонент Databasel с БД IB_BIBL Поместите в его свойство DatabaseName локальный псевдоним А.
Выберите в списке свойства DatabaseName компонента Tablel псевдоним А, в списке свойства Tabi eName — таблицу NAKLS и откройте НД. Назовите его по имени таблицы — NAKLS и создайте для него объекты-поля.
Свяжите компонент Queryl с псевдонимом А и разместите в его свойство SQL такой параметрический запрос:
SELECT * FROM BOOKS_FOR_NAKL (:NAKLID)
Раскройте окно свойства Params запроса и настройте параметр NAKLID: DataType " f tlnteger; ParamType = pt Input. Назовите компонент по имени детальной таблицы MOVES и создайте для него объекты-поля.
С помощью трех панелей ТРапе 1 разбейте поверхность формы на три части: поместите в свойства Align двух из них значения alBottom, а в такое же свойство третьей — значение alClient.
Разместите на форме два источника TDataSource. Свяжите один с НД NAKLS, а второй — с НД MOVES. Для НД MOVES в свойстве DataSource сошлитесь на источник, связанный с главным НД NAKLS.
Для создания подстановочных полей поместите на(};орму еще два компонента TTable и свяжите один с таблицей FIRMS, а второй — с таблицей TYPES.
Вид окна работающей программы показан на рис. 7.1.
晔4дата:":■[履力晶"]:「二"二[一][1 ;01,03.2000 ;Точка. Сооиальшй университет2^1,0Э,2000:Яймер3:01,03.2000 ikKC ООО•» .01.03.2000 ДЕСС-Пдблишерэ晔4дата:":■[履力晶"]:「二"二[一][1 ;01,03.2000 ;Точка. Сооиальшй университет2^1,0Э,2000:Яймер3:01,03.2000 ikKC ООО•» .01.03.2000 ДЕСС-ПдблишерэJMrtjhyj^o^rF……;‘I■ ГХхздажа на ре&мзлцкюПродажа с предоплатойJMrtjhyj^o^rF……;‘I■ ГХхздажа на ре&мзлцкюПродажа с предоплатой]&^F"倡;』7d^$P^;*」&ff]&^F"倡;』7d^$P^;*」&ff550.00 : 1,00335,92: 1,СМ550.00 : 1,00335,92: 1,СМПродажа ил рейгнмиию 45 337,50; 0,75Продажа ил рейгнмиию 45 337,50; 0,75—5 .01.03,2000,Ро№нчнм гродаж*► ^§01.03,2000 Jog мгиэм7:01.03.2000 000Издательсюо"Нолидж"—5 .01.03,2000,Ро№нчнм гродаж*► ^§01.03,2000 Jog мгиэм7:01.03.2000 000Издательсюо"Нолидж"Прихол ло обмену Прона»» с предоплатой Продажа на рмлнзацию Поставка на реалимцнюПрихол ло обмену Прона»» с предоплатой Продажа на рмлнзацию Поставка на реалимцнюб 782,00; 234,00 :2 32в,70155 610.00:б 782,00; 234,00 :2 32в,70155 610.00:1,00 зсн 1,10 L001,00 зсн 1,10 L000,00. 335,92;0,00: 二瀛: 234,000,00.:0,00. 335,92;0,00: 二瀛: 234,000,00.:60 201.6560 201.65550,00 纯 04.2000 0,00^31.03.2000 0,00Ц0.04.20(Ю> О^6]О1.О3.26Ь6'- 0,00^02.03.200032870 jM.M.ZOOO-550,00 纯 04.2000 0,00^31.03.2000 0,00Ц0.04.20(Ю> О^6]О1.О3.26Ь6'- 0,00^02.03.200032870 jM.M.ZOOO-95 408,35^30.04.2000^95 408,35^30.04.2000^—>^!В?с»<^¥АггЬр/ИмУДКт.8 二 …•..••;;.:•:> Введение в MATLA6/ Потемк* Диалог-МифиИсторий фшюсофии. Учебник для студентов ВУЗов/ Кохановскнй/ ФениксИстория жонсмкги: Учебник для высшей шкалы/ Комотопов/ Акадвм»««ский rpowrИстория эконожческкх учен»»!/ Бяпоусов/ Феникс'Философия .Учвбьмк для XXI века/ Камке/ Логос—>^!В?с»<^¥АггЬр/ИмУДКт.8 二 …•..••;;.:•:> Введение в MATLA6/ Потемк* Диалог-МифиИсторий фшюсофии. Учебник для студентов ВУЗов/ Кохановскнй/ ФениксИстория жонсмкги: Учебник для высшей шкалы/ Комотопов/ Акадвм»««ский rpowrИстория эконожческкх учен»»!/ Бяпоусов/ Феникс'Философия .Учвбьмк для XXI века/ Камке/ ЛогосR話 j R^j2yxi^7R話 j R^j2yxi^735,20“ 25]呼,00:35,20“ 25]呼,00:29,70 44,00 45J0 57,2029,70 44,00 45J0 57,2015: 445,50;4- 176,00- 炽 541,20; 5,逆,p0;15: 445,50;4- 176,00- 炽 541,20; 5,逆,p0;
晔4дата:":■[履力晶"]:「二"二[一][
1 ;01,03.2000 ;Точка. Сооиальшй университет
2^1,0Э,2000:Яймер
3:01,03.2000 ikKC ООО
•» .01.03.2000 ДЕСС-Пдблишерэ
晔4дата:":■[履力晶"]:「二"二[一][
1 ;01,03.2000 ;Точка. Сооиальшй университет
2^1,0Э,2000:Яймер
3:01,03.2000 ikKC ООО
•» .01.03.2000 ДЕСС-Пдблишерэ
JMrtjhyj^o^rF……;‘I■ ГХхздажа на ре&мзлцкюПродажа с предоплатой
JMrtjhyj^o^rF……;‘I■ ГХхздажа на ре&мзлцкюПродажа с предоплатой
]&^F"倡;』7d^$P^;*」&ff
]&^F"倡;』7d^$P^;*」&ff
550.00 : 1,00
335,92: 1,СМ
550.00 : 1,00
335,92: 1,СМ
Продажа ил рейгнмиию 45 337,50; 0,75
Продажа ил рейгнмиию 45 337,50; 0,75
—5 .01.03,2000,Ро№нчнм гродаж*
► ^§01.03,2000 Jog мгиэм
7:01.03.2000 000Издательсюо"Нолидж"
—5 .01.03,2000,Ро№нчнм гродаж*
► ^§01.03,2000 Jog мгиэм
7:01.03.2000 000Издательсюо"Нолидж"
Прихол ло обмену Прона»» с предоплатой Продажа на рмлнзацию Поставка на реалимцню
Прихол ло обмену Прона»» с предоплатой Продажа на рмлнзацию Поставка на реалимцню
б 782,00; 234,00 :
2 32в,70
155 610.00:
б 782,00; 234,00 :
2 32в,70
155 610.00:
1,00 зсн 1,10 L00
1,00 зсн 1,10 L00
0,00. 335,92;
0,00: 二瀛: 234,00
0,00.:
0,00. 335,92;
0,00: 二瀛: 234,00
0,00.:
60 201.65
60 201.65
550,00 纯 04.2000 0,00^31.03.2000 0,00Ц0.04.20(Ю> О^6]О1.О3.26Ь6'- 0,00^02.03.2000
32870 jM.M.ZOOO-
550,00 纯 04.2000 0,00^31.03.2000 0,00Ц0.04.20(Ю> О^6]О1.О3.26Ь6'- 0,00^02.03.2000
32870 jM.M.ZOOO-
95 408,35^30.04.2000^
95 408,35^30.04.2000^
—>^!В?с»<^¥АггЬр/ИмУДКт.8 二 …•..••;;.:•:
> Введение в MATLA6/ Потемк* Диалог-Мифи
Историй фшюсофии. Учебник для студентов ВУЗов/ Кохановскнй/ Феникс
История жонсмкги: Учебник для высшей шкалы/ Комотопов/ Акадвм»««ский rpowr
История эконожческкх учен»»!/ Бяпоусов/ Феникс
'Философия .Учвбьмк для XXI века/ Камке/ Логос
—>^!В?с»<^¥АггЬр/ИмУДКт.8 二 …•..••;;.:•:
> Введение в MATLA6/ Потемк* Диалог-Мифи
Историй фшюсофии. Учебник для студентов ВУЗов/ Кохановскнй/ Феникс
История жонсмкги: Учебник для высшей шкалы/ Комотопов/ Акадвм»««ский rpowr
История эконожческкх учен»»!/ Бяпоусов/ Феникс
'Философия .Учвбьмк для XXI века/ Камке/ Логос
R話 j R^j2yxi^7
R話 j R^j2yxi^7
35,20“ 25]呼,00:
35,20“ 25]呼,00:
29,70 44,00 45J0 57,20
29,70 44,00 45J0 57,20
15: 445,50;
4- 176,00- 炽 541,20; 5,逆,p0;
15: 445,50;
4- 176,00- 炽 541,20; 5,逆,p0;
:L#F:I可” r1外卜也吐(h…
Рис. 7.1. Использование хранимой процедуры для создания детального НД
Алгоритмический язык процедур и триггеров
Хранимые процедуры и триггеры кодируются на специальном алгоритмическом языке, в основе которого лежит язык SQL, дополненный локальными переменными, условными, циклическими операторами, операторами присваивания н некоторыми другими средствами. Отдельные операторы могут располагаться на нескольких строках и отделяются друг от друга точкой с запятой. Регистр букв в операторах не имеет значения. В любом месте программы можно поставить комментарий, обрамленный парой символов / * и * /. Символы каждой пары, а также символы операций сравнения >=, <=, о, !二(не равно), !< (не меньше), !> (не больше) не должны разрываться пробелами.
Локальные переменные
Локальные переменные объявляются для тех же целей, что и переменные в Delphi: они служат для временного запоминания промежуточных результатов вычислений. Объявление переменной имеет такой формат:
DECLARE VARIABLE <имя_переменной тип>;
Если локальные переменные, входные или выходные параметры указываются в теле SQL-оператора, их именам должны предшествовать двоеточия. В других операторах имя переменной указывается без двоеточия (см. представленный ранее пример).
Операторные скобки
Операторные скобки B2GIN...KND во всем подобны своим аналогам в Delphi: они ограничивают тело процедуры (триггера), и с их помощью создается составной оператор. Допускается произвольная глубина вложенности операторных скобок. В отличие от Delphi, перед словом END нельзя опускать точку с запятой (;)— символ-разделитель операторов.
Оператор SELECT
В отличие от SQL-оператора, в процедурном операторе SELECT допускается использование следующей секиии, с помощью которой можно указать локальные переменные и/или выходные параметры:
XNTO :<переменная> [, :<переменная>...]
В выходные параметры оператор должен поместить единичные возвращаемые значения или значения полей для каждой записи, если возвращается множество записей. В списке после зарезервированного слова INTO именам переменных и выходных параметров должны предшествовать двоеточия.
Условный оператор
Условный оператор имеет формат
XF (<условное—выражение>) THEN <оператор1> [ELSB <оператор2>]
В отличие от Delphi, в процедурном условном операторе условное выражение должно заключаться в круглые скобки. Условное выражение строится из знаков операций сравнения и логических операций AND, OR, NOT. Приоритет операций сравнения меньше, чем логических операций, что избавляет от необходимости расстановки группирующих скобок:
XF (NSum>0 AND NType XN (0, 6)) THEN •••
Операторы FOR и SUSPEND
Оператор FOR предназначен для получения множества значений^ Он имеет такой формат:
FOR SBLKCT <тело оператора SELECT> XNTO <список переменных> DO <оператор>
Для каждой записи, извлекаемой оператором SELECT, выполняется оператор <оператор>, которым часто бывает оператор SUSPEND. Этот оператор приоста-
навливает работу процедуры до тех пор, пока вызывающая программа не потребует очередной порции данных. На основе операторов FOR и SUSPEND строятся процедуры, возвращающие наборы данных.
Оператор присваивания
Оператор присваивания служит для занесения значения выражения в переменную или выходной параметр:
<переменная> = <выражение>
Выражение и переменная должны быть совместимого типа. Перед знаком равенства двоеточие не ставится. Имена переменных и выходных параметров в обеих частях оператора указываются без двоеточия. Поскольку в InterBase нет логического типа, выражение может быть только арифметическим или строковым. В арифметическом выражении используются четыре арифметические операции, поля, переменные, константы и обращения к функциям пользователя. В строковом выражении допустима единственная операция I I, определяющая конкатенацию (сцепление) строк.
Операторы WHILE и EXIT
Оператор WHXLB соответствует аналогичному оператору Delphi:
WHXL5 (<условие>) DO <оператор>
Оператор EXIT служит для принудительного завершения работы процедуры (в триггере оператор EXIT использовать нельзя):
IF (NType IN (2,3)) THBN BXIT;
Оператор EXECUTE PROCEDURE
С помощью оператора EXBCUTB PROCEDURB процедура (триггер) может обратиться к другой хранимой процедуре (к триггеру обратиться нельзя). Формат оператора:
EXECUTE PROCEDURB <имя> [<параметр> [, <параметр> ...]] [RETURNXNG_VAIjUES : <переменная> [, : <переменная> ...]];
После имени вызываемой процедуры перечисляются входные параметры, если они есть, а после ВВТШШ工NGJVALUES — локальные переменные и/или выходные параметры, в которые вызываемая процедура должна поместить результат обращения. Именам переменных должны предшествовать двоеточия.
Оператор EXECUTE PROCEDURE предназначен для обращения к так называемым процедурам действия, которые либо вообще не возвращают значений, либо возвращают лишь один экземпляр группы значений. Таким образом, процедуры действия не создают наборов данных. Для обращения к таким процедурам из программы предназначен специальный компонент TStoredProc (TADOStoredProc, TSQLStoredPros и т. п.).
Исключения
С помощью следующего оператора процедура (триггер) может возбудить исключение:
EXCEPTION <имя_исключения>;
Процедурное исключение имеет собственное имя <имя_исключения> и предварительно создается оператором
CRBATB EXCEPTION <имя^иcключeния>и<copбщeыиe>,^;
Здесь <сообщение> — произвольный текст. Обработка этого оператора осуществляется блоком WHEN…DO, который имеет такой формат:
WHEN {<ошибка> [, <ошибкам ...] I ANY}
DO <оператор>
<ошибка>=
{EXCEPTION <имя_исключения> I 8QLC0DE <номер> I GDSCODE
<КОД„О111ИбкИ>
Здесь:
EXCEPTION, SQLCODE, QDSCODE — зарезервированные слова;
<номер> — код ошибки SQL;
<код_ошибки> — код ошибки InterBase;
ANY — зарезервированное слово, определяющее обработку любых ошибок;
<оператор> — любой оператор или блок BEGXN...BND.
Блок WHBN...DO должен стоять непосредственно перед ключевым словом ENDt даже если ему предшествует слово SUSPEND.
Если возбуждено исключение, выполнение текущего блока прекращается и управление передается блоку WHEN...DO. Если такового нет или в нем не предусмотрена реакция на данное исключение, ищется блок WHKK...DO в блоке более высокого уровня и т. д. Если исключение не обработано, выполнение процедуры прекращается, ликвидируются все сделанные ею изменения и выдается сообщение <сообщение> (если исключение обработано оператором <оператор> в блоке WHEN…DO, сообщение не выдается).
Пусть в БД имеется таблица Users со списком всех сотрудников, имеющих те или иные права доступа к данным. Среди них есть сотрудник Иванов с неограниченными правами доступа, данные о котором из таблицы удалять нельзя. Создадим исключение:
CRBATE EXCEPTION No..Delete * Нельзя удалить пользователя Иванова!*
Кроме того, создадим триггер:
CREATE TRIGGBR Bef_Del_Users FOR Users
BEFORE DELETE AS
BEGIN
IP (old.Name = 'Иванов') ТН2Ы
BXCEPTION No_Delete;
BND
Теперь попытаемся очистить всю таблицу следующим оператором: delete from users
В этом случае появится соответствующее сообщение и все записи таблицы будут сохранены.
Замечу, что объявленные в БД исключения можно увидеть, раскрыв узел Exceptions в окне утилиты SQL Explorer. Однако если среди них есть хотя бы одно, текст которого набран кириллицей, этот список станет недоступным.
Компоненты доступа к хранимым процедурам
Как уже говорил ось, если хранимая процедура возвращает набор данных, ее вызов помещается в компонент-адаптер (для технологии ADO.NET) или в компонент-запрос (остальные технологии), В этом разделе рассматриваются компоненты для доступа к процедурам, возвращающим единичное значение или единственный экземпляр нескольких значений. Такие процедуры называются процедурами действия.
Компонент TStoredProc
Компонент TStoredProc используется в технолоши BDE.NET и предназначен для обращения к процедурам действия. При работе с сервером InterBase он не может создать механизм курсора, поэтому его нельзя использовать в качестве НД. Для серверов другого типа (например, Oracle и Microsoft SQL Sever) компонент TStoredProc может служить в качестве НД.
Свойства компонента TStoredProc перечислены в табл. 7.1.
Таблица 7.1. Свойства компонента TStoredProc
Свойство
Описание
type TParamBindMode = (pbByName, рЬВуЫшпЬегJ;
property ParamBindMode : TParamBindMode;
Устанавливает способ связи параметров компонента с параметрами процедуры: pbByName — по имени (в этом случае нмена параметров компонента должны совпадать с именами параметров процедуры); pbByNumber — по номеру (1-й с 1-м, 2-й со 2-м и т. д.)
property ParamCount: Word;
Содержит количество параметров процедуры
property Params: TParams;
Открывает доступ к параметрам процедуры (см. далее)
property Prepared : Boolean;
Если содержит True, процедура подготовлена к работе (см. далее)
property StoredProcName: String;
Указывает имя процедуры
Свойство Params имеет тип ТРагашз, который представляет собой класс со свойствами Count, Items и ParamValue. Свойство Count указывает количество параметров компонента. Другое свойство открывает доступ к значению параметра по его имени:
property ParamValues[const ParamName: String]: Variant;
Еще одно свойство позволяет получить описание параметра по его индексу:
property Items[Index: Word]: TParam;
Описание задается классом TParam, который содержит тип параметра (входной, выходной или входной и выходной), тип его значения, его имя и значение по умолчанию. Эти свойства можно проверить и установить в окне инспектора объектов. Для этого сначала задается псевдоним БД в свойстве DatabaseName, затем с помощью раскрывающегося списка свойства StoredProcName выбирается нужная хранимая процедура. В этот момент компонент считывает из БД описание параметров процедуры и соответствующим образом настраивает свое свойство Params. Теперь после двойного щелчка иа компоненте или с помощью коман* ды Fields Editor его контекстного меню можно вызвать окно редактора параметров и работать с параметрами так, как если бы они были объектами-полями компонентов ТТаЫе и TQuery.
Получить или установить значение параметра можно с помощью свойства Params.ParamValues:
spNakls.Params.ParamValues[*Nakl*].Aslnteger := 123;
Свойство Prepared позволяет подготовить процедуру к выполнению. Подготовка заключается в том, что сервер оптимизирует выполнение и компиляцию процедуры, после чего сохраняет результат компиляции. Это сокращает до минимума время обращения к процедуре. Если в свойство поместить значение False, сервер освободит ресурсы, выделенные для хранения результата компиляции, и при каждом обращении к процедуре всякий раз будет заново готовить ее к выполнению.
Важнейшие методы компонента TStoredProc перечислены в табл. 7.2.
Таблица 7.2. Методы компонента TStoredProc
Метод
Описание
procedure ЕхесРгос;
Требует от сервера выполнить процедуру
procedure GetResults;
Возвращает результат обращения к процедуре для серверов Sybase и MS SQL Server
function ParamByName(const value: String): TParam;
Позволяет обратиться к параметру по его имени
В отличие от свойства Params .ParamValues, функция ParamByName возвра- тает объект класса ТРагаш, содержащий не только значение параметра, но и все
Компоненты доступа к хранимым процедурам 299
другие его свойства (имя, тип и т. д.). Класс TParam содержит свойства AsXXXX, позволяющие обратиться к значению параметра:
spNakls.ParamByName(*Nakl*).Aslnteger := 123;
Общая схема работы с компонентом такова. Сначала с помощью свойства DatabaseName компонент связывается с нужной БД. Затем из списка свойства StoredProcName выбирается нужная хранимая процедура. Эти два этапа обычно реализуются при конструировании формы. Три следующих — в работающей программе: обращением к методу ParamByName устаяавливаются необходимые входные параметры, методом ЕхесРгос процедура выполняется и методом ParamByName получаются нужные выходные параметры.
Проиллюстрируем сказанное следующим примером (рис. 7.2):
Создайте в БД IB_BIBL процедуру, которая по номеру книги возвращает макси- ма.пьную партию ее продажи, то есть максимальное количество экземпляров, проданных одному покупателю:
CREATE PROCEDURE MAX_QUAN (BOOKID INT)
RETURNS (BOOK_QUAN INT) AS
BEGIN
SELECT
MAX(MQUAN)
FROM
MOVES, NAKLS
WHERE
MBOOK=:BOOKID AND NAKLS.NAKLID=MOVES.NAKLID AND NTYPE IN (1,7) INTO :BOOK_QUAN;
END
二[一一二:二 一 二 .二..二[一一二:二 一 二 .二..ВОСИ^) 」BNAM£ВОСИ^) 」BNAM£
二[一一二:二 一 二 .二..
二[一一二:二 一 二 .二..
ВОСИ^) 」BNAM£
ВОСИ^) 」BNAM£
1 :10 минут на урок MS Word 2000
2 10 минут на урок Windows 98
34563456江口 минут на урок.Освой самостоятельно MS Excel 2000
3
4
5
6
3
4
5
6
:100 компонентов общего назначения библиотеки Delphi 5
:1001 секрет реестра Windows NT
12 уроков тенниса.Самый доступньм самоучите^ для всех
j 13 шагов к успеху или пракпбческме советы как быстро достичь карьеры в
9 i 1C Ьухгалтерия.Самоучитать.Версии 7.5 и 7.7 е вопросах и ответах
lyly9 i3D Studio MAX 2.5 справочник
ly
ly
Рис. 7.2. Иллюстрация использования процедуры действия
Начните новый VCL-проект, поместите на пустую форму панель ТPanel, расположите ее вдоль нижнего края формы (Align 匸 alBottom) и на панель поместите надпись TLabel, установив такие ее параметры:
о AutoSyze = False;
о Anchors у [akLeft, akTop, akRight];
о Alignment = taCenter;
о Wordwrap = True.
Поместите на форму компоненты TDatabase, TTable, TStoredProc (категория BDE), TDataSuorce (категория Data Access) л TDBGrid (категория Data Controls). Настройте компонент Databasel на связь с БД IB_BIBL а компоненты Tablel и StoredProcl — на связь с локальным псевдонимом БД.
В списке свойства ТаЫeName компонента Tablel выберите таблицу BOOKS, назовите компонент именем таблицы, создайте для него объекты-поля и откройте НД.
В списке свойства StoredProcName компонента StoredProcl выберите имя процедуры MAX—QUAN.
Свяжите источник DataSourcel с НД BOOKS, а сетку DBGridl — с источником. Сетка должна наполниться данными.
Напшшгге такой обработчик события OnDataChange компонента DataSoursel:
procedure TForml.DataSourcelDataChange(Sender: TObject; Field: TField);
// Выполняет хранимую процедуру и опубликовывает ее результат begin
/ / Настраиваем входной параметр;
StoredProcl.ParamByNamel* BOOKIDт).Value := BOOKSBOOKID.Value;
StoredProcl.ExecProc;// Выполняем процедуру
// Получаем и используем ее результат:
Labe11.Caption := 1Максимальная партия продажи книги "' + BOOKSBNAME.Value +'"='+
StoredProcl.ParamByName('BOOK_QUAN').Assuring + ‘ экз.';
and;
Рассматриваемые далее в этом разделе компоненты других технологий для работы с хранимыми процедурами повторяют функциональность компонента TStoredProc, но имеют свои свойства и методы.
Компонент TADOStoredProc
В технологии dbGo.NET для работы с хранимыми процедурами предназначен компонент TADOStoredProc. Этот компонент является прямым наследником класса TCustomADODataSet, поэтому почти все свои свойства, методы и события он наследует от этого класса (см. раздел «Свойства, методы и события компонентов-наборов> в главе 4). У него есть два метода активизации: Open и ExecProc. Первый предназначен для получения наборов данных, второй — для выполнения процедур действия.
Компонент TSQLStoredProc
В технологии dbExpress.NET для работы с хранимыми процедурами предназначен компонент TSQLStoredProc. Этот компонент является прямым наследником класса TCu st omSQLDa t aS еt, поэтому почти все свои свойства, методы и события он наследует от этого класса (см. раздел «Компонент TSQLDataSet* в главе 5). У него есть два метода активизации: Open и ЕхесРгос. Первый предназначен для получения наборов данных, второй — для выполнения процедур действия. Два свойства строкового типа определяют имя хранимой процедуры: PackageName и StoredProcName. Первое используется только для сервера Oraclet в котором хранимые процедуры помещаются в пакеты. Его специфичный метод NextRecordSet используется для получения от процедуры очередной порции информации, если процедура возвращает набор даиных.
Компонент TIBStoredProc
В технологии IBX.NET для работы с хранимыми процедурами предназначен компонент TIBStoredProc. Этот компонент является прямым наследником класса TCustomlBDataSet, поэтому большинство своих свойств» методов и событий он наследует от этого класса (см. раздел «Компонент TIBDataSet* в главе 6).
Специфичные для компонента свойства и методы перечислены в табл. 7.3 и 7.4.
Таблица 7.3. Свойства компонента TIBStoredProc
Свойство
Назначение
property
Filtered: Boolean;
Указывает, будет ли фильтроваться НД, получаемый от хранимой процедуры
property
ParamCount; Integer;
Содержит общее количество параметров хранимой процедуры
property
Params: TParams;
Содержит параметры хранимой процедуры
property
Prepared: Boolean;
Указывает, будет ли предварительно готовиться выполнение хранимой процедуры
property
TString;
S t oredPropertyNames:
Возвращает список всех хранимых процедур, определенных в серверной БД
property String;
StoredPropertyNaine;
Содержит имя исполняемой хранимой процедуры
Таблица 7.4. Методы компонента TIBStoredProd
Метод
Назначение
procedure CopyParams(Value:
Копирует параметры хранимой процедуры в спи-
TParams);
сок Value
pzocedure ЕхесРгос;
Выполняет хранимую процедуру действия
продолжение
Таблица 7.4 (продолжение)
Метод
Назначение
function ParamByName (Name:
Открывает доступ к параметру хранимой проце-
String) : TParam;
procedure Prepare;
procedure UnPrepare ;
дуры по его имени
Готовит хранимую процедуру к исполнению
Ликвидирует последствия вызова метода Prepare
Создание триггеров
Триггер определяет программный отклик на изменение данных. Он создается таким SQL-оператором:
CRBATE TRIGGER <Имя_триггера> FOR <Имя_таблицы>
[ACTIVB I INACTIVB]
{BBFORB I AFTBR}
{DKLBTB I INSERT I XJPDATB}
[POSITION <номер>]
AS
[<объявление локальных переменных〉]
BBGIN
<операторы>
BND
Здесь:
е ACTIVE I INACTIVE — указывает, будет ли триггер активен (по умолчанию используется значение ACTIVE);
BEFORE I AFTER — определяет, будет ли триггер срабатывать до (BEFORE) или после (AFTER) изменения данных;
DELETE I insert | UPDATE — указывает тип изменения данных;
POSITION <номер> — необязательный параметр, определяющий очередность срабатывания триггера, если для одной и той же таблицы создано несколько однотипных триггеров (по умолчанию используется значение POSITION 0); триггеры с меньшими номерами выполняются раньше.
При написании триггера используется процедурный язык (см. раздел «Алгоритмический язык процедур и триггеров*)» в который добавлена возможность обращения к старым и новым значениям столбцов с помощью предикатов OLD и NEW соответственно.
Реализация бизнес-правил с помощью триггеров
В клиент-серверных БД с помощью триггеров следует реализовывать большую часть бизнес-правил (если это возможно, все бизнес-правила). Преимущества такого решения очевидны: вся работа реализуется сервером, и клиентская программа избавляется от необходимости обмена данными с ним. В результате резко
снижается сетевой трафик, а система управления БД в целом становится надежнее и проще: если понадобится изменить бизиес-правила, это гораздо легче реализовать в одном месте, чем вносить изменения в многочисленные клиентские программы.
Как уже говорилось, бизнес-правила тесно связаны с сутью тех зада% которые решаются с помощью создаваемой СУБД, поэтому невозможно дать какие-то единые рецепты их реализации. В данном разделе на примере БД «Книголюб» мы рассмотрим лишь те действия, которые необходимо проделать при удалении данных о накладной и при удалении названия книги из списка связанных с накладной книг.
Перед удалением данных о накладной следует удалить данные обо всех связанных с ней книгах. Это реализуется таким простым триггером:
CRBATE TRIGGKR BEFORE.DEL.NAKLS FOR NAKLS
ACTIVE BKFORK DELETE AS
BEGIN
DELBTB FROM Moves M
WHERE M.NakllD = OLD.NakllD;
END
Если в момент срабатывания триггера таблицы NAKLS и MOVES связаны реляционным отношением один ко многим, в таблице MOVES будут видны только те книги, которые относятся к удаляемой накладной, поэтому уточнение WHERE можно опустить:
GREATS TRIOGBR BEFORE_DELJSIAKLS FOR NAKLS
ACTIVB BBFORK DELBTK AS
BEGIN
DELBTE FROM Moves;
END
Удаление данных об отдельной книге влечет за собой более сложную логику действий: на основании типа накладной необходимо скорректировать количество экземпляров книги на складе и сальдо партнера, а также изменить сумму накладной:
CREATE TRIGGER BEFORE_DELJMOVES FOR MOVES
ACTIVE BEFORS DELBTE
AS
/* Объявление вспомогательных переменных: */
DBCLARB VARIABLB TypeN INTBGBR; /* Тип накладной */
DECLARB VARIABL8 FirmN INTEGER; /* Шифр партнера */
DECLARB VARIBLE Coeff FliOAT; /* Коэффициент накладной */
BEGIN
/* Помещаем тип накладной в переменную TypeN, шифр партнера в переменную FirmN % коэффициент в Coeff */
SELECT NType, NFirm
FROM Nakls
WHBRB Nakls.NaklID=OLD.NaklID
INTO :TypeN, :FirmN;
Z* Корректя данных в других таблицах зависит от типа накладной: */
IF (:TypeN ГЫ (0,3,4f6}} ТНВК
BEGIN
/* Удаляется книга из накладной, связанной с приходом книг.
Уменьшаем количество книг на складе */
UTOATB Books
SBT BQuan = BQuan - OLD.MQuan
WHSRB BookID = OLD.MBook;
/* Корректируем сальдо партнера */
IF (:TypeN=4) THEN
/* Увеличиваем обменное сальдо */
UPDATB Firms
SBT FChgDelta = FChgDelta + OLD.MQuan * OLD.MPrice * :Coeff WHERE FirmlD = :FirmN;
BLSK
/* Увеличиваем финансовое сальдо */
UPDATB Firms
SET FFinDelta 工 FFinDelta + OLD.MQuan * OLD.MPrice * :Coeff WHERE FirmlD = :FirmN;
BND 2LS2 B2GXN
/* Удаляется книга из накладной, связанной с уходом книг.
Увеличиваем количество книг на складе */
UPDATB Books
SBT BQuan=BQuan + OLD.MQuan
WHERE BookID = OLD.MBook;
IF (:TypeN=4) THEN
/* Уменьшаем обменное сальдо */
UPDATB Firms
SBT FChgDelta = FChgDelta - OLD.MQuan * OLD.MPrice * :Coeff WHKRE FirmID = :FirmN;
BLSB
/* Уменьшаем финансовое сальдо */
UPDATE Firms
SBT FFinDelta = FFinDelta - OLD.MQuan * OLD.MPrice * :Coeff WHERE FirmID = :FirmN;
END
BND
Многочисленные комментарии поясняют особенности тех или иных действий.
ПРИМЕЧАНИЕ
Если в текст объявления триггера, процедуры или любого другого компонента БД включить русскоязычный комментарий, этот текст станет недоступным (если включены англоязьшиые комментарии иля комментариев вообще нет, текст объявления любого компонента БД можно увидеть на вкладке Text окна утилиты SQL Explorer).
Как видите, в триггерах допускаются локальные переменные и условные операторы. Я не привожу объявления других триггеров» связанных с редактированием данных о накладных и книгах, — моя цель состоит в том, чтобы продемонстрировать особенности разработки клиент-серверных систем, и я вовсе не хочу
утомлять вас деталями реализации конкретной учебной системы. Тем не менее не моту не обратить вашего внимания на следующую деталь. Триггер BEFORE_DEL_ MOVES имеет серьезный недостаток: он не корректирует сумму накладной. Сделано это не случайно. Можно, например, в его начале вставить такие строки:
UPDATE Nakls
8МТ NSum 二 NSum - OLD.MQuan * OLD.MPrice * :Coeff WHERE NakllD = OLD.MNakl;
Если это сделать» то триггер прекрасно справится с задачей удаления данных о книге из накладной, но попытка удаления всей информации по накладной окажется невозможной, так как триггер будет пытаться изменить поле в удаляемой накладной, что категорически запрещается сервером. Как решить эту задачу? Дело в том, что, в отличие от процедуры» триггеру нельзя передать параметр, который указывал бы на то, что удаляется информация по накладной в целом. Получив такой параметр, триггер просто не стал бы изменять сумму накладной, да и коррекцию сальдо партнера можно было бы в этом случае сделать в триггере BEF_DEL_NAKLS сразу для всей суммы, а не делать этого для каждой отдельной книги. Однако повторяю» триггеру нельзя передать параметр, а в БД не существует глобальных переменных. Когда я впервые столкнулся с подобной проблемой на практике, она показалась мне неразрешимой. Однако после некоторого раздумья я нашел, как мне кажется, вполне приемлемое решение. Я добавил в таблицу MOVES новое поле:
ALTER TABLE MOVEBOOK ADD ISDelNakl VARCHAR(T)
Это поле заполняется в процессе ввода значением F в триггере BEF_INS_MOVES:
CREATE TRIGGER BEF_INS__MOVES FOR MOVES BSFORS INSERT AS BEGIN
NEW.IsDelNakl =
NEW.MovelD = GEH一工D(GEN_MOVEBOOK, 1);
END
Триггер BEF_DEL_NAKL первым делом выполняет такой оператор:
UPDATE MoveBook
SET isDelNakl 二'T'
WHERE MNakl = OLD.NakllD;
Теперь триггер BEF_DEL_J40VES может проанализировать это поле и блокировать коррекцию суммы в накладной> если поле содержит Т:
IF (OLD. IsDelNakl о Т) ТНВ»
UPDATE Nakls
SET NSum = NSum - OIJD.MQuan * OLD.MPrice * :Coeff WHERS NaklXD = OLD.MNakl;
Правильные тексты триггеров можно увидеть с помощью утилиты SQL Explorer. Для этого раскройте узел рядом с нужной таблицей, затем раскройте узел Triggers, выделите название нужного триггера и перейдите на вкладку Text
Изменение и удаление процедур и триггеров
Изменение процедур (триггеров) выполняется с помощью операторов ALTER PROCEDURE (ALTER TRIGGER), формат которых ничем не отличается от формата операторов создания процедуры (триггера), за исключением того, что при изменении триггера нельзя указывать часть FOR <имя_таблицы>. При выполнении оператора старое определение процедуры (триггера) заменяется новым.
Удалить процедуру (триггер) можно оператором DROP PROCEDURE (DROP TRIGGER) <имя_процедуры> (<имя_триггера>).
Представления
Представление (view) — это заранее составленный и хранящийся в БД SQL-запрос для выборки данных из одной или нескольких таблиц БД. Главное достоинство представления состоит в том, что, подобно хранимым процедурам, представление в момент создания оптимизируется и компилируется сервером, что сокращает время выполнения запроса.
Представление создается следующим оператором:
CREATE VIEW <Имя_представления> [(<MMH_CTon6na_VIEW>
[,< Имя_столбца_У1EW> ...])]
AS <OnepaTop_SELECT> [WITH CHECK OPTION]
В этом операторе за именем представления следует необязательный список имен столбцов представления, а <Оператор_ЗЕЬЕСТ> — это полнофункциональный оператор SELECT. Необязательный параметр WITH СНВСК ОРТХОН запрещает вставлять в обновляемое представление записи, значения полей которых противоречат условиям выборки записей представления.
Например:
CREATE VIEW Nakl_View
AS
SELECT NakllD, NDate, FName, TName, NSum, NPayedSum, NRetSum, NCoeff, NRetDate FROM Nakls, Firms, TypeNakl WHKRB
FirmID = NFirm AND TypelD = NType
ORDER BY NDate
Представление является «виртуальной» таблицей БД, поэтому с ним могут работать компоненты-наборы, как с реальными таблицами БД: имя представления можно указывать в компоненте TTable как имя реальной таблицы, к нему может обращаться компонент TQuery с запросом типа
SBLKCT * FROM Nakl„View
Представление может быть обновляемым или необновляемым. Чтобы представление было обновляемым, оно должно отвечать следующим требованиям:
состоять из записей одной таблицы;
в столбцы представления должны входить все столбцы таблицы, имеющие атрибут NOT NULL;
в представлении не должны использоваться агрегатные функции, параметры DISTING и having, хранимые процедуры и пользовательские функции.
Если представление удовлетворяет этим условиям, к нему можно применять операторы INSERT, UPDATE и DBLE7B. Если в столбцах представления указаны не все столбцы NOT NULL, к нему можно применять только операторы UPDATE И DBLB7B.
Список имен столбцов указывается в том случае, когда в представление включаются вычисляемые столбцы:
CRBA7B VIEW Move^JAiew(ID, Nakl, Book, Quan, Price, Sunuua)
AS SBLECT MoveXD, NakllD, MB。* MQuan, MPrice, MQuan*MPrice
FROM Moves
WHBRE MBook = 1 WITH CHECK OPTION
Количество имен палей представления должно строго соответствовать количеству полей, возвращаемых оператором 8BLBCT. Наличие в представлении вычисляемых столбцов не запрещает ему быть обновляемым (показанное выше йредставление — обновляемое» однако в него нельзя вставить записи, столбец MBook которых содержит значение» отличное от 1, — это запрещает параметр WITH CHECK OPTION). Представление нельзя изменить, но его можно удалить оператором
DROP VIEW <Имя_представления>
Отчеты
В большинстве случаев данные, которые хранятся в таблицах БД, необходимо тем или иным способом публиковать, создавая так называемые отчеты. Для облегчения этой работы вместе с Delphi 2005 поставляются специальные программы (генераторы отчетов) Crystal Reports и Rave Reports. Обе программы могут работать на платформе .NET, но первая используется только в технологии ADO.NET (то есть в приложениях WinForms); для остальных технологий (для VCL-приложений) предусмотрена программа Rave Reports. В этой главе рассматриваются обе технологии.
Основы технологии Crystal Reports
Программа Crystal Reports позволяет выполнить выборку и форматирование результирующего НД из БД или другого источника данных. Эта программа способна создавать любые отчеты — от простого на основе одной таблицы до сложного отчета, группирующего данные из нескольких таблиц, с многочисленными диаграммами и производящего сложные вычисления над публикуемыми данными. Создание отчетов в Crystal Reports осуществляется под управлением встроенного дизайнера отчетов, который запускается при добавлении к проекту WinForms объекта Crystal Reports. Созданный отчет запоминается в файле с расширением RPT. Для связи с отчетом в проект добавляется объект ReportDocument, а для визуализации отчета — объект CrystalReportViewer.
Пример создания простого отчета
В этом разделе описывается процесс создания несложного отчета, показанного на рис. 8.1. Отчет представляет собой прайс-лист оптового поставщика, созданный на основе информации, содержащейся в таблице BOOKS.
['累;「;зГ百胃毎”苗'各咨0>*…
w^1^
I
Пранс-лип книг
24.0: J(W5
10 vx,i)" »* >piin M* 3 wrxi 20W HImiihvi на yfM»ir ^ii>4<»wv ^4 Ю MWyim Yhix.Oca” 貝 Cii.uwioeitiitHijMS BucJ ХЧЮ HXl м、*,"、нсю<'н g:::ue H»2”sx”* *M>.g“5“ IkW» IWJI ivKpci p*x ipft Wtndi>^« NT
12 урек。》reiFKxjs <\“u* 4ivvyi!iiufi c«MAy,n<ierik ;(;e
I 3 insi'i*» к \\';ie*y it<ii 1||иг>>1ЧЁСьиЁ еонегз Юк Gwcrpu
I' • !>у\>лгчери«.Саи<1учм)ел|-.Н(;|хчлг ",S н ?.? i* N、》g<a、 ЗП Smilw VAX 25 \ "罔**”““1》
3D Studio MAX З.УчсйлыЯ к\ pt •; СП-ROM
”J Studio MAX КЗ Снсцтффек гы и ahu*” " ('D R0M
;П Studw MAX Hi<yv(4HHu>i мир. 1<>м 2 - (. D-H<FM
、【〉St“diu Mx、3.0 tn i>5^sti» ;n> лмнчяцкк - Cl)-HOM №> 1иукокы.ч M “у “скальммк “pvt 4aMM 稣m>»W\ui» gWHl’M*斗X,|>'гж-1лыл
.Ассме 2<M*ii ли 1и5;и.ч''вД1е-1>.Р>,гифиц)[р1^ьш;ии □с(ппя
Ассол «1 1、мз”,м rm,iuk макрох |ыку “ \ BA -( F)-KOM Acee*8 '^,'>KUHit;fpiKJiu ио^ькииссл ♦ *,:U-K(jM
.5Jn)jnJ>Vtl7ni! SUi. SW> FJ- '.C^pi>t^Hx:m>i:>Hi-i4X)
•\J、Z IIIusha<KH 8.C л ”4.и“”ин*с
Adobe llht'K^ror x、,,нб“з" ырс
*t.7s t”rx<"・“ a iwi,“》>;““a"
陈7启) М.МЮ ?l.№ 6600
ЛрХЙМ! с;"*ий Джи
Дпалсхтнкл
ДкаСоЦн hliV-(4HwT-ITCTtp6%r HIIVWnllEpOyp
В"' -kMC«i леям I АклСлфт
R“\>4wr J jm^Avn
Kom*viih MnfH/n
'1t.1IWNP1A>lfMKft0
・y:Ut tIM JK”批Akuh /1»“оя,,.
“CM1HC
?Ш2Л %"Х£Н 6:w«ut
IIotHJ.Mapt'KKU
Имшъсш. Вкмамт JltfAACtlUM HBgMU
Fwvvx»» Рсийжцня Tej»f»-<'ititpi ПоЛИПРМПТЕА Ч'рлумф
BUV-Cj^uT-IlmpGyp
15.40 «м :0».ft0
М>.П0 115,50 $7" EA'.Ofl
:^^^;^1工:二:二二二:二П?^^^ 端r多绥鑒翁a
Рис 8.1. Пример отчета в окне предварительного просмотра
К сожалению. Crystal Reports не может использовать технологию BDP-npoвайде- ра. поэтому для доступа к таблицам БД «Книголюб» мы будем использовать провайдер Microsioft OLE DB Provider for ODBC driver:
Настроите драйвер Microsoft Paradox Driver на работу с таблицами файл-сер- вериой БД «Книголюб» так, как описано в разделе «Пример простой программы» главы 4.
Начните новое приложение WinForms и выберите команду File ► New ► Other. В появившемся окне New Item (рис. 8.2) раскройте узел Crystal Reports п на правой панели щелкните на значке Report, после чего закройте окно.
Процесс создания отчета начинается с нового окна Oystal Report Gallery (рис. 8.3). В этом окне переключатель Using the Report Expert определяет пошаговый процесс создания под управлением эксперта. Переключатель As a Blank Report также инициирует пошаговый процесс, но он менее автоматизирован и требует большего умения со стороны программиста. Переключатель From an Existing Report служит для создания отчета на основе уже существующего. Список Choose an Expert позволяет выбрать нужного эксперта, в том числе:
о Standard - эксперт создания стандартного отчета, содержащего данные из одной или нескольких таблиц, причем разрешены фильтрация, сортировка, группировка и численная обработка данных, допустимо включение в отчет диаграмм, использование различных стилей отчета;
о From Letter — создание писем с использованием информации из БД;
о Form — создание отчета с логотипом на базе отсканированного изображения;
Рис. 8.2. Выбор нового отчета
i Gukfes Ihft eeation Ы а 1уркчй шмм1i Gukfes Ihft eeation Ы а 1уркчй шмм1Рис. 8.3. Окно Crystal Report GalleryРис. 8.3. Окно Crystal Report GalleryО Form Letter 叵]Form Й Cross-Tab ^Subrepoct ® Mail Label 回 Dtil DownО Form Letter 叵]Form Й Cross-Tab ^Subrepoct ® Mail Label 回 Dtil Down;Oe^e:^New.QyrtdR<^ortOo^ ' 四 G Ihmtheaeport E^ert;Oe^e:^New.QyrtdR<^ortOo^ ' 四 G Ihmtheaeport E^ert"j- C& — ^ ^血唸启叩ort"j- C& — ^ ^血唸启叩ort』Е^ёйф ah Expert -”-“““““•—』Е^ёйф ah Expert -”-“““““•—
i Gukfes Ihft eeation Ы а 1уркчй шмм1
i Gukfes Ihft eeation Ы а 1уркчй шмм1
Рис. 8.3. Окно Crystal Report Gallery
Рис. 8.3. Окно Crystal Report Gallery
О Form Letter 叵]Form Й Cross-Tab ^Subrepoct ® Mail Label 回 Dtil Down
О Form Letter 叵]Form Й Cross-Tab ^Subrepoct ® Mail Label 回 Dtil Down
;Oe^e:^New.QyrtdR<^ortOo^ ' 四 G Ihmtheaeport E^ert
;Oe^e:^New.QyrtdR<^ortOo^ ' 四 G Ihmtheaeport E^ert
"j- C& — ^ ^血唸启叩ort
"j- C& — ^ ^血唸启叩ort
』Е^ёйф ah Expert -”-“““““•—
』Е^ёйф ah Expert -”-“““““•—
о Cross-Tab — создание отчета с перекрестными ссылками;
о Subreport — создание детального отчета, данные из которого включаются в главный отчет;
о Mail Label — создание серии почтовых этикеток (конвертов);
о Drill Down — создание сводного отчета с возможностью его детализации.
Выберите в окне пошаговый процесс создания стандартного отчета под управлением эксперта» установив переключатель Using the Report Expert, и закройте окно щелчком на кнопке ОК.
В окне Standard Report Expert (рис. 8.4) щелкните на узле OLE DB (ADO), чтобы активизировать процесс создания источника данных (рис. 8.5).
Выберите провайдер Microsoft OLE DB Provider for ODBC Driver и щелкните на кнопке Далее.
В новом окне выберите драйвер Paradox files, как показано на рис. 8.6, н щелкните на кнопке Готово. На экране вновь появится вкладка Data окна Standard Report Expert (рис. 8.7).
Откройте узел C:\BIBLDATA, выберите таблицу BOOKS, щелкните на кнопке Insert Table, затем — на кнопке Next.
312 Глава 8 • Отчеты
QL£ ОВРптфи
■■■■■■ Salect a pravtdm horn the hi of Tect a data link 他.
二 Efoyeiec二 EfoyeiecMtccosoft OLE DB Piovider fa Internet PubliiAiMicrosoft OLE DB Piovider for Dlap Service:Microsoft OLE DB Ptovidet for DiadeMiciosofl OLE DB Provider for Outlook Sear ,;;;Microsoft OLE D8 Ptovider for SQL ServerMiciosoft OLE DB Simple PioviderMSDataShapeSQL Server Replication OLE DB Piovider to- i 、,WrC Мтсссшл ГгЛМЕаг』Мапасог Pfrivii 总式: 人,・・H ' Е,Mtccosoft OLE DB Piovider fa Internet PubliiAiMicrosoft OLE DB Piovider for Dlap Service:Microsoft OLE DB Ptovidet for DiadeMiciosofl OLE DB Provider for Outlook Sear ,;;;Microsoft OLE D8 Ptovider for SQL ServerMiciosoft OLE DB Simple PioviderMSDataShapeSQL Server Replication OLE DB Piovider to- i 、,WrC Мтсссшл ГгЛМЕаг』Мапасог Pfrivii 总式: 人,・・H ' Е,ГГРис. 8.5. Первый шаг создания источника данныхРис. 8.5. Первый шаг создания источника данныхОтмена .Отмена .
二 Efoyeiec
二 Efoyeiec
Mtccosoft OLE DB Piovider fa Internet PubliiAi
Microsoft OLE DB Piovider for Dlap Service:
Microsoft OLE DB Ptovidet for Diade
Miciosofl OLE DB Provider for Outlook Sear ,;;;
Microsoft OLE D8 Ptovider for SQL Server
Miciosoft OLE DB Simple Piovider
MSDataShape
SQL Server Replication OLE DB Piovider to- i 、,WrC Мтсссшл ГгЛМЕаг』Мапасог Pfrivii 总式: 人,・・H ' Е,
Mtccosoft OLE DB Piovider fa Internet PubliiAi
Microsoft OLE DB Piovider for Dlap Service:
Microsoft OLE DB Ptovidet for Diade
Miciosofl OLE DB Provider for Outlook Sear ,;;;
Microsoft OLE D8 Ptovider for SQL Server
Miciosoft OLE DB Simple Piovider
MSDataShape
SQL Server Replication OLE DB Piovider to- i 、,WrC Мтсссшл ГгЛМЕаг』Мапасог Pfrivii 总式: 人,・・H ' Е,
Г
Г
Рис. 8.5. Первый шаг создания источника данных
Рис. 8.5. Первый шаг создания источника данных
Отмена .
Отмена .
HDBCDSN;HDBCDSN;Locals etv« 瀨處陶麻辍;:^缀磁^ Xheme Sample Database 2003 база данных MS Access Файлы dBASE Файлы ExcelLocals etv« 瀨處陶麻辍;:^缀磁^ Xheme Sample Database 2003 база данных MS Access Файлы dBASE Файлы Excel
HDBCDSN;
HDBCDSN;
Locals etv« 瀨處陶麻辍;:^缀磁^ Xheme Sample Database 2003 база данных MS Access Файлы dBASE Файлы Excel
Locals etv« 瀨處陶麻辍;:^缀磁^ Xheme Sample Database 2003 база данных MS Access Файлы dBASE Файлы Excel
ODBC Data Sow се Choose a data $burce hom the fist
Рис. 8.6. Второй шаг создания источника данных
Щелчок на кнопке Next форсирует переход к работе с новой вкладкой окна Standard Report Expert. В нашем случае откроется вкладка Fields, позволяющая отобрать поля, данные из которых будут опубликованы в отчете (рис. 8.8).
二:?Ау9ЙЙЙ' М МЧ*:二:?Ау9ЙЙЙ' М МЧ*:■♦ 口 Project Data-U0LEDB(AD0)目 Make New Connect»on-号 Paradox hlec±4 Add Cornmdnd gCABIBLDATA 圈般期 餾 FIRMS 圄 Move$ 圃 NAKLS ^PAYMENTS 圖 PdxSecufity 囲 Types.* EDODB匚(RDO)■♦ 口 Project Data-U0LEDB(AD0)目 Make New Connect»on-号 Paradox hlec±4 Add Cornmdnd gCABIBLDATA 圈般期 餾 FIRMS 圄 Move$ 圃 NAKLS ^PAYMENTS 圖 PdxSecufity 囲 Types.* EDODB匚(RDO)Blank ReportBlank ReportРис. 8.7. Выбор таблицы БДРис. 8.7. Выбор таблицы БДP&U F^s |gw | j^ fj^N] Ch^ ):Sateet|:S |:P&U F^s |gw | j^ fj^N] Ch^ ):Sateet|:S |:Оюо$а the bfomatipn to 血知 on the 隅MОюо$а the bfomatipn to 血知 on the 隅M-Seted the avahbte h^dsi ^Асошайп th& daKa ^>ou wart to teport cm. Then add thorn S the FieHi® 今 ^^y&<-Seted the avahbte h^dsi ^Асошайп th& daKa ^>ou wart to teport cm. Then add thorn S the FieHi® 今 ^^y&<,Vai^)te ReHs:」 Й Repott Fields:产 E 0 Paradox files (OLE DB (ADO)) ГТ,Vai^)te ReHs:」 Й Repott Fields:产 E 0 Paradox files (OLE DB (ADO)) ГТFiddt to Dbpla^Fiddt to Dbpla^114114冗 ^BOOKS■ оэ BookID■ та BName■ ® В Author в В Publish■ g BYea■ g В Pages та BISBN 皿 В Stand rm DHi >ftr.冗 ^BOOKS■ оэ BookID■ та BName■ ® В Author в В Publish■ g BYea■ g В Pages та BISBN 皿 В Stand rm DHi >ftr.A^N今A^N今<<R«rtgye<<R«rtgyewAera^AIwAera^AIBOOKS.BookIDBOUKS.BName BOOKSBAuthof BOOKS.BPubhhBOOKS.BookIDBOUKS.BName BOOKSBAuthof BOOKS.BPubhh:帀丁二 ШП:帀丁二 ШПCdifQn Heading: |ЦейаCdifQn Heading: |Цейа
二:?Ау9ЙЙЙ' М МЧ*:
二:?Ау9ЙЙЙ' М МЧ*:
■♦ 口 Project Data
-U0LEDB(AD0)
目 Make New Connect»on
-号 Paradox hlec
±4 Add Cornmdnd gCABIBLDATA 圈般期 餾 FIRMS 圄 Move$ 圃 NAKLS ^PAYMENTS 圖 PdxSecufity 囲 Types
.* EDODB匚(RDO)
■♦ 口 Project Data
-U0LEDB(AD0)
目 Make New Connect»on
-号 Paradox hlec
±4 Add Cornmdnd gCABIBLDATA 圈般期 餾 FIRMS 圄 Move$ 圃 NAKLS ^PAYMENTS 圖 PdxSecufity 囲 Types
.* EDODB匚(RDO)
Blank Report
Blank Report
Рис. 8.7. Выбор таблицы БД
Рис. 8.7. Выбор таблицы БД
P&U F^s |gw | j^ fj^N] Ch^ ):Sateet|:S |:
P&U F^s |gw | j^ fj^N] Ch^ ):Sateet|:S |:
Оюо$а the bfomatipn to 血知 on the 隅M
Оюо$а the bfomatipn to 血知 on the 隅M
-Seted the avahbte h^dsi ^Асошайп th& daKa ^>ou wart to teport cm. Then add thorn S the FieHi® 今 ^^y&<
-Seted the avahbte h^dsi ^Асошайп th& daKa ^>ou wart to teport cm. Then add thorn S the FieHi® 今 ^^y&<
,Vai^)te ReHs:
」 Й Repott Fields:
产 E 0 Paradox files (OLE DB (ADO)) ГТ
,Vai^)te ReHs:
」 Й Repott Fields:
产 E 0 Paradox files (OLE DB (ADO)) ГТ
Fiddt to Dbpla^
Fiddt to Dbpla^
114
114
冗 ^BOOKS
■ оэ BookID
■ та BName
■ ® В Author в В Publish
■ g BYea
■ g В Pages та BISBN 皿 В Stand rm DHi >ftr.
冗 ^BOOKS
■ оэ BookID
■ та BName
■ ® В Author в В Publish
■ g BYea
■ g В Pages та BISBN 皿 В Stand rm DHi >ftr.
A^N今
A^N今
<<R«rtgye
<<R«rtgye
wAera^AI
wAera^AI
BOOKS.BookID
BOUKS.BName BOOKSBAuthof BOOKS.BPubhh
BOOKS.BookID
BOUKS.BName BOOKSBAuthof BOOKS.BPubhh
:帀丁二 ШП
:帀丁二 ШП
CdifQn Heading: |Цейа
CdifQn Heading: |Цейа
.:. . Find 岡&.
В 吋 Report I;В 吋 Report I;ti* ]. ”耻* I . 4> I . &ЙИ I /
В 吋 Report I;
В 吋 Report I;
Щелкните на поле BookID в списке Available Fields, затем — на кнопке Add. Поле будет перенесено в список Fields to Display, а в поле Column Heading появится заголовок соответствующей колонки отчета — BookID. Замените его названием №.
Перенесите таким же образом поля BName, BAuthor, BPublish и BRozn, заменив заголовки их колонок именами Название, Автор, Издательство, Цена соответственно.
Наш простой отчет почти сформирован. Осталось указать его заголозок. Щелкните на вкладке Style.
В поле Title введите текст Прайс-лист книг, как показано на рис. 8.9, и щелкните на кнопке Finish.
Рис. 8.9. Ввод заголовка отчета
Появится окно с предложением зарегистрировать утилиту Crystal Reports (рис. 8.10). Щелкните на кнопке Register Later.
Перед генерацией отчета сохраните текущее состояние проекта на диске и перенесите на пустую форму компонент ReportDocument. В этот момент появится диалоговое окно с предложением подтвердить необходимость генерации только что созданного проекта отчета.
Поместите на форму компонент CrystalReportViewer, в его свойство Dock установите значение Fill, а в свойстве Reportsource сошлитесь на проект отчета. Отчет и средство его просмотра готовы.
Основы технологии Crystal Reports 315
、• crystal decisions
Experience the Power of Costal Repo^
Register now to access these additional fesources:
Award winning T echnical Suppoft
Valuable product updates
Helpful Samples, Tutoriels and T echnical Briefs
Information on Crystal Analysis and Crystal Enteiprise
^'SFM 丄I 0;盲门]^'SFM 丄I 0;盲门]Regei Ut«Regei Ut«
^'SFM 丄I 0;盲门]
^'SFM 丄I 0;盲门]
Regei Ut«
Regei Ut«
Рис. 8.10. Окно регистрации Crystal Reports
Дополнительные средства эксперта создания стандартного отчета
В созданном простейшем отчете не использовались многие возможности эксперта создания стандартного отчета. Эти возможности связаны с не рассмотренными нами вкладками Group, Totdl, TopN, Chart и Select.
Вкладка Group предназначена для группировки данных (рис. 8.11).
В левом списке указаны отобранные для публикации поля. Выберите нужное поле и перенесите его в правый список — группировка данных в предложении GROUP BY будет вестись по этому полю. Пусть, например, мы решили создать отчет с группировкой книг но издательствам. Выделите щелчком пункт BPublish и щелкните на кнопке Add. Вид отчета с группировкой показан на рис. 8.12.
Вкладка Total становится доступной только после группировки данных. Она позволяет добавлять в отчет сводную информацию по группам. Например, в нашем случае можно в конце каждой группы указать количество книг, выпущенных издательством и предлагаемых для продажи (рис. 8.13).
С этой целью удалите из правого списка добавленное экспертом единственное числовое поле BRozn и добавьте в него поле BName. Раскрывающийся список Summary Туре определяет тип сводных данных. Содержимое этого списка зависит от типа поля, используемого для получения сводной информации. Для строковых полей он включает такие значения:
maximum — максимальное значение;
minimum — минимальное значение;
Dato I FMdc JH« | t^ IgpHj Chan | $d| Si^i |
: Bectxd* ^ ^ MxtcdbiM 01Й¥«^^ (he Group By Mck Add summary iriorm^ioh轴庙 ktab step必bie^ :• •the wrtedmcor&.Ho:gtoupr ;.
■ GwwpBy;
■fl *
? Й Report Fields:
■™ BOOKS.BookID
■ oa BOOKS.BNome
■ <п» BOOKS.BAuthcx
□a BOOKS.BPubfith
зВСЮ依BR叫
三 ф Paradox fries (OLE DB (ADO)) w;親 BOOKS
eta BooWD
:oa BName g BAtAha схя BPubiish
;as BY ear
3
1举d:>i
c Remove :
Sort Ojdet J in ascending older. []
s
;BP®曲 D&a T
:::■ ■ BUnkBepott
Рис. 8.11. Группировка данных
■ 自国立NY
^K^^^^S?办資*•#■«;!
1 Пранс-лигг книг
I 2^.03 2005
а “丄叫гикмпд
1京|
Clt НЙУ'ШЛГ:!». pLlfxJ t Ы Hd
Аахш. IhlEhl,
窗 HUV-Кнеи
1 BliV-Kwn
Atucx ?tKKt ,i <h
VamuiI》udtc r> Dq uh'x pvkonyj<i»f<i
Miu.fJtrp
I HHY・Xi
Visual {■*-<! .1:11 110:1k. к1>к,1(11:11
儿n,w
芻 HUY-knai
Н«Ч<К1<Щ> $ НОЧЫК! р\КОЛ«Э,1СГЖО ■■
K.fjMMiJ eurafM
芻 HUVIe
V讣ual H$$ic 0 IkhiHOr |,y*“・o t、itH'
Рзй;1|:|,Ср
尋 HllV.KMtk
VjMjiJ “,«С 6 0 t“《卄OiCK* S'MPid
Р.1Й1Н1НФ
Й UHV-Khch
11 NIXrpy kvmjc tmo cktneWHi'r i-
ItCMb;
BHV.Khc
«'uxlcwv QX qiw p<>;ib'iOKaie:t
KC;2C">H:CR
BIIVKh»
(kiick.l 1роск1Мр<*ва>1нг 6ai shhux
Jump
BIIV-Kwe»
Whld(,4 9K.U0 lii<X pyKUtKUCiSO ;
Мннзсн
WlV-Kwe
ll>iX;MIK i pVMCinilHhKMC CpC.KiM ■-■
BlIV-кмгв
WiMuws 9X,pv*t<iM>4uiso
Ititb
BHV.Khcd
Wirxlfwi УХ^руичтолс пю
BHVKf
ViWWl BiSJC 6 Pvyw4f 12
llerpYf
HUV.Km**
Visuill H*制С6.П ^1Л riii'ik.'K»Kun*.iM
Ряк1 imt tr
BHV-Kn»
EK8.M
;ВН\-Санкт-|1сгсрбу|Н
UHV-CiMKrJIcicp^'rp)'
1 b?7 L»4O)-4trt4JJib Ml t. - ;iMttccr#
1 OXOMlipftn
鼠 HUV-C *мгт」М*■睢卜 nr
1 e? 1
「7小7"2.". &ll"M \( ),1黑中"
1 In VI"W
ibinWpea* Ne;2 -.^ftWlFtveNrS*'.'.IZoamFfltjtqn 1004
~r-”- f “”,,”, ”,Ш^_ — " — 1,*,””,-??^!.” = —— ''#=」”-" W”"r”"”HEErr^^2?g?g,U-",,"Wq"f-
Рис. 8・12・ Отчет с группировкой книг по издательствам
ОЫа: |:Relds:| Gioup; T^' :|Tcp,H | Chat |;Se^:| Styfe; |
(Opb^^Surn^Wof^^:■
■ For «dchgroups^ tian сКрсйеопё^^^^^tummariza
socks,ешь
■-: Report Fields:';esBOOKS.BooKID aa BOOKS.BName,g BOOKS.BAuthof.cEjBOOKS.BPublish□Э BOOKS BRozn£ 9 Paiadoxtitec(OLE DB (ADOJ1 :一屬 BOOKSg BookID .eej BName ■ g BAuthor■-: Report Fields:';esBOOKS.BooKID aa BOOKS.BName,g BOOKS.BAuthof.cEjBOOKS.BPublish□Э BOOKS BRozn£ 9 Paiadoxtitec(OLE DB (ADOJ1 :一屬 BOOKSg BookID .eej BName ■ g BAuthorSunffHMsedFieldr;SunffHMsedFieldr;BOOKS.BookIDBOOKS.BookID<R^DQve<R^DQveSummay Type: | countSummay Type: | count~3~3::::8 rgie1^ b 廿,京];::::8 rgie1^ b 廿,京];、•厂 ^Гe9Зшон Г口号总大:3* ;£м出 笳建门;二]P Add Grand Total».、•厂 ^Гe9Зшон Г口号总大:3* ;£м出 笳建门;二]P Add Grand Total».
■-: Report Fields:
';esBOOKS.BooKID aa BOOKS.BName
,g BOOKS.BAuthof
.cEjBOOKS.BPublish
□Э BOOKS BRozn
£ 9 Paiadoxtitec(OLE DB (ADOJ1 :一屬 BOOKS
g BookID .eej BName ■ g BAuthor
■-: Report Fields:
';esBOOKS.BooKID aa BOOKS.BName
,g BOOKS.BAuthof
.cEjBOOKS.BPublish
□Э BOOKS BRozn
£ 9 Paiadoxtitec(OLE DB (ADOJ1 :一屬 BOOKS
g BookID .eej BName ■ g BAuthor
SunffHMsedFieldr;
SunffHMsedFieldr;
BOOKS.BookID
BOOKS.BookID
<R^DQve
<R^DQve
Summay Type: | count
Summay Type: | count
~3
~3
::::8 rgie1^ b 廿,京];
::::8 rgie1^ b 廿,京];
、•厂 ^Гe9Зшон Г口号总大:3* ;£м出 笳建门;二]P Add Grand Total».
、•厂 ^Гe9Зшон Г口号总大:3* ;£м出 笳建门;二]P Add Grand Total».
IIII« 艮啾、L ^^a |[ fi^"~l
II
II
Рис. 8.13. Вкладка Total
count — количество значений;
distinct count — количество разных значений;
Nth largest — №u наибольшее значение;
Nth smallest ― Me наименьшее значение;
mode — статистическая мода значений, то есть наиболее вероятное значение;
Nth most frequent — Мс наиболее часто встречающееся значение.
В случае числовых полей в списке имеются еще и такие значения:
sum — сумма значений;
average — среднее значение;
weighted average — взвешенное среднее значение;
medium — медиана значений поля;
sample variance — дисперсия значений;
sample standard deviation — среднее отклонение значений;
population variance — дисперсия генеральной совокупности;
correlation — коэффициент корреляции;
covariance 一 смешанный момент второго порядка.
Вкладка Top N (рис. 8.14) позволяет добавить в отчет дополнительные средства анализа на основе полученных на вкладке Total сводных результатов.
Рис. 8.14. Вкладка Top N
В списке For this group sort имеются следующие варианты средств анализа, опреде- 』兄ющнс, какие нменно данные будут участвовать в получении сводных данных:
АН — вес данные;
Top N — первые ^ значений;
Bottom N — последние ^ значений;
Top Percentage — N-й процент первых;
Bottom Percentage — М仃 процент последних.
С помощью вкладки Chart (рис. 8.15) в отчет можно добавить диаграмму.
ПРИМЕЧАНИЕ
В БД «Книголюб» содержатся книги более 200 издательств. Чтобы не загромождать диаграмму таким количеством данных, ограничимся несколькими издательствами. Для этого ла в качалке Top N в списке For this group sort выберите вариант Top N. в списке Based On — вариант Count of BOOKSBName, в поле Where N Is введите значение 7 и сбросьте флажок Include other groups with the label.
Эта вкладка имеет три внутренние вкладки — Type, Data и Text.
Вк.'1адка Туре представлена на рис. 8.15. С ее помощью выбираются тип диафам- мы и ос расположение (по вертикали нлн по горизонтали листа). В списке Chart type перечислены все возможные типы диаграмм, справа от списка располагается от одной до шести (количество зависит от выбранного типа) кнопок, уточняющих пил диаграммы.
Рис. 8.15. Вкладка Туре на вкладке ChartРис. 8.15. Вкладка Туре на вкладке Chart
Рис. 8.15. Вкладка Туре на вкладке Chart
Рис. 8.15. Вкладка Туре на вкладке Chart
Date I Fields | Group | Total | ^opN j Dri) Cbart ] Select j SMe j pptkN^) Inchde a diart on the/epcxtSeied a dwt ^ and tha:d0id ^pu war# it to represent.
Type ^*卜翱衣j
1Meh毗|Йт^Ш7ГХЗ^лИЭ 6 He咖广 Fptef
^^^^^3
jCount of BOOKS BNarne™—R
Ofctf J::曲p J «BadC J Hext» ]| : £哟]
На вкладке Data (рис. 8.16) следует выбрать поля, по значениям которых будет построена диаграмма, количество диаграмм и их размещение (в начале отчета — переключатель Header, в его конце — пере1спючатель Footer).
Наконец, с помощью вкладки Text (рис. 8.17) можно задать поясняющие надшей: заголовок (Title), подзаголовок (Subtitle), нижнюю поясняющую надпись (Footnote), заголовки групп (Group title) и данных (Data title).
По умолчанию соответствующие поля заполняются автоматически фор\!прую- тимся текстом. Чтобы разблокировать их, нужно сбросить семя ве гствуюццie флажки Auto-Text. Элемемты группы Format используются для проверки или установки нужных шрифтов.
Замечу, что независимо от реальных данных диаграмма в окне формирования отчета показывается схематично, например так, как на рис. 8.18.
Реальные данные используются только в окне предварительного 1цюсмогра и при печати отчета (рис. 8.19).
Замечу, что для редактирования диаграмм предусмотрен специальный редактор. Для обращения к нему щелкните на диаграмме правой кнопкой мыши и в контекстном меню выберите команду Format Char ► General. С помощью средств этого редактора можно отказаться от вывода легенды, придать диаграмме «трехмерный» вид и т. д.
Основы технологии Crystal Reports 321Основы технологии Crystal Reports 321Рис. 8.18. Диаграмма в окне формирования отчетаРис. 8.18. Диаграмма в окне формирования отчета丁 т,丁第百力聋施樓芸а:w畔‘丁 т,丁第百力聋施樓芸а:w畔‘.D:D D 口 口.D:D D 口 口I./ ..II./ ..IПитер.ЮНИТИS[BHV-Смст-Пвтярбу: ЯРусская Рмакция -щСолон圖Питер.ЮНИТИS[BHV-Смст-Пвтярбу: ЯРусская Рмакция -щСолон圖МЙАсро*^МЙАсро*^Книги по издательствамКниги по издательствамКинги ио мздагсльовам Ж23
Основы технологии Crystal Reports 321
Основы технологии Crystal Reports 321
Рис. 8.18. Диаграмма в окне формирования отчета
Рис. 8.18. Диаграмма в окне формирования отчета
丁 т,丁第百力聋施樓芸а:w畔‘
丁 т,丁第百力聋施樓芸а:w畔‘
.D
:D D 口 口
.D
:D D 口 口
I./ ..I
I./ ..I
Питер.
ЮНИТИS[
BHV-Смст-Пвтярбу: Я
Русская Рмакция -щ
Солон圖
Питер.
ЮНИТИS[
BHV-Смст-Пвтярбу: Я
Русская Рмакция -щ
Солон圖
МЙАсро*^
МЙАсро*^
Книги по издательствам
Книги по издательствам
&*£&Dl&*£&DlCurejPa 做儀TCurejPa 做儀TФсмммгФениксФсмммгФеникс1 622 Pm』ns uneixc.Aii0>u:KiM ipexciMitiHi1 622 Pm』ns uneixc.Aii0>u:KiM ipexciMitiHi:;fibui日r1謁林詳,:;fibui日r1謁林詳,HMunsim
&*£&Dl
&*£&Dl
CurejPa 做儀T
CurejPa 做儀T
Фсмммг
Феникс
Фсмммг
Феникс
1 622 Pm』ns uneixc.Aii0>u:KiM ipexciMitiHi
1 622 Pm』ns uneixc.Aii0>u:KiM ipexciMitiHi
:;fibui日r1謁林詳,
:;fibui日r1謁林詳,
Рис. 8.19. Диаграмма в окне предварительного просмотра
Вкладка Select окна эксперта создания стандартного отчета показана на рис. 8.20. С ее помощью можно задать фильтр отбора данных. Фильтр записывается на специальном языке, допускающем названия полей, константы и символы следующих операций:
Is equal to — равно;
Is not equal to 一 не равно;
и Зак 449
Рис. 8.20. Вкладка Select
Is less then — меньше чем;
Is less then or equal to — не больше;
Is greater then — больше;
Is greater then or equal to — не меныие;
Is one of — одно из перечисленных значений;
Is between — значение в указанном диапазоне
Is not between — значение вне указанного диапазона;
Is like — значение, соответствующее указанному шаблону;
Is starting with — значение, начинающееся с указанной подстроки.
Экспорт отчета
С помощью кнопки Export Report в окне предварительного просмотра можно экспортировать отчет в файл формата PDF, который читается утилитой Acrobat Reader корпорации Adobe. На рис. 8.21 показан вид отчета в окне этой утилиты.
Как видите, качество преобразования очень высокое. А поскольку утилита Acrobat Reader распространяется бесплатно (http://www.adobe.com), созданный вами отчет сможет прочитать любой желающий.
1 10 mhhvt на урок MS Won! 2(XX)
Внлъачс
16,2ч
2 10 миичт 1Ш урок Windims 9i
4^.111)^
Д<шектик1
23JO
3 10 ш<н¥1)ш урок.ОсаюД
加尸еh
Нильжмс
46,20
4 IW кииоинснтпа обшсго ня-лпгюшх
Ар^янгальскпИ
Бнж*м
44.W1
5 1001 секрет реестра W"心ws КТ
Д^<нслс
Pvcvku Редяиш»
6^1.50
G 12 урок1Ж'1син№п Самый дштчиныА
Ян'пк
Teppa<iR^n
15.40
7 1 / пшим к успеха* или npurnrvccitiw
flunnriexiiHici
6.60
К 1С:К*лпигтср»01,Свмотчюсл1. Ikpciinr
К*“・гн"
209.00
У 3D Studio МАХ 2 5 справочинк
Марив
66.00
Ю 5D Studin МАХ 3 Учебный ш ре *
rjincp
II4S0
11 ?Г> Siudio МАХ КЗ Сие1Пффектм н
U\ 70
12 5D SiudMi МАХПжтренннй мир. Гом
'Хгонмст-Эпишр
加oCi巾
165.00
13 5D Studin Млх 3.0 иг объек-щ до
К\ЛЛПП1
ВНУ<»нк1-11е«грб\ pi
1 出.00
14 6()01№ ксмых ц м^шкальных
Жимй&ик
BHV4JiuiKf-t Ieitp6vpf
心 Q8 иип:мч;тгш Wmds/w、9B с
ДМК01КЯ
7Л,10
以1吧"上心晦d ¥兰一 *切н嬉整?尸М»1雕1
^"бПЙГуйадеГ^,■~
н@.图叫方心熏八 и * *:口哪8名旣阊
Прайс-;1ис1 книг 24,03.20»
Рис. 8.21. Отчет в окне утилиты Acrobat Reader
Основы технологии Rave Reports
Технология Rave Reports разработана компанией Nevrona Designs, которая является авторизованным членом Комитета открытых систем и разрабатывает программное обеспечение для Delphi н C++ Builder. В ее основе лежит идея отделения процесса разработки отчета от процесса его создания за счет использования промежуточного документа, который называется проектом отчета. Проект отчета готовится с помощью среды Rave1 (Report Authoring Visual Environment — визуальная среда автора отчета), а в создаваемую программу внедряется так называемая машина генерации отчета, которая по данным, полученным из файла проекта, строит документ отчета.
В категории Rave палитры компонентов (эта категория доступна только в режиме создания VCL-приложений; она не видна в окне Categories, так как располагается за категорией Internet — для доступа к ней используйте полосу прокрутки) имеется два ключевых компонента — RvProj ect и RvSystemt перенос которых в программу внедряет в нее машину генерации отчетов. Проект будущего отчета создается заранее с помощью утилиты Report Manager Designer, которая вызывается из Delphi и взаимодействует с загруженной в среду Delphi программой.
Пример создания отчета
В следующем примере будет создан простейший отчет, показанный на рис. 8.22: 1. Для создания главного окна начните новый проект, поместите на пустую форму компонент Database (категория BDE), раскроете список его свойства AliasName н выберите псевдоним В工BLDATA, в свойстве DatabaseName введите ААА.
В буквальном переводе с английского《rave* означает сбредить», «бушевать», «выть亂
Прайс-лист книг
№Название /Автор /ИздательствоЦена110 минут на урок MS Wsd 200ь /Эйткен 启нпьамс4621Q мнн/т на урок Wincows &8 /Фултон 公н町9M~nixe23,110 мнм нз ydoh Cicbom самостодтепьнб MS Excel 2000 /бпто /Вюьямс46,24100 компонентов общего назначения 6н6пи?теки Delphi 5/Аркангвпьсютй /Бином4451001 секрет реестра Windows NT Щзннепс /Русская Редакция60.5Е12 уроков тенниса Самьч! доступный самоучитель дпя всех /Янчук jTeppa-Спорт1”713 шагов к v<nexv или пратичесние советы как бькпро достичь карьеры е / /Пс-литехника6f£1С Бу^гаптерия Самиучитепь Версии 7 5 и 7 7 в вопроса» и ответах /Комягин ГТркт^м力20£g3D Study MAX 2.5 справочник диадое /Питер86103D Stud2 МАХ 3 Учебный курс + CD-ROM /Марое /Питер115.5и3D Studio MAX R3 Слецэффекгь! и дизайн + CdROM йепп /Диапекшка伯3?123D Stuciu МАХ Внутренний мир Там 2 + CCbROM /Эспиноза-Эгипар /ДиаСофт您1-3D Studio Мах 3 0 от о6ьек!а до анимации + CD-ROM /Кулашн /ВНУ-Санкт-Петов^г1414600 звуковых и мг^ьзпьхых программ /Живайкмн /ВНУ-Сзнкг-Петербург83.61598 вопрогоо по Windows 98 с ответами /Дьяконов "二。non70.116Access 2noij дпа попьзоеатепя Русифицированная версия /Ьзсько /BHV-киее8 517Access 97 Руководство по макроязыку и VBA * COROM /Ноеалм /НОРМ18718Access 97 Энцихлопедия пользователя + COROM /Двайн ЩиаСоФт27€的Adininistrennq SOL Server 7 Сертиф0кацианнь|А эюзмен-экстерном(7П-028) /гeqCvc /Пите71Л20А"Ве Illustrator 9 0 в лодпннни» е /Пономаренко BHV-Санит-Пвтербург66力Aoobe lllu^baior 3 /чабный курс /Тайц /Питер*3.62?Adobe InDesiqr в подпиннт"? /Та^цы /BHV-С анкст-Петорбл'!103.J23Adobe Photoshop 5 для на4H<82щих и не только Л донников /Поэнавате-пьная нм ига*30.824Adobe Pholoshop 50в подлиннике /Пономаренко /ВН V- С анкт-Пегербург'70,425Adoba Photoshop 5 03a 24 часа.Освой самостоятельно /Роуз 仙wm77№Название /Автор /ИздательствоЦена110 минут на урок MS Wsd 200ь /Эйткен 启нпьамс4621Q мнн/т на урок Wincows &8 /Фултон 公н町9M~nixe23,110 мнм нз ydoh Cicbom самостодтепьнб MS Excel 2000 /бпто /Вюьямс46,24100 компонентов общего назначения 6н6пи?теки Delphi 5/Аркангвпьсютй /Бином4451001 секрет реестра Windows NT Щзннепс /Русская Редакция60.5Е12 уроков тенниса Самьч! доступный самоучитель дпя всех /Янчук jTeppa-Спорт1”713 шагов к v<nexv или пратичесние советы как бькпро достичь карьеры е / /Пс-литехника6f£1С Бу^гаптерия Самиучитепь Версии 7 5 и 7 7 в вопроса» и ответах /Комягин ГТркт^м力20£g3D Study MAX 2.5 справочник диадое /Питер86103D Stud2 МАХ 3 Учебный курс + CD-ROM /Марое /Питер115.5и3D Studio MAX R3 Слецэффекгь! и дизайн + CdROM йепп /Диапекшка伯3?123D Stuciu МАХ Внутренний мир Там 2 + CCbROM /Эспиноза-Эгипар /ДиаСофт您1-3D Studio Мах 3 0 от о6ьек!а до анимации + CD-ROM /Кулашн /ВНУ-Санкт-Петов^г1414600 звуковых и мг^ьзпьхых программ /Живайкмн /ВНУ-Сзнкг-Петербург83.61598 вопрогоо по Windows 98 с ответами /Дьяконов "二。non70.116Access 2noij дпа попьзоеатепя Русифицированная версия /Ьзсько /BHV-киее8 517Access 97 Руководство по макроязыку и VBA * COROM /Ноеалм /НОРМ18718Access 97 Энцихлопедия пользователя + COROM /Двайн ЩиаСоФт27€的Adininistrennq SOL Server 7 Сертиф0кацианнь|А эюзмен-экстерном(7П-028) /гeqCvc /Пите71Л20А"Ве Illustrator 9 0 в лодпннни» е /Пономаренко BHV-Санит-Пвтербург66力Aoobe lllu^baior 3 /чабный курс /Тайц /Питер*3.62?Adobe InDesiqr в подпиннт"? /Та^цы /BHV-С анкст-Петорбл'!103.J23Adobe Photoshop 5 для на4H<82щих и не только Л донников /Поэнавате-пьная нм ига*30.824Adobe Pholoshop 50в подлиннике /Пономаренко /ВН V- С анкт-Пегербург'70,425Adoba Photoshop 5 03a 24 часа.Освой самостоятельно /Роуз 仙wm77
№
Название /Автор /Издательство
Цена
1
10 минут на урок MS Wsd 200ь /Эйткен 启нпьамс
462
1Q мнн/т на урок Wincows &8 /Фултон 公н町9M~nixe
23,1
10 мнм нз ydoh Cicbom самостодтепьнб MS Excel 2000 /бпто /Вюьямс
46,2
4
100 компонентов общего назначения 6н6пи?теки Delphi 5/Аркангвпьсютй /Бином
44
5
1001 секрет реестра Windows NT Щзннепс /Русская Редакция
60.5
Е
12 уроков тенниса Самьч! доступный самоучитель дпя всех /Янчук jTeppa-Спорт
1”
7
13 шагов к v<nexv или пратичесние советы как бькпро достичь карьеры е / /Пс-литехника
6f
£
1С Бу^гаптерия Самиучитепь Версии 7 5 и 7 7 в вопроса» и ответах /Комягин ГТркт^м力
20£
g
3D Study MAX 2.5 справочник диадое /Питер
86
10
3D Stud2 МАХ 3 Учебный курс + CD-ROM /Марое /Питер
115.5
и
3D Studio MAX R3 Слецэффекгь! и дизайн + CdROM йепп /Диапекшка
伯3?
12
3D Stuciu МАХ Внутренний мир Там 2 + CCbROM /Эспиноза-Эгипар /ДиаСофт
您
1-
3D Studio Мах 3 0 от о6ьек!а до анимации + CD-ROM /Кулашн /ВНУ-Санкт-Петов^г
14
14
600 звуковых и мг^ьзпьхых программ /Живайкмн /ВНУ-Сзнкг-Петербург
83.6
15
98 вопрогоо по Windows 98 с ответами /Дьяконов "二。non
70.1
16
Access 2noij дпа попьзоеатепя Русифицированная версия /Ьзсько /BHV-киее
8 5
17
Access 97 Руководство по макроязыку и VBA * COROM /Ноеалм /НОРМ
187
18
Access 97 Энцихлопедия пользователя + COROM /Двайн ЩиаСоФт
27€
的
Adininistrennq SOL Server 7 Сертиф0кацианнь|А эюзмен-экстерном(7П-028) /гeqCvc /Пите
71Л
20
А"Ве Illustrator 9 0 в лодпннни» е /Пономаренко BHV-Санит-Пвтербург
66
力
Aoobe lllu^baior 3 /чабный курс /Тайц /Питер
*3.6
2?
Adobe InDesiqr в подпиннт"? /Та^цы /BHV-С анкст-Петорбл'!
103.J
23
Adobe Photoshop 5 для на4H<82щих и не только Л донников /Поэнавате-пьная нм ига*
30.8
24
Adobe Pholoshop 50в подлиннике /Пономаренко /ВН V- С анкт-Пегербург'
70,4
25
Adoba Photoshop 5 03a 24 часа.Освой самостоятельно /Роуз 仙wm
77
№
Название /Автор /Издательство
Цена
1
10 минут на урок MS Wsd 200ь /Эйткен 启нпьамс
462
1Q мнн/т на урок Wincows &8 /Фултон 公н町9M~nixe
23,1
10 мнм нз ydoh Cicbom самостодтепьнб MS Excel 2000 /бпто /Вюьямс
46,2
4
100 компонентов общего назначения 6н6пи?теки Delphi 5/Аркангвпьсютй /Бином
44
5
1001 секрет реестра Windows NT Щзннепс /Русская Редакция
60.5
Е
12 уроков тенниса Самьч! доступный самоучитель дпя всех /Янчук jTeppa-Спорт
1”
7
13 шагов к v<nexv или пратичесние советы как бькпро достичь карьеры е / /Пс-литехника
6f
£
1С Бу^гаптерия Самиучитепь Версии 7 5 и 7 7 в вопроса» и ответах /Комягин ГТркт^м力
20£
g
3D Study MAX 2.5 справочник диадое /Питер
86
10
3D Stud2 МАХ 3 Учебный курс + CD-ROM /Марое /Питер
115.5
и
3D Studio MAX R3 Слецэффекгь! и дизайн + CdROM йепп /Диапекшка
伯3?
12
3D Stuciu МАХ Внутренний мир Там 2 + CCbROM /Эспиноза-Эгипар /ДиаСофт
您
1-
3D Studio Мах 3 0 от о6ьек!а до анимации + CD-ROM /Кулашн /ВНУ-Санкт-Петов^г
14
14
600 звуковых и мг^ьзпьхых программ /Живайкмн /ВНУ-Сзнкг-Петербург
83.6
15
98 вопрогоо по Windows 98 с ответами /Дьяконов "二。non
70.1
16
Access 2noij дпа попьзоеатепя Русифицированная версия /Ьзсько /BHV-киее
8 5
17
Access 97 Руководство по макроязыку и VBA * COROM /Ноеалм /НОРМ
187
18
Access 97 Энцихлопедия пользователя + COROM /Двайн ЩиаСоФт
27€
的
Adininistrennq SOL Server 7 Сертиф0кацианнь|А эюзмен-экстерном(7П-028) /гeqCvc /Пите
71Л
20
А"Ве Illustrator 9 0 в лодпннни» е /Пономаренко BHV-Санит-Пвтербург
66
力
Aoobe lllu^baior 3 /чабный курс /Тайц /Питер
*3.6
2?
Adobe InDesiqr в подпиннт"? /Та^цы /BHV-С анкст-Петорбл'!
103.J
23
Adobe Photoshop 5 для на4H<82щих и не только Л донников /Поэнавате-пьная нм ига*
30.8
24
Adobe Pholoshop 50в подлиннике /Пономаренко /ВН V- С анкт-Пегербург'
70,4
25
Adoba Photoshop 5 03a 24 часа.Освой самостоятельно /Роуз 仙wm
77
Рис. 8.22. Пример отчета в окне предварительного просмотра
Поместите на форму компонент TTable (категория BDE), в списке его свойства Databas巳Nam巳 выберите локальный псевдоним AAA, а в списке свойства ТйЫеЫйте — таблицу BOOKS. Назовите компонент именем Books (свойство Name). Создаете для набора данных 5 объектов-полей, связав их с полями BookXD, BName, В Au t.hor, В Publish и BPrice. Для объекта BName нгншши- те такой обработчик события OnGetText:
procedure TForml.BooksBNarneGetText(Sender: TField; var Texc: String; DisplayText: Boolean);
begin
Text :二 BooksSNarrie . Value+ 1 / ' ^-BooksBAuthor. Value + '/1+BooksВPublish.Value;
end;
Разместите на форме компонент DataSource (категория Data Access) и свяжите его свойство DataSet; с набором данных Books. Откройте набор данных (Active 二 True).
Поместите на форму две панели TPanel (категория Standard). Установите для одной из них свойство Align 二 alBottom, для другой — Align 二 alClient. Очистите их свойства Caption.
На верхнюю панель поместите компонент DBGrid (категория Data Controls), установите в его свойство Align значение alClient, а в свойство DataSource —
Основы технологии Rave Reports 325
значение DataSourcel. Создайте для сетки два столбца, связав первый с полем BName, а второй — с полем BPrice. В свойство Title.Name первого поместите значение Название /Автор /Издательство, а в такое же свойство второго — значение Цена. Установите ширину первого столбца (свойство Width) равной 500.
На нияснюю панель поместите навигатор DBNavigator (категория Data Controls) ii кнопку TButton (категория Standard). Свяжите навигатор с источником DataSourcel н оставьте в нем только первые 4 кнопки (в примере не предполагается изменение набора данных). В свойство Caption кнопки поместите значение Показать отчет.
Вид формы на этом этапе показан на рис. 8.23.
.餃峥隰*S&llows 98
10 z图ут на урок.Освой самостоятельно MS Excel 2000
: 100 компонентов общего назначения библиотеки Delphi 5
U 001 секрет реестра Windows МТ
: 12 уроксе тежиса.Самый доступный самоучитель для всех
■ 13 шагов к успеху или практические советы как быстро достичь карьеры в
: 1С:Бухгалтерия.Самоучитель.Версии 7.5 и 7.7 в вопросах и ответах
3D Studio МАХ 2.5 справочник
3D Studio МАХ 3.Учебный курс + CD-ROM
и1213и12133D Studio МАХ ЯЗ.Спецэффекты и дизайн + CD-ROM
и
12
13
и
12
13
3D Studio МАХ .Внутренний мир-Тон 2 + CD-ROM
■・.na$asaTb CFT4et : J■・.na$asaTb CFT4et : J3D Studio Max 3.0 от объекта до анимации + CD-ROM
■・.na$asaTb CFT4et : J
■・.na$asaTb CFT4et : J
Рис. 8.23. Форма на этапе конструирования
Сохраните проект на жестком диске под яменем RaveRepDemo.
До этого момента мы создали лишь программу с набором данных. Теперь начинается собственно создание отчета.
Поместите на форму компонент TRVTabl eConnect (категория Rave) и свяжите его с набором данных Books (свойство Table).
Вся дальнейшая работа осуществляется под управлением утилиты Rave Reports Designer. Для ее вызова выберите в главном меню команду Tools ► Rave Reports Designer. На экране появится окно, показанное на рис. 8.24.
Как видите, утилита Rave Reports Designer имеет собственную палитру компонентов, дерево объектов, инспектор объектов и набор инструментальных кнопок. Центральную часть окна занимает рабочая область с двумя вкладками: Раде Designer и Event Editor. Первая используется подобно окну формы среды Delphi —
326 Глава 8 • Отчеты
на ней автор отчета разметает нужные компоненты из палитры Rave Reports Designer (но никак не из палитры Delphi). На вкладке Event Editor он может написать код для обработчиков событий OnBeforePrint, OnBeforeReport, OnAfterPrint, OnAfterReport, OnGetText для любого размещенного на вкладке Page Designer компонента отчета. Обработчики пишутся на языке, который представляет собой подмножество языка Delphi.
Инспе!сгор Инструментальные объектов кнопкиИнспе!сгор Инструментальные объектов кнопкиОбласть компонентов и инструментальных панелейОбласть компонентов и инструментальных панелей
Инспе!сгор Инструментальные объектов кнопки
Инспе!сгор Инструментальные объектов кнопки
Область компонентов и инструментальных панелей
Область компонентов и инструментальных панелей
I?艮,.ГI?艮,.ГДерево объектовДерево объектов9(^ЛяГ-:-;9(^ЛяГ-:-;0*МлсШ■УЙКаояГ0*МлсШ■УЙКаояГОбласть формирования отчетаОбласть формирования отчета:QWM№^QVWdtt MpirStR •% .:QWM№^QVWdtt MpirStR •% .Nam; pmn・rty [: ftwrura cilht?;ccopowt The name t мп on^ certaini:hHMiA-Z. 09md the 盛闕岂買4&k ^Nam; pmn・rty [: ftwrura cilht?;ccopowt The name t мп on^ certaini:hHMiA-Z. 09md the 盛闕岂買4&k ^Рис- 8.24. Окно Rave Reports DesignerРис- 8.24. Окно Rave Reports Designer
I?艮,.Г
I?艮,.Г
Дерево объектов
Дерево объектов
9(^ЛяГ-:-;
9(^ЛяГ-:-;
0*МлсШ
■УЙКаояГ
0*МлсШ
■УЙКаояГ
Область формирования отчета
Область формирования отчета
:QWM№
^QVWdtt MpirStR •
% .
:QWM№
^QVWdtt MpirStR •
% .
Nam; pmn・rty [: ftwrura cilht?;
ccopowt The name t мп on^ certaini:
hHMiA-Z. 09md the 盛闕岂買4&k ^
Nam; pmn・rty [: ftwrura cilht?;
ccopowt The name t мп on^ certaini:
hHMiA-Z. 09md the 盛闕岂買4&k ^
Рис- 8.24. Окно Rave Reports Designer
Рис- 8.24. Окно Rave Reports Designer
Mi",. ”:;«■;;.1;;:. "Г:»«”.*!«*;;":":..3>;: ;;“:,..
I: Л* RceRg
:;S ^ Rtport lb«y
I86kMpадеСаШсб
上 ^ DataV«wD«tun*y
С помощью команды File > New Data Object вызовите окно Data Connections, в котором выберите продолжение Direct Data View и — после щелчка на кнопке Next — RvTableConnectionl. Таким образом отчет связывается с источником данных, которые он будет отображать.
Командой Tools ► Report Wizards 卜 Simple Table вызовите эксперт создания отчета по данным, получаемым из единственной таблицы. Этот эксперт с помощью последовательно раскрывающихся окон позволяет задать основные параметры отчета. В первом окне (рис. 8.25) выбирается источник данных (DataViewl), во втором — отображаемые поля (отметьте флажками все поля или установите флажок All). В следующем окне вы можете изменить порядок следования в отчете выбранных полей (в данном случае оставьте все без изменения). Окно Report Layout Options позволяет задать заголовок отчета (введите
Основы технологии Rave Reports 327
в строку Report Title текст Прайс-лист книг) и ширину полей (группа строк Report Margin). Для экономии бумаги введите во все строки значение 0,3.
Рис. 8.25. Начальное окно эксперта создания отчетаРис. 8.25. Начальное окно эксперта создания отчета
Рис. 8.25. Начальное окно эксперта создания отчета
Рис. 8.25. Начальное окно эксперта создания отчета
Заключительное окно (рис. 8.26) предназначено для выбора шрифтов, которыми будут отображаться три основные части отчета: его заголовок, заголовки полей и данные.
Title FontTitle FontSelect the <Шгм1 fonts to им for thta report
Title Font
Title Font
Прайс-лист книг!
Caption FontCaption Fontkg?雙1国鹤I
Caption Font
Caption Font
The Caption Font Will Look Like This
BodyFontBodyFontChange FontChange FontThe Printed Data Will Look Like ThisThe Printed Data Will Look Like ThisмIII1мIII1
BodyFont
BodyFont
Change Font
Change Font
The Printed Data Will Look Like This
The Printed Data Will Look Like This
м
II
I1
м
II
I1
Рии 8.26. Завершающее окно эксперта создания отчета
После щелчка на кнопке Generate в завершающем окне эксперта происходит начальная генерация файла проекта отчета, который появляется в окне утилиты Rave Designer (рис. 8.27).
328 Глава 8 • Отчеты
BPUBLJSHBRC二注:二.:;?.JF^可强IBPUBLJSHBRC二注:二.:;?.JF^可强I寿q^^^T 立jZH £(Й№ 中,寿q^^^T 立jZH £(Й№ 中,Прайс-лист книгПрайс-лист книгРис. 8.27. Вид отчета после начальной генерацииРис. 8.27. Вид отчета после начальной генерации:IY c?t!l^riT1 ^1^ ОуФ*41^*^1M"^:IY c?t!l^riT1 ^1^ ОуФ*41^*^1M"^IVо*№^ячкггмимие«м :•:••,■■: . :.■ BiBNAMEBAUTHORwa^^i^rit.q^iyn^^M.…二工.二二._IVо*№^ячкггмимие«м :•:••,■■: . :.■ BiBNAMEBAUTHORwa^^i^rit.q^iyn^^M.…二工.二二._.:;巾 © Acpurt U>.y : ◎ G3"«goU 门.$♦ G“V«wO3.:;巾 © Acpurt U>.y : ◎ G3"«goU 门.$♦ G“V«wO3
BPUBLJSHBRC
二注:二.:;?.JF^可强I
BPUBLJSHBRC
二注:二.:;?.JF^可强I
寿q^^^T 立jZH £(Й№ 中,
寿q^^^T 立jZH £(Й№ 中,
Прайс-лист книг
Прайс-лист книг
Рис. 8.27. Вид отчета после начальной генерации
Рис. 8.27. Вид отчета после начальной генерации
:IY c?t!l^riT1 ^1^ ОуФ*41^*^1M"^
:IY c?t!l^riT1 ^1^ ОуФ*41^*^1M"^
IVо*№^ячкггмимие«м :•:••,■■: . :.■ BiBNAMEBAUTHOR
wa^^i^rit.q^iyn^^M.…二工.二二._
IVо*№^ячкггмимие«м :•:••,■■: . :.■ BiBNAMEBAUTHOR
wa^^i^rit.q^iyn^^M.…二工.二二._
.:;巾 © Acpurt U>.y : ◎ G3"«goU 门.$♦ G“V«wO3
.:;巾 © Acpurt U>.y : ◎ G3"«goU 门.$♦ G“V«wO3
На этом этапе полезно сохранить файл проекта отчета. Выберите команду File ► Save или щелкните на соответствующей кнопке инструментальной панели. Сохраните файл проекта Projectl.rav в той же папке, в которой хранится проект RaveDemo.
Теперь внесем в отчет изменения:
о сформируем дату генерации;
о изменим формат вывода данных;
。введем нумерацию страниц;
о расчертим отчет горизонтальными и вертикальными линиями.
Многие системные параметры отчета, в том числе текущая дата и номер текущей страницы, доступны в компоненте DataText палитры компонентов утилиты Rave Repots Designer (вкладка Report). Его свойство Da匸aField позволяет не только ссылаться на нужное поле данных, но и использовать выражения с участием системных переменных,
Для формирования даты разместите сразу под заголовком отчета компонент DataText (вкладка Report палитры компонентов утилиты Rave Reports Designer) и установите для него следующие свойства:
о Left = 0;
о Width = 7,9;
Основы технологии Rave Reports 329
о Top = 0,6;
о FonrJusti fy = pjCenter;
O Font 二 Arial, 14, Bold.
ПРИМЕЧАНИЕ
В Rave Reports Designer координаты задаются в дюймах. При вводе вещественных чи- ссл знак разделения дробной н iie/ioii Hacrcii зависит от лок;ип1зацн11. Для русифици- poBamioii версии Windows таким разделителем является запятая, для англоязычной (панъевропейский) — точка.
В CBoiicTno DataField поместите следующий текст:
"он ” S.Repor l. . Da^eLong
Как видите, вместо имени поля в свойство можно помещать произвольное выражение с участием системных переменных (в нашем случае — с переменной Report. DateLong, содержащей текущую дату в полном формате ДД Месяц ГГГГ). Другой вариант формирования значения этого поля: раскроете редактор поля (кнопки с многоточием в правом углу значения свойства), в поле Data Text окна Data Text Editor введите ' от ' -*-, раскройте список Report Variables и выберите н нем пункт DateLong, после чего щелкните на кнопке Insert Report Var (рис. 8.28).
:回m…- DafaVfe^:回m…- DafaVfe^BOOKIDBOOKIDOSeted吋 DataVtewlOSeted吋 DataVtewl不产般不y酬巒竺;.!:Datelong不产般不y酬巒竺;.!:Datelong:了瓦 дедр&твтю:了瓦 дедр&твтюm L1ns也“ ”.〕‘m L1ns也“ ”.〕‘
:回m…- DafaVfe^
:回m…- DafaVfe^
BOOKID
BOOKID
OSeted吋 DataVtewl
OSeted吋 DataVtewl
不产般不y酬巒竺;.!:Datelong
不产般不y酬巒竺;.!:Datelong
:了瓦 дедр&твтю
:了瓦 дедр&твтю
m L1ns也“ ”.〕‘
m L1ns也“ ”.〕‘
Рис. 8.28. Формирование значения поля DataField с помощью редактора
Заметьте: редактор выражений поддерживает как синтаксис C# ("от "&), так и синтаксис Delphi (' от ' +).
330 Глава 8 • Отчеты
Для изменения формата отображаемых данных удалите с нижней полосы компоненты DataText3 и DataText4 для отображения полей BAuthor и В Publish, а в свойство DataField компонента DataText2 (для поля BNaine) поместите такую строку: BName+ ' / • +BAuthor+ ' /' +BPublish. Установите для этого компонента свойства Left = 0,39 и Width 二 7. Для компонента DataTextl (поле Bookid) — свойства Left = 0, Width = 0,3. Для компонента DataText5 (поле BPrice) ~ свойства Left = 7,4, Width = 0,5. В свойства FontJustify обоих компонентов поместите значение pj Right.
Соответственно измените названия колонок в средней полосе: № вместо Bookid, Название /Автор /Издательство вместо BNama и Цена вместо BPrice.
Чтобы вставить в отчет номера страниц, нужно предусмотреть в проекте страницы пространство для размещения компонента DataText. Эксперт создания отчета отвел для заголовков и данных всю страницу. Щелкните на компоненте DataViewlRegion в дереве объектов (предварительно раскройте узлы Report Library, Report 1, MainPage) и установите в его свойство Height значение 9,7. С помощью вертикальной полосы прокрутки сместите изображение страницы в окне Page Design к самому ее концу и вставьте под серым пространством компонент DataText (рис. 8.29). В его свойство DataField поместите такую строку:
'Стр. 1^Report.CurrentPage+1 из '+Report.Totalpages'
:注:注aa史史:ГСтр. ** R«port.Curr*nlPao> * *иа '* Raport.TotilFaoed:ГСтр. ** R«port.Curr*nlPao> * *иа '* Raport.TotilFaoed11rlpВТ務EI'士q弊曰承EMff諄舞雷令當第疗乜11^^^::);-+1」+;",*;,},晶特:一而.||1)1" 一、: 丁:一;".",y,*•a*-^'~,:"":lr.tJ1"":THhX[""."**r,3"^Mlt?W》.J*J:a:°t+:”尸.f一:于廿"■•■r■vrf~~*ur*E,r,ntm*nTVri‘^^[SgeOwSw M4,*11rlpВТ務EI'士q弊曰承EMff諄舞雷令當第疗乜11^^^::);-+1」+;",*;,},晶特:一而.||1)1" 一、: 丁:一;".",y,*•a*-^'~,:"":lr.tJ1"":THhX[""."**r,3"^Mlt?W》.J*J:a:°t+:”尸.f一:于廿"■•■r■vrf~~*ur*E,r,ntm*nTVri‘^^[SgeOwSw M4,*# RxePi畢cl# RxePi畢cl中RBI& Q Re«o紋中RBI& Q Re«o紋* H D“WBw1R«ggn ©&ар“£м^од D“ Vi>w OielanvyВ D“AW1* H D“WBw1R«ggn ©&ар“£м^од D“ Vi>w OielanvyВ D“AW1Рис. 8.29. Нумерация страниц отчетаРис. 8.29. Нумерация страниц отчета;軍/!3 ЙМ8ЙЙИР*單‘-Bw遍嬲te>而嶼汴* jswdi向加srAmu11ft5*1卄』感2 一
:注
:注
a
a
史
史
:ГСтр. ** R«port.Curr*nlPao> * *иа '* Raport.TotilFaoed
:ГСтр. ** R«port.Curr*nlPao> * *иа '* Raport.TotilFaoed
11rlpВТ務EI'士q弊曰承EMff諄舞雷令當第
疗乜11^^^::);-+1」+;",*;,},晶特:一而.||1)1" 一、: 丁:一;".",y,*•a*-^'~,:"":lr.tJ1"":THhX[""."**r,3"^Mlt?W》.J*J:a:°t+:”尸.f一:于廿"■•■r■vrf~~*ur*E,r,ntm*nTVri‘
^^[SgeOwSw M4,*
11rlpВТ務EI'士q弊曰承EMff諄舞雷令當第
疗乜11^^^::);-+1」+;",*;,},晶特:一而.||1)1" 一、: 丁:一;".",y,*•a*-^'~,:"":lr.tJ1"":THhX[""."**r,3"^Mlt?W》.J*J:a:°t+:”尸.f一:于廿"■•■r■vrf~~*ur*E,r,ntm*nTVri‘
^^[SgeOwSw M4,*
# RxePi畢cl
# RxePi畢cl
中RBI
& Q Re«o紋
中RBI
& Q Re«o紋
* H D“WBw1R«ggn ©&ар“£м^од D“ Vi>w Oielanvy
В D“AW1
* H D“WBw1R«ggn ©&ар“£м^од D“ Vi>w Oielanvy
В D“AW1
Рис. 8.29. Нумерация страниц отчета
Рис. 8.29. Нумерация страниц отчета
Установите для компонента шрифт Arial высотой 14 и начертанием Bold.
Чтобы расчертить отчет линиями, поместите на среднюю полосу (объект DataViewlBand в дереве объектов) компонент HLine (вкладка Drawing) со свойствами Тор = 0, Left = 0, Width = 7,9, а также два компонента VLine с параметрами Тор = 0, Height = 0?24, Left = 0,35 (для первого) и Left = 7,4 (для второго).
На нижнюю полосу с данными поместите по два компонента HLine и VLine. Длина горизонтальных линий равна ширине проекта отчета (7,9 единицы), а свойство Тор равно 0 для первой и 0,2 для второй. Высота вертикальных линий равна высоте полосы (0,2), а свойство Left равно 0,35 для первой и 7,4 для второй.
Для предварительного просмотра формируемого отчета нажмите клавишу F9 или щелкните на соответствующей инструментальной кнопке.
После подготовки проекта отчета сохраните его на диске, закройте окно утилиты Rave Designer и вернитесь в Delphi. Поместите на форму компонент RvProject, в его свойстве ProjectFile укажите ссылку на файл проекта Projectl.rav. Напишите такой обработчик щелчка на кнопке Показать отчет:
procedure TForml.ButtonlClick{Sender: TObject);
begin
RvProjectl.Execute
end;
Привязка проекта отчета к приложению
Имеет смысл обсудить вот какую проблему. Для организации связи приложения с проектом отчета имя файла отчета помещается в свойство ProjectFile компонента TRvProject. Это делает программу чувствительной к положению ее файла на диске или к изменению в ходе ее работы текущей папки. В самом деле, в свойство ProjectFile можно поместить полное имя файла с маршрутом доступа или только имя файла. В первом случае программа будет зависеть от положения файла проекта, что затруднит ее тиражирование или продажу. Во втором случае программа и файл проекта просто должны быть в одной папке, и эта папка должна быть текущей. Это снимает проблему тиражирования, но если в ходе работы программы произойдет смена текущей папки, связь программы с проектом окажется потерянной. Выходом из положения может быть указание в свойстве ProjectFile только имени файла и дополнение этого имени полным маршрутом доступа в момент старта программы. Например:
procedure TForml.FormCreate(Sender: TObject);
var
S: String;
begin
S :二 Арр1ication«ExeName;
while S[Length(S)]<>'\1 do
Delete(S/ Length(S), 1);
rvProject.ProjectFile := S+rvProject.ProjectFile end;
Визуальная среда Rave Reports Designer
Как уже говорилось» для технологии Rave Reports характерно то. что отчет создается специальной машиной генерации отчета по указаниям, получаемым из файла проекта отчета. Файл проекта разрабатывается с помощью утилиты Rave Reports Designer, которая создает особую визуальную среду (см. рис. 8.24).
С помощью главного меню решаются задачи общего управления проектом (команда Rie — создание нового проекта, включение в проект нового отчета, связь с наборами данных и т. д.), настройки параметров среды и проекта (команды Zoom и Edit ► Preferences) и вызова экспертов создания отчетов (команда Tools).
Некоторые наиболее важные команды представлены восемью верхними инструментальными кнопками. Семь нижних инструментальных кнопок упрощают настройку среды.
Окно инспектора объектов во многом похоже на окно инспектора объектов среды Delphi. В нем отображаются свойства объекта, выбранного в области формирования отчета или в дереве объектов. Замечу, что свойства, определяющие положение и размеры объекта, по умолчанию задаются в дюймах. При этом разделитель целой и дробной частей в вещественных значениях определяется настройкой Windows (в русскоязычной ОС этим разделителем является запятая). С помощью команды Edit > Preferences > Default ► Units можно установить другие единицы измерения (в том числе миллиметры или пикселы). Однако эта установка будет действительной только для нового проекта. Ниже окна свойств находится вспомогательное окно, содержащее справку о выбранном свойстве.
Справа от инструментальных кнопок располагается область компонентов и инструментальных панелей. Представленные здесь вкладки перечислены в табл. 8.1.
Таблица 8.1. Назначение вкладок области компонентов и инструментальных панелей
ВкладкаНазначение
Drawing Компоненты для вставки в отчет простейших геометрических фигур
Bar CodeКомпоненты для отображения различных штриховых кодов
Standard Компоненты для вставки в отчет данных, не связанных с БД (поясняющие надписи, многострочный текст, изображения и т. и.)
Report Компонента для вставки в отчет данных из БД
Zoom Инструментальная панель с кнопкам”, управляющими масштабом отображаемого отчета
Colors Инструментальная панель для изменения цвета выделенного элемента отчета
Unes Инструментальная панель для управления толщиной и стилем текущей линии
FillsИнструментальная панель для выбора стиля заполнения текущей фигуры
FontsИнструментальная панель для выбора шрифта текущего элемента с текстом
Alignment Инструментальная панель для управления положением выбранного элемента
Область формирования отчета занимает всю центральную часть окна. В ее верхней часта находятся вкладки Page Designer и Event Editor, переключающие режимы отображения страницы отчета и ввода/редактирования обработчика того или иного события.
Режим Page Designer — основной режим окна. Отчет (точнее, его прообраз, представленный в режиме Page Designer) может содержать произвольное количество страниц, каждая из которых выбирается щелчком на соответствующей вкладке в верхней части окна. Прообраз страницы отображается в макете печатной страницы в центре окна. Программист формирует этот прообраз, размещая на макете компоненты из вкладок области компонентов. Он может в любой момент просмотреть или напечатать отчет, нажав клавишу F9 или щелкнув на соответствующей инструментальной кнопке.
С помощью команды Tools основную содержательную часть отчета можно сформировать, используя диалоговые окна соответствующих экспертов (для отчета с одной таблицей и отчета главный—детальный).
Расположенное в правой части окна утилиты Rave Reports Designer окно дерева объектов отображает основные объекты проекта отчета — отчеты (проект может содержать произвольное количество отчетов), глобальные страницы и объекты отображения данных из БД.
Режим Event Editor предназначен для создания/редактирования обработчиков событий OnAfterPrint, OnAfterReport, OnBeforePrint, OnBeforeReport, OnGetText. Язык программирования обработчиков является подмножеством языка Delphi. Если, например, на странице отчета расположить компонент Text3, то представленный ниже обработчик события OnBeforePrint этого компонента обеспечит нумерацию страниц отчета (начальное значение его свойства Text должно содержать символ 0):
Text3.Text := IntToStr(StrToInt(Text3.Text)+1);
Мои эксперименты с языком среды Rave Reports Designer (он не описан в документации) показали, что он имеет очень скромные возможности и рассчитан в основном на однострочные операторы присваивания, изменяющие значения того или иного свойства объекта, В нем нельзя использовать локальные переменные, блоки begin...end, try...endT условные операторы.
Составляющие проекта отчета
Любой проект отчета имеет три составные части:
библиотеку отчетов (узел Report Library в дереве объектов);
каталог глобальных страниц (узел Global Page Catalog);■
каталог объектов данных (узел Data View Dictionary).
Далее эти составляющие рассматриваются более подробно.
Библиотека отчетов
Библиотека отчетов хранит все созданные в проекте отчеты. Каждый отчет не зависит от других (эта связь подразумевается создателем проекта). В проекте
может быть сколько угодно отчетов. Чтобы начать очередной отчет в рамках текущего проекта, нужно выбрать команду Rie ► New Report или щелкнуть на соответствующей инструментальной кнопке.
Каждый отчет характеризуется своим уникальным именем (свойство Name) и/или полным именем (свойство FullName). В свойство Description следует поместить комментарий с краткой характеристакой отчета.
Первый созданный в проекте отчет становится умалчиваемым, то есть он печатается командой
RvProjectl.Execute;
Получить список всех отчетов программа может с помощью такого метода компонента TRvProject:
procedure GetProjectList(ReportList: TStrings; FullName: Boolean);
Параметр FullName при обращении к этому методу должен содержать значение True, если программист хочет получить список всех значений свойства FullName, и False, если нужен список значений свойства Name. Напечатать любой отчет из этого списка можно с помощью такого метода:
procedure ExecuteReport(ReportName: String);
Для удаления ненужного отчета из библиотеки отчетов следует выбрать его в дереве объектов и нажать клавишу Delete.
Каждый отчет может содержать одну или несколько страниц. Для добавления к отчету новой страницы используйте команду File ► New Report Page или щелкните на соответствующей инструментальной кнопке. Чтобы удалить страницу из отчета, выберите ее в дереве объектов и нажмите клавишу Delete. Если на странице проекта расположена полоса с данными, при печати эта страница воспроизводится столько раз, сколько необходимо для полного отображения всех данных. Каждая страница характеризуется уникальным (в пределах отчета) именем (свойство Name), а также свойствами Orientation, PageHeight, PageWidth и PageSize (последнее определяет размер бумаги, например Letter 8 1/2 by 11-inch или А4 Sheet, 210 by 297-mm). Страиицы по умолчанию печатаются в том порядке, в котором они представлены в дереве объектов. Свойство GotoPage определяет страницу, которая будет печататься после текущей. Изменение этого свойства позволяет печатать страницы в произвольном порядке.
Каталог глобальных страниц
Разработчик может создать одну или несколько глобальных страниц, то есть страниц, которые будут доступны из любого отчета. Таким способом можно оформить все отчеты единым образом, например, каждый отчет может предваряться печатью глобальной страницы с названием и эмблемой организации. Чтобы добавить к отчету глобальную страницу, нужно вызвать редактор его (отчета) свойства PageList (рис. 8.30), предварительно выделив отчет в библиотеке отчетов. В этом же редакторе можно изменить очередность печати страниц.
Рис. 8.30. Редактор свойства PageList отчета
Для создания глобальной страницы используется команда File ► New Global Page или соответствующая инструментальная кнопка. Чтобы отобразить глобальную страницу на вкладке Page Designer, нужно дважды щелкнуть на ее названии в дереве объектов. Таким способом можно выбирать не только глобальную, но и любую страницу любого отчета.
Каталог объектов данных
Каталог объектов данных содержит все определенные в проекте источники данных и, возможно, средства аутентификации пользователей для парольной защиты тех или иных отчетов. Для включения в проект нового объекта данных необходимо выбрать команду File ► New Data Object или щелкнуть на соответствующей инструментальной кнопке. В ответ появляется диалоговое окно, позволяющее уточнить тип объекта данных (рис. 8.31).
Вы можете выбрать один из следующих типов объектов данных:
Data Lookup Security Controller — организует аутентификацию пользователя при попытке просмотра или печати защищенного источника данных;
Database Connection — создает непосредственное соединение с источником данных на основе технологии dbGo.NET, BDE.NET, IBX.NET или dbExpress.NET с использованием специальных драйверов технолоши Rave Reports;
Direct Data View — создает соединение с набором данных, созданным в приложении Delphi;
Driver Data View — создает соединение с ранее созданным в проекте объектом данных Database Connection;
Simple Security Controller — организует список имен и паролей пользователей для доступа к отчету.
Data Object Туре
。Dflia Loolcup Seciriy Controller
❽ Database Connection
0 Direct Data View
Q Driver Data View 自 Simple Security ControRer
Рис. 8.31. Окно выбора типа объекта данных
Все объекты данных глобальны, то есть могут использоваться в любой странице любого отчета. Подробнее объекты данных рассматриваются в следующем разделе.
Объекты данных
Объектами данных называются различные объекты, связанные с импортом в проект внешних данных. Характерной особенностью технологии Rave Reports является возможность непосредственного (без использования Delphi) импорта данных из таблиц или запросов, а также импорта данных из произвольных файлов. Другая интересная особенность технологи — возможность парольной защиты публикуемых данных.
Доступ к наборам данных в приложении Delphi
Самый часто используемый объект данных — Direct Data View — обеспечивает импорт в отчет данных, полученных наборами данных (НД) приложения Delphi. Для взаимодействия отчета с НД в Delphi должны размещаться посредники —компоненты TRvDataSetConnection (универсальный связной компонент; в документации рекомендуется для клиентских НД в трехзвенной архитектуре), TRvTableConnection (для таблиц) и TRvQueryConnection (для запросов). Эти компоненты находятся в категории Rave среды Delphi. Каждый публикуемый в отчете НД должен снабжаться соответствующим посредником.
Для добавления в проект нового объекта нужно выбрать команду File ► New Data Object или щелкнуть на соответствующей инструментальной кнопке и затем в диалоговом окне выбрать вариант Direct Data View. После щелчка на кнопке Next этого окна появится новое окно, в котором предлагается выбрать один из определенных в приложении Delphi объектов-посредников.
Непосредственный доступ к данным
Технология Rave Reports позволяет создать отчет, не связанный с какими-либо наборами данных в приложении Delphi, а получающий эти данные непосредственно
из БД. Для этого предусмотрен специальный объект данных Database Connection. Этот объект может связываться с БД по технологии dbGo.NET (ADO), BDE.NET, dbExpress.NET (DBX) или IBX.NET
Для реализации это11 возможности нужно в окне Data Connections выбрать вариант Database Connection, а после щелчка на кнопке Next — одну из перечисленных технологий. Дальнейший диалог зависит от выбранной технологии доступа.
Если выбрана технология BDE, в новом диалоговом окне (рис. 8.32) нужно выбрать псевдоним БД (список Alias) и драйвер BDE для доступа к данным (список Driver).
Рис. 8.32. Настройка соединения BDE
Диалоговые окна настройки соединения для технологий ADO, DBX и IBX описаны в главах 4, 5 и 6 соответственно.
Хотя объект Database Connection обеспечивает техническую связь отчета с данными, он не может поставлять эти данные отчету. Поставщиком данных является объект Driver Data View. После выбора этого объекта в окне Data Connections (см. рис. 8.31) в следующем диалоговом окне предлагается выбрать один из определенных в проекте объектов Database Connection, после чего появляется окно, показанное на рис. 8.33.
Это окно автоматизирует процесс формирования SQL-запроса к БД. В правой его части содержится список всех таблиц БД. Запрос формируется путем пере- таскшзания таблиц на вкладку Layout, где они отображаются в виде перечней всех своих полей. По умолчашпо выбраны все поля (установлен флажок *). Установка флажка рядом с именем любого поля ведет к сбросу флажка * и позволяет выбрать только нужные поля. Для организации реляционных связей главный—детальный поле связи из дстальпоп) набора перетаскивается на ключевое поле главной таблицы. Также устанавливается связь с подстановочной таблицей.
После создания всех необходимых связей щелкните на кнопке Editor, чтобы увидеть автоматически сгенерированный SQL-запрос (рис. 8.34).
Рис. 8.33. Окно формирования SQL-запросаРис. 8.33. Окно формирования SQL-запросаDesignerDesignerРис. 8.34. Окно просмотра/редактировакия запросаРис. 8.34. Окно просмотра/редактировакия запросаSQLEditoi .SQLEditoi .QUset-DefmdSQLQUset-DefmdSQLSelect
Рис. 8.33. Окно формирования SQL-запроса
Рис. 8.33. Окно формирования SQL-запроса
Designer
Designer
Рис. 8.34. Окно просмотра/редактировакия запроса
Рис. 8.34. Окно просмотра/редактировакия запроса
SQLEditoi .
SQLEditoi .
QUset-DefmdSQL
QUset-DefmdSQL
Tl.-.
T2.-.
ТЗЯЯМЮ.
T3.FNAME.
■ T4.TYPEIO.
:T4.TNAME.
T5.BDQKID.
.T5.BMAME, :T5BAUTHOR.
j T5.BPUBLISH
NAKLS Tl.
MOVES T2.
.FIRMS ТЭ.
TYPES T4.
BOOKS T5
T2.NAKLIO-Tl HAKLID AND T3,FIRMID-T1NFIRMAND
T4.TYPEID-TINTYPE AND
:15.80OKID-T2MB0QK
При необходимости этот запрос можно редактировать. Например, добавить к нему секцию ORDER BY ИЛИ GROUP BY,
Импорт в отчет произвольных внешних файлов
С помощью связного компонента TRvCus tomConnect i on можно импортировать в отчет данные из внешнего файла. Характер дамных, хранящихся в файле, может быть любым — лишь бы программист умел с ними работать.
Поскольку утилита Rave Designer не распознает формат файловых данных, основная работа возлагается на программиста. Он должен создать как минимум три обработчика событий компонента TRvCus t omConnec t i on:
в обработчике события OnOpen необходимо определить общее количество строк отчета и поместить это число в свойство DataRows компонента;
в обработчике события OnGetCols с помощью метода WriteField компонента определяются количество, тип и ширина всех полей отчета;
в обработчике события OnGetRow программист должен передать в отчет значения всех полей для очередной строки отчета.
ВНИМАНИЕ
Поскольку метаданные отчета (количество, тип и ширина полей) определяются динамически, в момент создания проекта отчета эти обработчики должны быть определены, а приложение Delphi — запущено.
В следующем примере программа создает отчет на основе данных из произвольного текстового файла:
Начните новый отчет, поместите на пустую форму панель со свойством Align = alBottom, а на нее — две кнопки (Файл и Отчет). Для кнопки Отчет установите свойство Enabled = False. На форму выше панели поместите компонент ТМето с такими свойствами: Align = alClient, ScrollBars = ssBoth (рис. 8.35).
Поместите на форму компонент TOpenDialog, его свойство Filter сформируйте следующим образом:
PAS-файлыI *.pas I Текстовые файлы I *.txt 1 Файлы HTML I *.htm
Напишите такой обработчик щелчка на кнопке Файл:
procedure TForml.ButtonlClick(Sender: TObject);
// Загрузка файла
begin
if OpenDialogl.Execute then
begin
Memo.Lines.LoadFromFile(OpenDialogl.FileName);
Button2.Enabled := True
end
end;
OpienOtalo^OpienOtalo^期Pr*H R线碱誨緇却璇献期Pr*H R线碱誨緇却璇献
OpienOtalo^
OpienOtalo^
期Pr*H R线碱誨緇却璇献
期Pr*H R线碱誨緇却璇献
.Зтат;<тий^;^^^^Ыа'йа осйбее ;лйэ6огЪ 丁
6wr
Рис. 8.35. Вид формы на этапе конструирования
Разместите на форме компоненты RvProject и RvCustomConnection. Для компонента RvCustomConnectionl поместите в свойство Name значение Connection.
Для компонента Connection напишите такие обработчики событий ОпОреп, OnGetCols и OnGetRow:
procedure TForml.ConnectionOpen(Connection: TRvCustomConnection); // Определяет количество строк отчета и сбрасньает счетчик строк begin
Connection.DataRows := Memo.Lines.Count;
k := 0
end;
procedure TForml.ConnectionGetCols(Connection: TRvCustomConnection); // Определяет единственное текстовое поле шириной 80 стволов begin
Connection.WriteField( 'StrField' , dtstring, 80, ' StirFielci* , ' 1 );
end;
procedure TForml.ConnectionGetRow(Connect ion: TRvCustomConnection); // Передает в отчет очередную строку begin
if Memo.Lines.Count >= k then
Connection.WriteStrData(,', Memo.Lines[k]); inc(k) end;
Определите глобальную для обработчиков переменную к типа Integer. В обработчике Соппес t i onOpеп указывается количество строк отчета, которое
равно количеству строк файла, загруженного в многострочное поле Memol. С помощью метода WriteField в обработчике ConnectionGetCols определяется единственное поле отчета. При обращении к методу первым параметром передается имя поля (Name), вторым — тип поля, третьим — его длина, четвертым —полное лмя (FullName) и последним — описание (Description). Обработчик Connect ionGetRow передает в отчет очередную строку файла. При обращении к методу WriteStrData первым параметром указывается форматирующая строка, а вторым — собственно текстовые данные.
Сохраните проект на диске, запустите его и вызовите утилиту Rave Designer.
Начните новый проект отчета и создехйтс в нем объект Direct Data View, связав его с компонентом Connection. Раскройте узлы Direct View Dictionary и DataViewl и убедитесь, что создано поле DataViewlStrField. Если к моменту создания объекта Direct Data View приложение Delphi не будет запущено, Rave Designer не сможет определить количество н тип полей и создаст единственное абстрактное поле DataViewlDataFieId. Если все сделано верно и определено строковое поле, закройте приложение Delphi и продолжите формирование отчета.
С помощью команды Tools > Simple Table вызовите эксперт создания отчета по данным из единственной таблицы и с его помощью оформите заголовок отчета, заголовки полей и отображаемые данные. Сохраните отчет на диске и укажите ссылку на него в свойстве ProjectFile компонента RvProjectl.
ПРИМЕЧАНИЕ
Вот типичный пример проблемы связи приложения с файлом проекта: при обращении программы к OpenDialogl может произойти смена текущего каталога! Решение проблемы см. в подразделе ^Привязка проекта отчета к приложению». См. также обработчик ОпСгеа匸е главной формы примера (файл Chap_08\CustomConnect\Main.pas).
Для кнопки Отчет напишите такой обработчик:
procedure TForml.btRunClick(Sender: TObject);
// Создает отчет
begin
RvProjectl.Execute
end;
Защита данных
Два объекта данных — Data Lookup Security Control и Simple Security Control — позволяют защитить проект в целом или какой-то его отчет от несанкционированного доступа. Различие в компонентах состоит в том, что первый считывает список имен пользователей и их паролей из таблицы БД, а второй имеет собственный список. Наличие этих объектов в проекте отчета лишь дает возможность проверить право пользователя на получение доступа к данным, однако собственно механизм защиты реализуется программно в приложении Delphi.
Компонент TRvProject имеет сложное свойство ProjMan (от Project Manager — менеджер проекта), в котором определено свойство Securitycontrol как ссылка на один из определенных в проекте компонентов защиты — для защиты проекта
в целом, а также свойство ActiveProj ect. Securitycontrol — для защиты на уровне отчета. Собственно контроль пользователя реализуется следующим методом любого из этих свойств:
function IsValidUser(UserName, Password): Boolean
Перед проверкой компонент TRvProject должен быть открыт. Вот пример реализации контроля на уровне проекта в целом:
procedure TForml.btRunClick(Sender: TObject);
begin
RvProjectl.Open;
if RvProjectl.ProjMan.Securitycontrol.IsValidUser
(edUserName.Text, edPassword.Text) then
RvProjectl.Execute
else
ShowNessage(1В доступе отказано *);
RvProjectl.Close
end;
Для использования объекта Data Lookup Security Control его нужно связать с объектом типа Direct Data View и указать в свойстве UserField поле НД с именами пользователей, а в свойстве PasswordField — поле с паролями. Для объекта Simple Security Control следует заполнить его свойство UserList строками вида имя_пользователя = пароль .
Например:
Userl = Password!
Guest - Delphi
Типы отчетов
С помощью технологии Rave Reports можно создавать отчеты разных типов — с получением данных нз единственного набора данных, из наборов данных, связанных отаошением главный—детальный, с группировкой данных и т. д. Эти способы создания отчетов рассматриваются в этом разделе.
Отчет с единственной таблицей или запросом
Отчет с единственной таблицей (запросом) подробно описан в разделе «Пример создания отчета», где рассматривается общая технология создания подобных отчетов и свойства основных компонентов визуализации — областей и полос.
В общем виде процедура создания отчетов с одним источником данных выглядит следующим образом:
Создайте приложение Delphi, содержащее нужный НД (таблицу или запрос), компонент TRvProject и компонент TRvDataSetCormection. Вместо последнего можно использовать компонент TRvTableConnection или TRvQueryConnection в зависимости от типа НД. Во всех случаях компонент TRvXXXXConnect ion нужно связать с НД с помощью свойства DataSet, Table или Query.
ПРИМЕЧАНИЕ
Выбор нужного связного компонента зависит от используемой технологии доступа к данным. В технологиях dbExpress^NET, dbGO.NET, 1BX.NET для связи с таблицами и запросами может использоваться только компонент TRvDataSetConnection, а компоненты TRvTableConnection и TRvQueryConnection работают лишь в технологии BDE.NET.
Вызовите утилиту Rave Reports Designer, начните новый отчет (или проект отчета) и создайте в нем объект данных Direct Data View, связав его с компонентом TRvXXXXConnec t i on.
Вызовите эксперт создания отчета (командой Tools ► Simple Table) и с его помощью завершите начальное формирование отчета.
Если вас не устраивает отчет, созданный экспертом, модифицируйте его — введите нумерацию страниц, включите графические компоненты, нaпpи^fep для вставки в страницы отчета эмблемы вашего предприятия, или создайте связанную с отчетом глобальную страницу и т. п.
Сохраните отчет в файле и вернитесь в среду Delphi,
Установите в свойство ProjectFile компонента TRvProject ссылку на файл проекта. Для вызова окна просмотра объекта и/или для печати отчета предусмотрите в программе соответствующий интерфейсный элемент (кнопку или команду меню). В обработчике связанного с ним действия укажите оператор Proj ectName. Execute, если отчет единственный (умалчиваемый), или оператор Proj ectName. ExecutePerort ('ReportName'), если отчет не единственный в проекте и не умалчиваемый (Proj ectName — имя компонента TRvProject, ReportName — имя проекта).
В результате работы эксперта будет создан отчет, содержащий единственную стра* ницу MainPage, в которой имеется область просмотра данных Dat aVi ewlRegion с тремя полосами: DataViewlTitleBand* DataViewlBand и DataViewlData- Band.
Две первые полосы являются полосами заголовка отчета м заголовков полей. Они различаются тем, что первая печатается только в начале отчета, а вторая — на каждой странице. Поэтому в редакторе важнейшего свойства полей Bandstyle, определяющего положение полосы и ее наличие на странице при печати отчета, для первой установлены флажки Body Header и First а для второй — еще и флажок New Page. Если этот флажок сбросить, полоса напечатается только на первой странице. На любом из этих полей можно размещать компоненты вкладки Standard палитры компонентов Rave Designer.
Полоса данных Dat aVi ewl Da t aBand повторяется столько раз, сколько записей содержит соответствующий НД. Если после полосы данных расположить еще одну текстовую полосу (например, для нумерации страниц), она будет напечатана только в конце отчета. Чтобы вставить внизу или вверху каждой печатаемой странвды элементы оформления, нужно располагать эти элементы вне области просмотра данных. При этом, возможно^ понадобится соответствующим образом уменьшить вертикальный размер области.
Если вы не хотите пользоваться услугами эксперта создания простого отчета, последовательность формирования отчета должна быть такой:
Создайте в отчете связанный с данными объект отображения Direct Data View (если отчет связан с НД из приложения Delphi) или Driver Data View (отчет получает данные без помощи приложения Delphi).
На пустую страницу поместите надписи, графические изображения и другие элементы оформления с вкладок Drawing, Ваг &xje и Standard окна Rave Reports Designer, которые должны печататься на каждой странице.
На страницу поместите компонент Region (вкладка Report). Его размеры и положение на странице должны быть такими, чтобы не закрывать оформительские элементы вверху, внизу или по бокам страницы.
Поместите на страницу полосы Band (вкладка Report) для заголовка отчета и названий полей. Каждая помещаемая в область заголовка полоса занимает весь ее горизонтальный размер. Для полосы заголовка отчета в редакторе свойства Bandstyle должны быть установлены флажки Body Header и First, для полосы названий полей — флажки Body Header, First и New Page.
За полосами заголовка на страницу поместите полосу DataBand (вкладка Report). Своим свойством DataView она связывается с объектом отображения данных.
На полосе DataBand расположите компоненты для отображения данных из отдельных полей НД. Каждый компонент через свойство DataView свяжите с объектом отображения данных, а в его свойстве DataField укажите отображаемое компонентом поле данных или выражение с участием полей и системных переменных.
Отчет главный—детальный
Отчет главный—детальный воспроизводит данные из одной записи главной таблицы и все записи связанной с ней дочерней таблицы. Например, таким отчетом будет накладная на отпуск книг с указанием реквизитов покупателя и перечня проданных ему книг.
Для подготовки отчетов главный—детальный в Rave Reports Designer предусмотрен эксперт, который вызывается командой Tools ► Master/Detail Report Перед обращением к эксперту выполните следующие действия:
В приложении Delphi создайте два НД — главный и детальный. Между ними можно не устанавливать соответствующую реляционную связь, так как эта связь будет создана в проекте отчета.
Поместите в приложение два связных компонента TRvDataSetConnection, связав их с наборами данных. Как уже говорилось, если в приложении используется технология BDE.NET, допустимо применение компонентов TRvTable- Connection и TRvQueryConnect ion. Но если детальный НД создан на базе параметрического запроса, то и в этом случае для связи с ним требуется компонент TRvDataSetConnection, который, таким образом, является универсальным связным компонентом.
Создайте в проекте отчета два объекта данных типа Direct Data View, которые используют соответстнующие связные компоненты, и обратитесь к услугам эксперта создания отчета главный—детальный.
Пример отчета главный—детальный показан на рис. 8.36.
Поэнаватепьная миига01.03 2000
Назм»т» /Автор /ИздатепьствоКол-во
Internet Советы ёмвалага ч1йни*э /З/н /Лаббртпзрия базомх знаний Пел «се руководство no MS Wndtw» 98 Линенов /Лаборлорн* 6азо|м> энвиий Учимся “бьгтъ н« коыльют«р* Сзиоучитель длл детей м родитупЗ /Фролов /Лйор А^миннстрмр&камие с«ти MS Windows NT 4 0 Дли самастсипмьнйй ппдгсповх / /Русек Электромагнвтиэы Основные законы /Иродов /ЛаВрригория 6аэ@・нк эианий Основа патдкиини Уи・6нн* длл мадицински* ВУЗ0s /Зайчик /ЭЛБИ
Книги, полученные по обмену
ПартнерДата
ДЕСС-Паблишерэ01 03 2000
Назеани» ZArrop /ИзддтельспюКол-во
НоееАшй?7|моу»415Ср»5отьГ*Тго1|пнопр^35
ПрограммьфМаии* на языка Овма для имошьмикм и студ*мтм /Бобровски ХДксS6
ЕксМ лрм^ичссш* руководств。/Попов 仰《4в
ПартнерДата
Рис. 8.36. Вид отчета главный—детальный в окне предварительного просмотра
Для создания этого отчета начните новое VСL-приложение и на пустую форму поместите компонент TD&t&base, два компонента TQuery (категория BDE), два компонента TRvDataSetConnect ion (категория Rave) и кнопку (категория Standard). Настройте компонент Databasel на связь с БД IB_BIBL.GDB.
Свяжите компонент Queryl с локальным псевдонимом, созданным компонентом Databasel, назовите его NAKLS и разместите в его свойстве SQL такой запрос:
SELECT
NAKL工D, FNAME, NDATE
FROM
NAKLS, FIRMS
WHBR£
FIRMID = NFIRM AND NTYPE = 4
Компонент Query2 также свяжите с локальным псевдонимом, назовите его MOVES и разместите в нем такой запрос:
SELECT
NAKL工D, BNAME, BAUTHOR, BPUBLISH, MQUAN
FROM
MOVES, BOOKS
WHER£
BOOKID MBOOK
Как видите, детальный НД создан обычным (не параметрическим) запросом, '「аким образом, реляционная связь в приложении не создается — она будет создана в отчете.
Один компонент TRvDataSetConnect ion свяжите с НД NAKLS и назовите его NAKLSConn, второй — с НД MOVES, назовите его MOVESConn.
Вид формы к этому моменту показан на рис. 8.37.
Рис. 8.37. Форма с компонентами
Вызовите Rave Reports Designer, начните новый проект и создайте два объекта Direct Data View: первьп! для компонента NAKLSConn, второй для MOVESConn.
С помощью команды Tools ► Report Wizards ► Master/Detail Report вызовите эксперт создания отчета главный—детальный. Работа с экспертом происходит в последовательно раскрывающихся окнах. В первом окне эксперт предлагает выбрать главный НД (рис. 8.38).
Рис. 8.38. Выбор главного НД
Щелчком выберите набор DataViewl и щелкните на кнопке Next. Во втором окне предлагается выбрать детальный НД — выберите набор Dat6iView2. В третьем окне (рис. 8.39) можно отобрать поля главного НД для показа в отчете.
WNWNОсновы технологии Rave Reports 347
WN
WN
Select The Mvter Helda you wiM> to uv#
XWiew: DateViewlXWiew: DateViewl"奴」L"奴」L酬 MAKLID 团 FNAME 河 NOATE酬 MAKLID 团 FNAME 河 NOATE
XWiew: DateViewl
XWiew: DateViewl
"奴」L
"奴」L
酬 MAKLID 团 FNAME 河 NOATE
酬 MAKLID 团 FNAME 河 NOATE
F^SO [ 一而;J [J^?^〕
Рис. 8.39. Выбор полей главного НД
Щелкните на кнопке АПТ затем — на кнопке Next. В очередном окне эксперт попросит указать порядок отображения полей. Согласитесь с умалчиваемым. Два следующих окна позволяют указать поля и порядок их следования в детальном НД. Выберите все поля и умалчиваемый порядок. Наконец, в седьмом окне предлагается выбрать ключевые поля (рис. 8.40).
;;3«toctThe fMie Т。Um Аа Key*
Master Keys Selected; 1
Detail Keys Selected: 1
^W«M»^ "2謬“欠步"
L.j BNAME
口 BAUTHOR:
匸 BPUBUSH;
MQUAN
:^ЯИ □ FNAME □ ndate
Рис. 8.40. Установление реляционной связи
Установите флажки рядом с полями NAKLID обоих НД п щелкните на кнопке Next В следующем окне в строке Report Title введите текст Книги, полученные по обмену и установите ширину полей отчета в строках Left и Right равными 0,3 дюйма. В заключительном окне щелкните на кнопке Generate. Начальный вариант проекта отчета готов (рис. 8,41).
Теперь доработаем отчет — изменим названия полей, удалим ненужные.
В полосах Dat aViewlBand и DataViewlDataBand удалите компоненты Textl и DataTextl, предназначенные для отображения заголовка и значения поля NAKLID главного НД. В свойстве Text компонента T,xt2 вместо значения FNAME введите значение Партнер. Измените заголовок поля NDATE иа Дана.
348 Глава 8 • Отчеты348 Глава 8 • Отчеты泾二二二仁E二;二上二二.1…旧泾二二二仁E二;二上二二.1…旧限尸;;± ♦ D*aVi DidumyHf限尸;;± ♦ D*aVi DidumyHf[J:Mjfl*wl^[J:Mjfl*wl^|:VMi№n^fti>HWi'MwteMtf :NAWLFNAME|:VMi№n^fti>HWi'MwteMtf :NAWLFNAMEКйи^к Ptfctv^o^aana.Кйи^к Ptfctv^o^aana.&WJTHOP&WJTHOP:仆职乃行::m:仆职乃行::mталмояталмояЖившиЖившиI ▲.皤^^Wwri^^^g^.:,I ▲.皤^^Wwri^^^g^.:,(№^М๫Ш# .(№^М๫Ш# .№ATEJINDATE 1ВРУВиЗН卜№ATEJINDATE 1ВРУВиЗН卜芯占侬可0}.06.¥■*工礴碱筑同赢二…芯占侬可0}.06.¥■*工礴碱筑同赢二…咬.if咬.if
348 Глава 8 • Отчеты
348 Глава 8 • Отчеты
泾二二二仁E二;二上二二.1…旧
泾二二二仁E二;二上二二.1…旧
限尸;;± ♦ D*aVi Didumy
Hf
限尸;;± ♦ D*aVi Didumy
Hf
[J:Mjfl*wl^
[J:Mjfl*wl^
|:VMi№n^fti>HWi'MwteMtf :
NAWLFNAME
|:VMi№n^fti>HWi'MwteMtf :
NAWLFNAME
Кйи^к Ptfctv^o^aana.
Кйи^к Ptfctv^o^aana.
&WJTHOP
&WJTHOP
:仆职乃行::m
:仆职乃行::m
талмоя
талмоя
Живши
Живши
I ▲.皤^^Wwri^^^g^.:,
I ▲.皤^^Wwri^^^g^.:,
(№^М๫Ш# .
(№^М๫Ш# .
№ATE
JINDATE 1
ВРУВиЗН卜
№ATE
JINDATE 1
ВРУВиЗН卜
芯占侬可0}.06.¥■*工礴碱筑同赢二…
芯占侬可0}.06.¥■*工礴碱筑同赢二…
咬.if
咬.if
Книги, полученные по обмену
Рис. 8.41. Начальный вариант отчета
Полосы Dat aView2Band и DataVi 巳w2DataBand предназначены для отображения заголовков и значений полей детального НД. Удалите в них компоненты для вывода заголовков и значений полей NAKL工D, BAUTHQR и BPUBLISH. Заголовок поля BNAME (свойство Text компонента Text5) замените на Название /Автор /Издательство. В то же свойство компонента Text 8 поместите значение Кол-во. Компонент DataText5 предназначен для отображения поля ENAME. С помощью редактора его свойства DataField введите такое выражение:
BNAME + ' /' +BAUTHOR + ' /' +BPUBLISH
Нажав клавишу F9, выполните пробную генерацию отчета. При необходимости измените высоту шрифта в компонентах, визуализирующих данные.
Сохраните проект отчета на диске и закройте окно утилита Rave Reports Editor.
Поместите на форму компонент TRvProject (вкладка Rave). В его свойстве ProjectFile сошлитесь на файл проекта отчета. Напишите такой обработчик щелчка на кнопке:
procedure TForml.ButtonlClick(Sender: TObject);
begin
RvProjectl.Execute;
end;
* fhfvtl^n^i* ** а :出 Ёч* &ХЖ1501.收』► м::Р>э<; |* fhfvtl^n^i* ** а :出 Ёч* &ХЖ1501.收』► м::Р>э<; |of69 ■典 H 0 0 Zoomof69 ■典 H 0 0 Zoom限晒льствсх Arp&n码Hi:限晒льствсх Arp&n码Hi:60606060404£404£ЕрвымхииЕрвымхииКонвгопав КраеувмкоКонвгопав КраеувмкоСтвф»иеню "PT Комотвп”Ствф»иеню "PT Комотвп”Осчкмпмглва бес«лов 3”Ш8Осчкмпмглва бес«лов 3”Ш8
* fhfvtl^n^i* ** а :
出 Ёч* &ХЖ1
501.收』► м::Р>э<; |
* fhfvtl^n^i* ** а :
出 Ёч* &ХЖ1
501.收』► м::Р>э<; |
of69 ■典 H 0 0 Zoom
of69 ■典 H 0 0 Zoom
限晒льствсх Arp&n码Hi:
限晒льствсх Arp&n码Hi:
60
60
60
60
40
4£
40
4£
Ервымхии
Ервымхии
Конвгопав Краеувмко
Конвгопав Краеувмко
Ствф»иеню "PT Комотвп”
Ствф»иеню "PT Комотвп”
Осчкмпмглва бес«лов 3”Ш8
Осчкмпмглва бес«лов 3”Ш8
Группирующий отчет
Группирующими называют отчеты, в которых вся информация разделяется на группы данных, объединенных каким-то общим признаком (например, остаток непроданных книг, поставленных конкретным поставщиком, или список книг, упорядоченный по издательствам).
В Rave Reports Designer нет эксперта создания группирующего отчета, так что мы познакомимся с технологией создания отчета «вручную».
Рассмотрим такой пример. Пусть необходимо получить список всех книг с груп- nnpoBKoii но издательствам (рис. 8.42).
賓您淡守?綴微玄个图^您^^ 遂癒爾醪啰駿核i滋編認礎й
Названии
Лизинг для пр^^Ринимггеля Лр1г?н^ес»ое лосьЬне
Наззани^Наззани^Нзд;тЕьств。; Акаде 值 Мческнй 叩 biicC]
Наззани^
Наззани^
Пчцнос:ъ м и^1шл«ние ребенм Swazoc w м шррвкция
Мини ДТГ Panasonic и Samsung
Нмбьпял?нмйя "3,Е,р*ПН*
Сгчиолигнй арукгук” согн^есне схемы с комм(нт*рияии
История эгЭноыяки Учебник дпя Высшей щкопв
СоциолсиМ Учебник для студйиюв ЙУЗ&в
Г.сиюлогия и i&A“0E,a Учебное пособие для аысшвй зты
4208** Уиебхнк А” ВУЗо»
Терапия tu“zecKMM с»имыр^*»ниеы
Зтмапсигалогой Учебник для 8УЗо・
Ис»ушечив погустороичкм
Из тупика Зко“см“иескнА опыт мирм и путь Гсссми
Рис. 8.42. Пример группирующего отчета
В этом случае в приложении Delphi должен быть компонент TQuery со следующим текстом запроса:
SELECT
BName, BAu匸hor, BPublish, BYear, BOpt
FROM
Books
GROUP BY
BFubliah, BName, I3Aiithor, BYear, BOpt
Другой вариант запроса может быть таким:
SELECT
FROM
Bocks
ORDER BY
BPublish
j 6 В・тИ (М.Мет);У Band2 (G)j ^ DataSandl (Master)1 ♦DataBandl (Master) j ♦DataOandl (Master)i A Band3 (g)j 6 В・тИ (М.Мет);У Band2 (G)j ^ DataSandl (Master)1 ♦DataBandl (Master) j ♦DataOandl (Master)i A Band3 (g)匚®二]上 Print |.освШ1 *t □awh* Header (0) iз □2гоЦ»НовсЬг9): [□RowHeeder(R),□ M(D);DRomlFooter (0 i 飞 ,t ПОгоийrooter(5).:;. 胃口Bod*Footer® & :'' ■ ' :?:.r ■/ Prfat 0ССу|теГ1£В …、 电丽8□ Clew Paget?) 卜:; □ f%w Column (Q ;匚®二]上 Print |.освШ1 *t □awh* Header (0) iз □2гоЦ»НовсЬг9): [□RowHeeder(R),□ M(D);DRomlFooter (0 i 飞 ,t ПОгоийrooter(5).:;. 胃口Bod*Footer® & :'' ■ ' :?:.r ■/ Prfat 0ССу|теГ1£В …、 电丽8□ Clew Paget?) 卜:; □ f%w Column (Q ;
j 6 В・тИ (М.Мет)
;У Band2 (G)
j ^ DataSandl (Master)
1 ♦DataBandl (Master) j ♦DataOandl (Master)
i A Band3 (g)
j 6 В・тИ (М.Мет)
;У Band2 (G)
j ^ DataSandl (Master)
1 ♦DataBandl (Master) j ♦DataOandl (Master)
i A Band3 (g)
匚®二]
上 Print |.освШ1 *
t □awh* Header (0) i
з □2гоЦ»НовсЬг9): [□RowHeeder(R),
□ M(D)
;DRomlFooter (0 i 飞 ,t ПОгоийrooter(5).:;. 胃口Bod*Footer® & :
'' ■ ' :?:.r ■
/ Prfat 0ССу|теГ1£В …、 电丽8
□ Clew Paget?) 卜:; □ f%w Column (Q ;
匚®二]
上 Print |.освШ1 *
t □awh* Header (0) i
з □2гоЦ»НовсЬг9): [□RowHeeder(R),
□ M(D)
;DRomlFooter (0 i 飞 ,t ПОгоийrooter(5).:;. 胃口Bod*Footer® & :
'' ■ ' :?:.r ■
/ Prfat 0ССу|теГ1£В …、 电丽8
□ Clew Paget?) 卜:; □ f%w Column (Q ;
Разница между вариантами незначительна. В первом случае информация упорядочивается (сортируется) по составному ключу, во втором — по какому-то одному полю. Напомню, что в запросах нельзя называть индекс, по которому осуществляется доступ к данным. Если какая-то таблица имеет нужный индекс, он будет использоваться автоматически. Поэтому с точки зрения скорости доступа оба запроса приблизительно равноценны.
В обоих случаях группирующим является поле В Publish: изменение значения в нем воспринимается как свидетельство окончания очередной группы данных и начало следующей.
Для связи с НД типа TQuery можно использовать компонент TRvQueryConnect ion или TRvDatcLSetConnection.
В проекте отчета создается объект отображения данных типа Direct Data View, ссылающийся на связной компонент TRvXXXXConnection в приложении Delphi. Все дальнейшие действия осуществляются над компонентами Rave Reports Designer и напоминают разработку формы на этапе конструирования.
Основным компонентом отчета является компонент Region (вкладка Report па
литры компонентов Rave Reports Designer). Этот компонент определяет область отображения данных (страницу отчета). На него помещаются остальные компо
ненты. Для публикации данных используются компоненты Band и DataBand (вкладка Report). Полосы Band предназначены для размещения вспомогательной информации: заголовка отчета, названий полей, значений агрегатных функций и т. д. Полосы DataBand являются контейнерами для основных данных отчета.
Эти полосы при печати отчета повторяются столько раз, сколько записей содержит НД.
При размещении любой полосы на компоненте Region она автоматически растягивается по всей ширине компонента. Высота полосы может регулироваться программистом.
Основным свойством полос Band является свойство Bandstyle. В его редакторе (рис. 8.43) имеется две группы флажков: Print Location и Print Occurrence.
Первая определяет положение полосы при печати, вторая — появление полосы в ходе печати. Назначение флажков фуппы Print Location (содержание полосы, если флажок установлен):
Рис. 8.43. Редактор свойства BandStyleРис. 8.43. Редактор свойства BandStyle• Group Header — заголовок группы;• Group Header — заголовок группы;Body Header — заголовок страницы;
Рис. 8.43. Редактор свойства BandStyle
Рис. 8.43. Редактор свойства BandStyle
• Group Header — заголовок группы;
• Group Header — заголовок группы;
Row Header — заголовок данных;
Detail —данные;
Row Footer — подвал данных;
Group Footer — подвал группы;
Body Footer — подвал страницы.
Назначение флажков группы Print Occurrence (момент печати полосы» если флажок установлен):
First — печатается первой;
New Page — печатается в каждой новой странице;
New Column — печатается в каждой новой колонке.
Замечу, что полоса не будет печататься, если не установлен хотя бы один флажок этой группы.
Спецификой группирующего отчета является то, что полосы с данными, относящимися к какой-то группе, должны указывать на объект отображения данных в своем свойстве GroupView и на поле группировки — в свойстве GroupKey. Поле группировки — это поле, изменение значения которого означает конец предыдущей группы и начало следующей. Обычио такое поле указывается первым в секции ORDER BY или GROUP BY SQL-запроса.
На пустой лист отчета поместите область отображения данных Region и установите нужные размеры этой области.
На область отображения данных поместите полосу Bandl для заголовка отчета. Установите флажок First в ее свойстве Bandstyle.
Ниже расположите три полосы для отображения заголовка данных(Band2), собственно сгруппированных данных (DataBandl) и итога отображения (Band3 ). Каждая iu полос должна иметь ссылку на объект отображения данных в свойстве GroupView и группирующее поле (BPublish) в свойстве GroupKey. В редакторе свойства Bandstyle полосы Band2 установите флажки Group Header, First и New Page, последней полосы — флажок Group Footer. В редакторе свойства Bandstyle средней полосы флажки в группе Print Location можно не устанавливать. Заголовочная и итоговая полосы должны ссылаться на полосу с группой данных в своем свойстве ScrollerBand. Чтобы это стало возможным, средняя полоса с данными должна быть компонентом DataBand. На рис. 8.44 показаны полосы группирующего отчета.
Использование агрегатных функций
Если вы внимательно посмотрите на рис. 8.44, то увидите в конце каждой группы итоговую строку с количеством наименований книг в группе. Такого рода данные получаются как результат обработки группы записей и формируются с помощью так называемых агрегатных функций. В Rave Reports предусмотрены стандартные для языка SQL92 агрегатные функции, перечисленные в табл. 8.2.
352 Глава 8 • Отчеты
жгжгИтагп наИтагп наРис. 8.44. Полосы группирующего отчетаРис. 8.44. Полосы группирующего отчетаTbau^hoa I I TMa,iTbau^hoa I I TMa,i沙学「沙学「Книги по издательствамКниги по издательствамHueamifjARe**;8vidi:'.:.::'. ■HueamifjARe**;8vidi:'.:.::'. ■•可 方 K,Piciee1•':哀② RepoftLtxiryI @БШР«цвС#*Ь0“ 厶♦卩&V^wDidKnaiy•可 方 K,Piciee1•':哀② RepoftLtxiryI @БШР«цвС#*Ь0“ 厶♦卩&V^wDidKnaiy
жг
жг
Итагп на
Итагп на
Рис. 8.44. Полосы группирующего отчета
Рис. 8.44. Полосы группирующего отчета
Tbau^hoa I I TMa,i
Tbau^hoa I I TMa,i
沙学「
沙学「
Книги по издательствам
Книги по издательствам
Hueamif
jARe**;8vidi:'.:.::'. ■
Hueamif
jARe**;8vidi:'.:.::'. ■
•可 方 K,Piciee1
•':哀② RepoftLtxiry
I @БШР«цвС#*Ь0
“ 厶♦卩&V^wDidKnaiy
•可 方 K,Piciee1
•':哀② RepoftLtxiry
I @БШР«цвС#*Ь0
“ 厶♦卩&V^wDidKnaiy
Таблица 8.2. Агрегатные функции
Название функции
Назначение
AVERAGE(AVG)
COUNT
Вычисление среднего значения из одного поля пэуппы записей
Подсчет количества значении поля
SUM
Суммирование значений поля для группы записей
MIN
Определение мин1шальпого значения поля
MAX
Определение макенма^чьпого значения поля
Для получения в отчете результатов работы одной из этих функций предусмотрены два вычи с лительных компонента вкладки Report: CalcText и CalcTotal. Первый вычисляет и показывает значение агрегатной функции, второй лишь вычисляет значение и передает его другому вычислительному компоненту для его дальнейшего преобразования.
Оба компонента имеют свойства Dat a View, DataField и CalcType. Два первых определяют поле НД, значения которого будут использоваться при вычислении, третье определяет агрегатную функцию. Функция COUNT может быть применена к полю любого типа, остальные функции определены только для вещественных (целочисленных) полей.
Чтобы определить момент срабатывания вычислительного компонента, нужно каким-то образом пометить полосу отчета, в которой отображаются значения группы. Для этого используется специальный невидимый компонент CalcController (контроллер), который помещается на печатаемую группу. Ссылку на него следует указать в свойстве Controller вычислительного компонента. Другой вариант: сослаться в этом свойстве на саму полосу с данными. Печать полосы с контроллером (или полосы, указанной в свойстве controller) вызывает срабатывание вычислительного компонента, то есть реализацию очередного цикла вычислений. В результате после завершения печати групповых данных вычислительный компонент накопит значение нужной агрегатной функции.
Поясним сказанное примером. Для оформления итоговой полосы отчета, показанного на рис. 8.44, на нее был помещен компонент CalcText. В его свойстве DataView указана ссылка на нужный объект отображения данных (DataViewl). Он подсчитывает общее количество значений поля BName, поэтому его свойство CalcType имеет значение ctCount. В свойстве Controller компонента указана ссылка на саму полосу с данными DataBandl.
Экспорт отчета в файл
Экспорт отчета в файл того или иного формата необходим, когда созданный в программе отчет требуется переслать партнеру. Например, в работе оптового поставщика книг периодически создается и рассылается всем покупателям прайс-лист имеющихся на складе книг. В окне предварительного просмотра отчета по умолчанию можно сохранить отчет только в специфичном для технологии формате NDR или в виде последовательности поступающих на принтер команд в формате PRN. Ясно, что ни тот, ни другой формат нельзя считать приемлемым. (В самом деле, откуда у покупателя из Владивостока или Израиля возьмутся соответствующие средства просмотра?)
В технологии Rave Reports имеется возможность экспортировать отчет в файлы наиболее распространенных форматов — HTML, PDF (для просмотра с помощью бесплатно распространяемой утилиты Acrobat Reader корпорации Adobe Systems), RTF и TXT. Для этого в категории Rave предусмотрены компоненты TRvRenderPDF, TRvRenderHTML и т. д., которые нужно просто поместить на форму приложения. После этого в окне предварительного просмотра достаточно щелкнуть на кнопке сохранения файла и выбрать нужный формат в раскрывающемся списке Тип файла.
Практика показывает» что приемлемым форматом для русскоязычных отчетов является формат RTF, который позволяет получать прекрасные по качеству документы (рис. 8.45). Отчет, сохраненный в этом формате, можно просмотреть и напечатать с помощью текстового процессора MS Word или стандартной утилиты Windows Word Pad (в этом случае качество гораздо хуже, а некоторые длинные файлы эта утилита не сможет отобразить).
12 Зак. 449
攣锌解品产理期誉W尊鬱然京¥^^|!? 结**•«芻沙审 B^'l'V^W^sM^#”!•规辍眸哪 3»?审終ё》如再 覆碱X皆海^^?f礴簧海髡喻凌讣智jf^^s<{^^!**^if*«^: 事区我:1,*>>1;%*:第一 *69.鼻g購 e沁而谜话直:' "'「,一:.::—_二二二]m
(Издательство: Питер
…戸:礎^碎
Название
АвторГ одЦена
Пснкнатрия a sonpcca* н обетах
ВуАС
19»20
Неатлй'ги1й и%анцнка в вопросам и дтмтав
Кен*
20
Инвестиционный ыенед*и»нг Краткий гург
Бочарз»
25
М(*неджм»нт КраткнА курс
Большаки*
25
Интернет краткий гуре Пособие для усксдннир сБучеммн
Соламанчук
30
Денъп) к фикансовые ннст*пу«ы.Краткий курс
ЕалаСвнов
30
MS '?ffiCB 2000 Краткий курс
Леонтьев
30
MS Wniti 2000 «рзгкнА »'урс Русская зерен*
Рыиксз
30
MS Excel 2С00 краткпА курс
Рычков
30
口ипннг для иачмнающ»!
Жваколк>«
30
Деньги н финансы Тее >< задачи
Бклавамрв
30
Фмя^нсы КрагкнА курс
Бклабаьвеи
30
Кусьтура предпр<>мимат&лсС1вв Учетное пособие дпв ВУЗов
ТбМнПОВ
30
МанрВА.ономнка Пособив для подготовки к экзамену
8ечк«нйв»1
30
MS Window 96 ^рапий гуре
Аадл 喻
30
Кл*ничесм|е Секции п。кеоропоги” н нейрокиру^шн
Никифоров
36
Сн@илнс Руководство для ерамбй
Родионов
药
Рис. 8.45. Отчет в окне MS Word
Текстовьп! формат TXT (рис. 8.46) менее красив, но зато не искажает текст: если вы внимательно посмотрите на рис* 8.45, то заметите, что п названиях книг опущены некоторые слова.
警聲羅笈箭,季》ЬХУeЖ?С
w^^^mp^we^iwsw^
金вйл 皿吟 odpt*<T &HAi Сп»вк4.
книги по издательствам
издательство:1 Временно неизвестно
название
АВТОрГОД
цена
Практикум по курсу менеджмент
Виханский2000
35
теория гос-ва и права
Енгибарян2000
35
мир.экономика
халевинская2000
45
эконом.география России
гладкий2000
75
валютные операции комм.банков
сапожников2000
34
теория 「с-аа нсраеа в вопрос.
и ответакМасько2000
34
Философия.основные проблемы ч
2Кириллов2000
44
коцепции совр.естествознания
Наидыш2000
49
прокурор.надзор в рф
чувилева2000
49
отечественное зак-ство xi-xlx
вв.чистяков2000
49
Семейное право
Антокольская 2000
49
угол.право России.Особ.масть
Эдравомыслов2000
73
взыскание долгов и криминал
Скобликов2000
19
доверительное управление имуществомЗахарьин2000
24v
Рис. 8.46. Отчет в формате TXT
ВНИМАНИЕ
Форматы PDF н HTML искажают кириллицу.
Создание приложений для работы с Интернетом
Без риска ошибиться можно предположить, что вы, уважаемый читатель, в той или иной степени знакомы с Интернетом. В Delphi есть средства, существенно упрощающие публикацию в глобальной Сети различных данных, в том числе результатов запросов к базам данных. Описываемые в этой части технологии Delphi могут использоваться не только в глобальной, но и в локальной сети предприятия (локальная сеть, в которой передача информации организована в соответствии с технологиями Интернета, называется интранетом).
Актуальность публикации именно баз данных связана с бурным ростом количества так называемых сетевых магазинов 一 сайтов, предлагающих те или иные товары л услуги. Содержимое таких сайтов должно создаваться на основе информации из реальной БД предприятия (магазина).
ПРИМЕЧАНИЕ
Исходные тексты описываемых в книге примеров размещены на сайте www.piter.com. Для использования текстов примеров, рассматриваемых в этой части книги, каждый из них следует сохранить в отдельном виртуальном каталоге, входящем в папку c:\inetpub\wwwroot (виртуальным называется каталог, доступный серверу MS IIS). После размещения файла примера в каталоге следует с помощью команды Пуск > Панель управления ► Администрирование ► Internet Information Services операционной системы Windows запустить утилиту управления MS 1IS, раскрыть узел Локальные веб-узлы, разыскать и раскрыть узел с примером, щелкнуть на раскрытом узле правой кнопкой мыши, выбрать в контекстном меню команду Свойства и на вкладке Виртуальный каталог открывшегося окна разрешить чтение, запись и запуск сценариев, как показано на следующем рисунке.
В иртаальный каталог匕皿а^^Жйт^—予
Источник содержимого при подключении к ресурсу:
® каталог данного компьютера
О общая папка другого компьютера•:
О по£гоянньй аарес URL:
Локальный nm: ^Ainet^\wv^^■[淡熱浦亀叫二3 :
j □ Досту! к тексту сден^ия回 Запись в журнал;
Q УмениеИмаехсацид кдтдлогд
口乖怨忍 каталогов Параметры прмлсжения
Има приложения:Има приложения:^CheckBoxLi$l^CheckBoxLi$lИсхооная попка:Исхооная попка:<Be6..ACheckBoxLisl<Be6..ACheckBoxLislРазрешен запуск:Разрешен запуск:I Только сценарииI Только сценарии^予;7》СК0% Л..^予;7》СК0% Л..3砧吗d3砧吗dRxG相Г f父2㈠#看脸就"':.•:.RxG相Г f父2㈠#看脸就"':.•:.^И£Х]>КТЬ^И£Х]>КТЬ
Има приложения:
Има приложения:
^CheckBoxLi$l
^CheckBoxLi$l
Исхооная попка:
Исхооная попка:
<Be6..ACheckBoxLisl
<Be6..ACheckBoxLisl
Разрешен запуск:
Разрешен запуск:
I Только сценарии
I Только сценарии
^予;7》СК0% Л..
^予;7》СК0% Л..
3砧吗d
3砧吗d
RxG相Г f父2㈠#看脸就"':.•:.
RxG相Г f父2㈠#看脸就"':.•:.
^И£Х]>КТЬ
^И£Х]>КТЬ
◎&._」〔…⑴^更二「[пмШ [.арум〕
Установка прав доступа для виртуального каталога
Программирование
для Интернета
и технология ASP.NET :督一G
Технология ASP.NET (от англ. Active Server Pages — активные серверные страницы) является базовой технологией для работы с Интернетом на платформе .NET. В этой и последующих главах освещаются различные аспекты этой технологии.
Основы сетевого программирования
В этом разделе описываются базовые технологии, лежащие в основе Интернета. Если эти технологии вам известны, можете спокойно пропустить этот раздел.
Средства
Для работы с Интернетом ваш компьютер должен, прежде всего, иметь доступ к глобальной Сети. Кроме того, он должен содержать программные средства просмотра узлов Интернета, а если вы планируете не только потреблять информацию из Сети, но и поставлять в нее свою, на вашем компьютере должен быть установлен веб-сервер.
Важные средства — языки HTML и XML — описаны в приложении В,
Веб-сервер
Чтобы компьютер, владеющий данными, смог опубликовать их в сети (Интернет или интранет), он, во-первых, должен иметь постоянный доступ к этой сети. Поскольку обычная для пользователей связь с Интернетом через модем не обеспечивает нужной устойчивости и скорости обработки запросов, для этих целей создается выделенная линия (радио, оптоволоконная, спутниковая, телефонная) или используются специальные средства поставщика услуг Интернета. Во-вторых, на компьютере должен постоянно функционировать веб-сервер — программа, обслуживающая запросы клиентов.
Для серьезной корпоративной работы в сети обычно устанавливаются мощные серверы Microsoft Internet Information Services (IIS), Netscape FastTrack Server или Apache.
ПРИМЕЧАНИЕ
Так как описываемая далее базовая технолотя ASP.NET рассчитана на работу с I1S или с бесплатно распространяемым сервером Cassini Personal Web Server, один из этих серверов должен быть установлен на вашем компьютере или в доступном сетевом окружении. Мощный 11 S-сервер поставляется со всеми версиями Windows, начиная с Windows 2000. Значительно более простой сервер Cassini доступен длм бесплатной загрузки с узла Microsoft http://www.asp.net/Project5/Cassini/Download (объем — 217 Кбайт). В папке Samples/ Cassini каталога установки Delphi есть пример использования этого сервера.
Назначение веб-сервера заключается в том, чтобы переадресовать запрос клиентского браузера нужному веб-приложению, то есть специальной программе, которая в ответ на запрос формирует текстовую страницу в формате HTML (или XML) и передает ее серверу, а тот посылает эту страницу клиенту. Веб-приложения часто называются модулями расширения сервера. Таким образом, для публикации данных нужно с помощью Delphi разработать необходимые веб-приложения и разместить их на машине веб-сервера в специально для этих целей предусмотренной папке wwwroot.
Браузер
HTML-браузер — это программа, преобразующая описание полученной от сервера страницы в ее видимое изображение. Фактически в мире доминирует браузер Internet Explorer (IE) корпорации Microsoft, входящий в поставку 32-разрядных версий Windows. Однако многие пользователи других платформ предпочитают Netscape Communicator (NC), первые версии которого назывались Netscape Navigator. Наконец, почти 1>5 миллиона компьютеров оснащены «третьим браузером для стран третьего мира» — речь идет о браузере Opera производства норвежской компании Opera Software.
Каждый браузер в общем случае интерпретирует описание страниц по-своему. Программируя для Интернета, вы постоянно должны помнить об этом.
Некоторые детали протокола HTTP
Протокол HTTP (HyperText Transfer Protocol — протокол передачи гипертекста) используется в Интернете для передачи HTML-страниц. Поскольку далее при рассмотрении компонентов Delphi используются термины этого протокола, в данном разделе кратко поясняются некоторые его технические подробности.
По своей сущности HTTP отаосится к протоколам пользовательского уровня, так как определяет набор правил для взаимодействия непосредственно с программой пользователя, игнорируя такие важные уровни, как транспортный (на этом уровне реализуются контроль и исправление всех ошибок передачи), сетевой (на нем данные разделяются на блоки и снабжаются маршрутами доставки) и самый нижний — физический, на котором данные собственно и передаются от клиента к серверу и обратно. Эти уровни реализуются протоколом TCP/IP.
Для взаимодействия с пользователем протокол предлагает 4 метода:
HEAD — с помощью этого метода клиент получает от сервера информацггю о передаваемых данных: их заголовок (часть между тегами HEAD) и дату последнего обновления. Метод HEAD обычно используется клиентом для проверки связей шпертекста на действительность и доступность.
GET — этим методом клиент получает от сервера всю гипертекстовую страницу, включая ее заголовок, или передает серверу параметры заполненной диалоговой формы через переменные окружения операционной системы.
POST — с помощью этого метода клиент передает серверу параметры заполненной диалоговой формы через стандартный поток ввода-вьсвода (поток данных).
PUT — предписывает серверу заменить старое значение страницы новым. Таким методом обновляются удаленные сайты (и «взламываются» чужие!).
В подавляющем большинстве случаев клиент использует методы HEAD и GET, поэтому в запросе не присутствует дополнительная информация. Метод PUT обычно требует идентификации клиента, чтобы выяснить доступность метода. В этом случае в запросе указывается дополнительная информация, позволяющая отсеять нелегальных пользователей.
Протокол HTTP подразумевает обмен данными между браузером и веб-сервером с помощью пакетов сообщений. Различают два типа пакетов: пакет запроса и пакет ответа* Любой пакет состоит из трех частей:
строки запроса (пакет запроса) или строки состояния (пакет ответа);
заголовка НТТР-пакета;
тела пакета.
Строка запроса состоит из указания метода передачи данных, маршрута доступа к запрашиваемому ресурсу и номера протокола НТРР. Например:
GET /web/index.htm HTTP/1.1
В этом примере используется метод GET, означающий, что клиент хочет что-то получить от сервера. Что именно — указано во второй части строки (/web/ index. htm). Наконец, в третьей части строки запроса указывается номер версии протокола (НТТР/1.1).
Строка состояния также состоит из трех частей: версии протокола HTTP, кода состояния и текстовой строки, описывающей код состояния. Например:
HTTP/1.1 200 ОК
Код состояния 200, описанный как ОК, означает успех выполнения Другие коды состояния классифицированы по первой цифре кода следующим образом:
1хх — информация:
2хх — успех;
Зхх — переадресация;
4хх — клиентская ошибка;
5хх — ошибка сервера.
Заголовок HTTP-пакета содержит информацию о запросе или ответе. Строка заголовка состоит из пар «имя—значением. Существует четыре формы заголовков: общий (general), запрос (request), ответ (response) и элемент (entity). Общие заголовки содержат информацию о сервере или клиенте. Заголовки ответа содержат информацию о сервере, которая может быть полезна клиенту. Элемент содержит информацию о передаваемых данных. Более подробная информация о разных типах заголовков содержится в документе RFC2068, доступном по адресу www.w3c.org.
Наконец, тело пакета в случае запроса обычно отсутствует, а в случае ответа содержит HTML-текст.
Общая схема обработки запроса клиента
Структура URL
Пользователь оформляет свой запрос в виде URL-адреса. URL (Uniform Resource Locator — унифицированный указатель ресурса) — это цепочка символов, однозначно определяющая положение некоторого ресурса в сети и запрос клиента к этому ресурсу. В качестве примера рассмотрим следующий URL:
http: //www.TSite.com/art/gallery .dll/mainmals?anirnal=dog&color=black
В этом примере URL состоит из таких частей:
http — протокол передачи данных; здесь допускается указание протоколов https (secure HTTP — протокол HTTP повышенной секретности), ftp (File Transfer Protocol — протокол передачи файлов) и др.;
www,TSite ・ com — сетевое имя машины, на которой расположен веб-сервер;
artZgallery.dll — имя (возможно, с маршрутом доступа) веб-приложения, которому адресуется запрос клиента;
mammals — условное имя запроса (одно и то же веб-приложение может обрабатывать несколько запросов клиента);
animal=dog&color=black — параметры запроса (соседние параметры разделяются символом &).
Функционирование браузера при передаче запроса
Получив URL-адрес, браузер производит его предварительную обработку, дополняя информацией о методе протокола, параметрах самого браузера, операционном окружении и т. п. Например, рассмотренный выше URL-адрес может быть в конечном счете преобразован браузером в следующие строки:
GET /art/gallery.dll/animals?animal=dog&color=black HTTP/工.0 Connection: Keep-Alive User-Agent: Mozilla/9.0b4Gold (WinNT; I) Host: www.TSite.com:1024
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
В первой строке помимо информации о запросе указываются также метод (GET) и протокол (НТТР/1.0), который собирается использовать браузер для связи с ресурсом.
Вторая строка указывает, что соединение с ресурсом будет активным до тех пор, пока ресурс не обработает клиентский запрос.
В третьей строке приводится информация о браузере клиента и операционном окружении.
В четвертой строке указываются сетевое имя машины, на которой располагается нужный ресурс, и ее порт связи.
В пятой строке перечисляются компоненты мультимедиа, которые веб-приложение может поместить в свой ответ.
Работа веб-сервера при обработке запроса
Получив запрос клиентского браузера, веб-сервер отыскивает нужное веб-приложение, активизирует его и передает ему параметры запроса. Сервер ожидает окончания работы веб-приложения и передает сформированный им ответ браузеру.
Введение в технологию ASP.NET
В технологии ASP.NET сервер работает особым образом. По расширению aspx он выясняет, что клиент запросил страницу ASP.NET, Затем он передает запрошенный файл выделенному серверу ISAPI — aspneUsapi.dll. Последний посылает страницу рабочему процессу ASP.NET — aspnet_wp.exe. Рабочий процесс вызывает общеязыковую среду исполнения CLR, которая компилирует и выполняет код страницы. Результатом рабочего процесса является HTML-код, который и возвращается клиенту в теле ответа.
Назначение и архитектура технологии ASP.NET
Как следует из названия, технология ASP.NET предназначена для создания так называемых активных серверных страниц. Такие страницы содержат элементы управления и текст в формате HTML Они размещаются на сервере и, таким образом, доступны в Интернете или в интранете. При помещении страницы в браузер пользователя последний может воздействовать на элементы управления (кнопки, списки и т. д.), чтобы добиться нужного результата.
Состав приложения ASP.NET
Каждое приложение ASP.NET размещается в отдельном виртуальном каталоге (см. примечание перед началом этой главы) и имеет несколько файлов и подкаталогов (вложенных папок).
Файлы с расширением aspx содержат веб-формы, которые могут загружаться в браузеры. В одном приложении может содержаться сколько угодно веб-форм. Кахщая
форма обычно сопровождается pas-файлом, который содержит связанный с формой код Delphi. В этом файле чаще всего располагаются обработчики событий Page_Load, Onlnit, а также обработчики щелчков на элементах управления формы. После компиляции pas-файла появляется файл с расширением dcuil. Каждое приложение имеет два индивидуальных файла: Global.asax и Web.config. Первый содержит обработчики событий приложения в целом, а также объекты, доступные всем формам. С ним ассоциирован файл Global.pas, в котором объявляется класс TGlobal как наследник класса System.Web.HttpApplication, и имеются заготовки для обработчиков всех событий, касающихся приложения в целом. Файл Web.config содержит конфигурационную информацию. Он широк。используется, например, для защиты приложений ASP.NET (см. главу 15).
Наконец, полноценное приложение ASP.NET в Delphi имеет файл проекта с расширением dpr и связанные с ним файлы bdsproj, cfgt dsk и пр. Замечу, что имя каждого из этих файлов совпадает с именем виртуального каталога. Файл проекта управляет компиляцией приложения. Результат компиляции всегда помещается во вложенную папку BIN в виде файла с именем проекта и расширением dll.
Веб-формы, компоненты управления сервером и HTML-компоненты
Основными компонентами архитектуры ASP.NET являются веб-формы, компоненты управления сервером и HTML-компоненты.
Веб~формы предназначены для размещения на них текста и компонентов управления сервером, которые предъявляются пользователю в окне его браузера. С каждой веб-формой связывается файл с расширением aspx, содержащий описание страницы на языке HTML, и файл с расширением pas, в котором описывается логика работы приложения на языке Delphi. Aspx-файл автоматически создается и редактируется на этапе разработки веб-формы. Файл с логикой работы компилируется в динамически з^ружаемую библиотеку DLL, которая вместе с aspx-файлом размещается на сервере 1IS или Cassini.
Компоненты управления сервером представляют собой стандартные поля ввода, надписи, списки, кнопки н т. п., модифицированные для технолоши ASP.NET. Их свойства, методы и события используются для организации логики работы приложения. Помимо стандартных интерфейсных компонентов, имеются компоненты для работы с базами данных. При взаимодействии пользователя с интерфейсными компонентами срабатывает связанная с ними программная логика, которая заставляет сервер переслать в браузер нужным образом измененную страницу.
HTML-компоиенты предназначены для статического размещения текста и изображений. Обычно они не взаимодействуют с программной логикой.
Пример приложения
Чтобы пояснить сказанное, создадим простое приложение ASP.NET, которое в окне браузера выглядит так, как показано на рис. 9.1:
Выберите команду File ► New ► ASP.NET Web Application — Delphi for .NET. На экране появится окно (рис. 9.2), в котором необходимо определить нмя приложения, сервер Интернета и расположение файлов. Оставьте предлагаемые по умолчанию параметры без изменения и щелкните на кнопке ОК.
Поместите на пустую веб-форму поле TextBox, кнопку Button и надпись Label (все компоненты из категории Web controls). Выше поля ввода напишите строку Введите в этом окне текст и щелкните на кнопке, как показано на рис. 93
Для кнопки напишите такой обработчик события Click:
procedure TWebForml.Buttorkl_Click(sender: System.Object;
e: System.EventArgs);
begin
Labell.Text := * Привет, <i>' + TextBoxl.Text + '</i> * end;
i Application Name£
Type the name that you want to use for this appk&bn. Use the same namingI:
j conventions that you would for naming a directory.[
^^; |w0bApp1kdlion i"
ipeetont kWub/wrcKit而е1>^рр^£п1《::, ]
:• S^^wf рпЁёТп^игТогт^三卜,View ServerQptiqn$/J
OK [ Cancet [H 卿
Рис. 9.2. Окно для определения названия и расположения веб-приложения
Рис. 9.3. Вид веб-формы на этапе конструирования
Для запуска приложения в среде Delphi просто нажмите клавишу F9 — среда сама вызовет браузер и заполнит адресную строку, указав имя и положение созданного aspx-файла.
Анализ приведенного примера показывает главное достоинство технологии ASP.NET: программист использует те же приемы визуального программирования, что и при создании обычного приложения или приложения для работы с базами данных. Ему не обязательно детальное знание языка HTML (XML). И хотя он может вручную изменять aspx-файл, обычно этого не требуется (щелкните на вкладке WebForml.aspx, чтобы увидеть автоматически созданный текст HTML-документа).
Обратите внимание на использование атрибута Runat=" Server** в стандартных HTML-дескрипторах. Например:
<form Runat="Server">
Этот атрибут указывает на серверную версию дескриптора. Кроме того, вместо атрибута NAME в серверных дескрипторах используется атрибут ID:
<авр:TextBox id="TextBoxln
style=MZ-INDEX: 3; LEFT: 38px; POSITION: absolute; TOP: 54px* runat="server" borderstyle="InsetH borderwidth=nlpxM>
</авр:TextBox>
Возможности технологии ASP.NET
Помимо рассмотренных возможностей, технология ASP.NET имеет ряд других, таких как возможность работы с базами данных, возможность создания веб-служб, расширенные возможности среды и т. д. Эти возможности кратко рассматриваются в этом разделе.
Работа с базами данных
Технология ASP.NET тесно интегрирована с технологией доступа к базам данных ADO.NET. Это предельно упрощает довольно сложную задачу публикации баз данных в Интернете (интранете). Программист может использовать как стандартные для .NET Framework связные компоненты, провайдеры и адаптеры, так и средства технологии BDP.NET, которая, как это было показано в главе 3, поддерживает больше промышленных серверов БД. Для этого в состав Delphi 2005 включены компоненты категории DB Web, в том числе источники данных, сетки, навигаторы ит. д.
Создание веб-служб
Веб-службой называется установленное на сервере программное обеспечение, к которому клиент может получить доступ как к обычному сетевому ресурсу. Спецификой такого рода ресурсов является не создание текстовых HTML-страниц, а предоставление программных услуг. Напрнмер, можно создать службу, которая получает от клиента числовое значение денежной суммы и возвращает ему строку расшифровки (сумму прописью). Если, например, денежная сумма составляет 123 456,78, служба вернет такую строку:
сто двадцать три тысячи четыреста пятьдесят шесть рублей 78 копеек
С появлением технологии .NET корпорация Microsoft объявила, что делает акцент на предоставлении программных услуг, а не на разработке программного обеспечения. Клиент может на определенных условиях использовать веб-службы, то есть получать предлагаемые программные услуги. Технология ASP.NET имеет средства создания веб-служб.
Расширенные возможности среды
Кодовый редактор поддерживает автоматический контроль вводимого HTML-текста и выделение цветом синтаксических ошибок. Если текст содержит ошибку, он подчеркивается красной волнистой линией. При наведении указателя мыши на такой текст появляется окно с сообщением о возможном источнике ошибки. Если ошибка обнаружена на этапе прогона, вызывается окно трассировки, показанное на рис. 9.4.
:工:: 一_e三二 、 丁、. —二
£rtn Орама g ф^Р»**» С**К фИМ*::'1 ' >:-奪
0e®"導囹总
A*^、匾咖/ito^^Mt/Wefc^nwJcaiMM/MWgELMpx. . — ~「 М^^ЦЙ^.」;1^#'*
Ошибка сервера в приложении VW^bApplicationl'.
В экземпляре объекта не задана ссылка из объект.'
апис«нм«1 НкСрвб»(мм исшюмим при аьлсммгю тмги^ ме-мгром Итучле трвеофоку ста дл« гклучм** цопог»«ателн«п см*»«й о дмсА о«)&е и о 1ьп«м»ы м ;工
Сведвмкя об искл<оч«мии; $у»пМ№«1 wncvExOapMn в мммлп^е овмста не мцм сам» на овмкт
Ошибк* источмик*)
gCyTCTVyiTT U»T»rTCTSy<llMt УХОШме строк*]:
искйдиыв ・・an: с. VMKWSMcrDton№TYrimwoftwi "333Van*«irYAS>NETFI«iWMMt^ic#QMS3b2gSUeOcgnMnvO.e CrpemQ
Трасскравкя стека
[NullfteferenceExceptwn: в жлемгишре объекта ,aw ссылка объеят.] Бог1*л4Ас1 .Units.Window*.CresteWindow£x(UIm:32 dMCxStvlo( Stnng 1Х^*<**<>м, String 1 邮mtowNme, Ulntll dwStyle, 】nt?2 X. Int,2 Y, IrrtJI Borlaral. VcbUnits.WinUti H.Al)ocateHWndfn*itfitthM Metncdj Borland.Vcl .TAppItcBticn, ,Ctor(Coa(K»wnt Own")
Borltnd.Vch Uni “.Corttei ・.In»t€orrtrol*Q Borl 5* vc 1«Control 式) torl«nd.Vc1. Uhi t9.Cent ro)*.BtM-l*nd.Vcl .Corn col 5() «nd, Vcl .Units,Controlf. .cctor()
[TypcIniti«hz»tionExc«ptiont Иницив/шмторош типа "Borl«nd*Vcl .Units.Controls" cowu« исклочемне.] 5yiteM.Runti>ne.Cafflpiicr!;ervtEcs.ffuntii«eH<lp«ri.SunClu»Confftructc>r(ltufttiMTy»«t!andle type) 2 Bor1 and.Vel.TControt. .crto*"()
[Typelniti«1 iz*tionExceptiortt Интрклимтором Twn* "Bcrland.vcl .TControl- cqiaand мсклмжнм.] Sy,te«.auntinw.Cw,IerServi c«*.BumirmHel peri.RunCl*5sCanrtrurtor(euntirBtTyp«Hand1 e type) 2 Borland.Vcl.eHetaTControl..crttx-()
ETypBlni ti al ixrt ion Exception: ккмтимиэгпэроы iwn* "eMetiTControl" cciamo ・ckiw*“,.],
Рис. 9.4. Окно трассировки
Директива Раде
Для доступа к странице ASP.NET щелкните на вкладке WebForml.aspx в окне редактора кода. Вы увидите такой код1:
<%@ Раде 1апдиаде=,,с#и Debug="trueH Codebehind=*'WebForn\l .pas*
AutoEventWireup="false" Inherits=°WebForml.TWebFormlи %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4,01 Transitional//EN">
<html>
<head>
<titlex/title>
</head>
<body ms_positioning^"GridLayout">
<form runat "server">
</form>
</body>
</html>
Первые две строки кода в окне редактора представляют собой одну длинную строку. Вы можете разделить их гак, как показано здесь, но перед компиляцией редактор вновь объединит их.
Этот код соответствует пустой веб-форме. Первый элемент кода — директива @ Раде. Эта директива содержит атрибуты, используемые ASP.NET во время компиляции.
Атрибут language определяет язык для встраиваемых фрагментов кода — так называемых сценариев. По умолчанию этим языком является С#. Допускается также использование Visual Basic .NET (значение атрибута — VB) и JScript (значение атрибута — JS). Атрибут Debug указывает, следует ли в откомпилированную страницу помещать отладочную информацию. Атрибут CodeBehind определяет исходный pas-файл, ассоциированный с данной веб-страницей (см, следующий раздел). Атрибут AutoEventWireup указывает, будут ли события автоматически связываться с их обработчиками. Речь идет об обработчиках, определенных в сценариях, а не в ассоциированном pas-файле. Как мы увидим дальше, некоторые события не передаются в класс формы и, таким образом, недоступны в этом файле. Для обработки таких событий и приходится задействовать сценарии. В этом случае следует заменить значение атрибута на true. Наконец, атрибут Inherits указывает класс, объектом которого является веб-страница. Этот класс описан в ассоциированном pas-файле как наследник класса Sy stem, Web. UI. Page.
Атрибут CodeBehind
С помощью атрибута CodeBehind устанавливается связь между веб-страницей и ассоциированным pas-файлом. Автоматическое связывание страницы с pas-файлом является важнейшей особенностью ASP.NET, так как позволяет отделить задачу оформления веб-страницы от задачи реализации логики приложения. Как правило, программисты — плохие художники (сужу по своему личному опыту). Разделение двух задач позволяет более эффективно организовать совместную работу художников и программистов.
В pas-файле объявляется класс веб-страницы. Вот это объявление:
type
TWebForml 二 class(System.Web.UI.Page)
{$REG工ON 'Designer Managed Code1} strict private
procedure InitializeComponent;
{$ENDREGION}
strict private
procedure Page_Load(sender: System.Object; e: System.EventArgs); strict protected
procedure Onlnit(e: EventArgs); override; private { Private Declarations }
public
{ Public Declarations } end;
В новом классе первоначально объявляются процедура InitializeComponent и обработчики событий Load и Onlnit. По мере разработки логики приложения класс пополняется новыми членами.
Сценарии
Сценариями называются фрагменты кода, внедренные в текст веб-страницы между тегами <script> и </scripts Различают два вида сценариев: выполняемые браузером клиента и выполняемые веб-сервером^ Первые могут содержать только код JavaScript, так как только его умеют интерпретировать все современные браузеры. Серверные сценарии могут содержать код С#, JScript или Visual Basic .NET. Они исполняются серверами IIS и Cassini. Если на пустую форму ASP.NET поместить элемент Label, то можно написать такой простой сценарий:
<saript runat=" Server ** >
void Page__Load(Object obj , EventArgs e) {
Labe11.Text = "Hello, World!";
</script>
Этот сценарий определяет обработчик события Load формы на языке С#. Если вы захотите воспроизвести пример, учтите, что сценарий можно располагать в любом месте HTML-кода, но редактор Delphi требует, чтобы он находился сразу за тегами <titlex/title>. Кроме того, не забудьте изменить значение атрибута AutoEventWi reup в директиве @ Раде.
Веб-формы и серверные элементы управления
Как уже отмечалось в предыдущей главе, веб-формы и серверные элементы управления являются основными элементами технологии ASP.NET.
Веб-формы
В технологии ASP.NET формы с атрибутом Ruriat=,1 Server *' называются веб-формами. Этот атрибут указывает на то, что форма обрабатывается сервером. Обработка формы означает, что данные передаются как от сервера в форму (браузер клиента), так и наоборот — от формы в сервер.
Основные особенности веб-форм:
Содержимое формы создается сервером в ответ на запрос клиента.
Содержимое формы доступно для просмотра в любом браузере клиента. Программист может вставлять в форму компоненты, учитывающие специфические особенности конкретного браузера, например Internet Explorer.
Веб-форма реализуется в виде совокупности двух файлов: один (с расширением aspx) содержит HTML-текст, который в окне браузера интерпретируется в виде страницы с текстом и серверными элементами управления; второй (с расширением pas) реализует связанную с приложением логику и представляет собой модуль Delphi. При компиляции pas-файл преобразуется в динамически загружаемую библиотеку (DLL) и размещается в той же папке, что и aspx-файл.
В основе веб-формы лежит объект класса Раде пространства имен System. Web.UI. В табл. 10.1 описываются наиболее важные свойства этого класса.
Таблица 10.1. Свойства класса Раде
Свойство
Описание
property Application:
HttpApplicationState;
Это свойство, предназначенное только для чтения, возвращает объект, содержащий текущий запрос клиента
property Cache: Cache;
Возвращает объект класса Cache, содержащий буфер запросов
property ClientTarget: String;
Возвращает автоматически определенные параметры или устанавливает нужные параметры браузера клиента
property Context : HttpContext;
Возвращает объект, содержащий параметры, связанные с текущей страницей
property EnableViewState : Boolean;
Возвращает или устанавливает признакг определяющий, будет ли страница сохранять состояние, которое было к моменту завершения работы с ней
property ErrorPage: String;
Содержит название страницы, в которой будет сохраняться протокол ошибок, связанных с текущей страницей
property IsPostBack: Boolean г
Содержит True» если страница загружается в первый раз
property IsValid: Boolean;
Возвращает результат вызова метода validation
property Request : HttpRequest;
Возвращает запрос пользователя
property Response: HttpResponse;
Содержит ответ пользователю
property Server:
HttpServerUtility;
Возвращает сервер, связанный с текущей страницей
property Session: HttpSessionState;
Возвращает объект, содержащий параметры текущего сеанса
property Trace: TraceContext;
Возвращает трассировку выполнения текущего запроса
property User: IPrincipal;
Возвращает параметры пользователя, запросив* шего текущую страницу
property Validators: ValidatorCollection;
Возвращает коллекцию компонентов, которые прошли тестирование методом Validate
property ViewStateUserKey: String;
Возвращает идентификатор пользователя, для которого страница хранит состояние вида
property visible: String;
Возвращает True, если текущая страница была отрисована
Свойство EnableViewState по умолчанию имеет значение True, что означает способность формы и расположенных на ней серверных элементов управления
запоминать так называемое состояние вида (view state), то есть то состояние, которое было к моменту, когда пользователь завершил работу со странице!! и вызвал другую. Если в пределах того же сеанса пользователь вновь вызовет прежнюю страницу, она будет в точности такой, какой он видел ес в последний раз. Каким образом реализуется запоминание состояния вида? Для этого в окне браузера выберите команду Вид ► Просмотр HTML-кода. Вы увидите дескриптор, описывающий скрытое поле:
<input 匚уре二"hidden" name="—VIEWSTATE11 valuer r, . . . " / >
Вместо точек в значении атрибута value будет более или менее длинный набор символов. Зтот набор и есть хранилище состояния вида. Заметьте, что сбытого дескриптора _VIEWSTATE нет п исходном aspx-коде — его добавил и наполнил сервер. Состояние вида сохраняется в пределах текущего сеанса, то есть до закрытия окна браузера.
Поскольку страница имеет свойство ViewStaCelJserKey, в котором указывается ядентификатор пользователя, веб-страница может хранить индивидуа.т1ьное состояние вила для каждого посетившего ее пользователя.
Свойство Response класса HTTPResponse содержит ответ на запрос пользователя. Класс HTTPResponse имеет многочисленные свойства и методы, позволяющие программисту непосредственно воздействовать на содержимое HTML-страницы. В частности, методом Write этого класса в формируемую страницу помещается произвольный HTML-текст. Следующий обработчик события Load страницы (файл ChlO\Response\WebForml.aspx) создаст окно, показанное на рис. 10.1:
procedure TWebForml. Page__Load (sender : System.Obj ec匸;
e: System.EventArgs);
var
к: Integer;
begin
Page.Response.Write('<Ы>Демонстрация свойства Response</hl>*);
for к 1 to 7 do
Page.Response.Write (System.StString .Format (
'<font size= {0} >Delphi 2005<brx/font> ' , [k])); end;
Свойство Response (точнее, класс HTTPResponse) имеет метод Redirect, с помощью которого можно переадресовать запрос клиента на другой сайт:
Page.Response.Redirect('http://piter.com');
Серверные элементы управления
При разработке технологии ASP.NET сотрудники Microsoft создали две группы серверных элементов управления: HTML-элементы (категория HTML Elements) и веб-элементы (категория Web Controls), Первая группа относится к пространству имен System.Web.UI.HTMLControls, вторая — к пространству System. Web.UI.WebControls.
Чем это вызвано? Дело в том, что первая группа фактически представляет собой серверные аналоги стандартных HTML-элементов. Как уже говорилось, обычный HTML-элемент превращается в серверный вставкой атрибута Runat= иServer** и использованием атрибута ID вместо NAME. В состав компонентов .NET Framework включен компонент HTMLGenericControl (его нет в палитре компонентов Delphi), который реализует эту нехитрую замену для любого существующего элемента или для элемента, который еще не создан: именно для совместимости технологии с возможными изменениями HTML в будущем и разработана первая группа.
Однако сам язык HTML далеко не оптимален, так как создавался (и создается до сих пор) поэтапно и в его разработке участвовали многие (напомню» консорциум W3C, следящий за *порядком^ в Сети, принимает заявки на изменение HTML и выносит эти заявки на публичное обсуждение; если предложение одобряется компьютерным сообществом, оно становится частью языка). В то же время частые изменения HTML невозможны по той простой причине, что требуют выпуска новых версий браузеров, то есть ведут к многомиллионным затратам. Неоптимальиость HTML заставила Microsoft разработать иеб-компоненты, многие из которых в функциональном плане повторяют функциональность HTML-компонентой, но уже не являются их серверными аналогами. Более того, эта группа компонентов значительно больше и включает в себя компоненты, реализующие новую, по сравнению с HTML, функциональность.
Добавлю, что разработчики Borland внесли свою лепту в виде компонентов категорий Borland Data Provider и DB Web. Эти компоненты, а также стандартные компоненты д.пя работы с базами данных рассмотрены в главе 12.
Компоненты категории HTML Elements
Компоненты категории HTML Elements являются серверными аналогами стандартных элементов управления языка HTML. Они перечислены в табл. 10.2.
Таблица 10.Z Серверные аналоги стандартных элементов управления
Название
Описание
HTML Label
Обычная надпись
HTML Button
Обычная кнопка
HTML Text Box
Поле ввода
HTML Text Area
Многострочное поле
HTML Password
Поле для ввода пароля
HTML Reset Button
Кнопка установки значений, используемых по умолчанию
HTML Submit Button
Кпопка пересылки данных из формы на сервер
HTML Image Button
Кнопка с изображением
HTML CheckBox
Флажок
HTML RadioButton
Переключатель
HTML DropDown
Раскрывающийся список
HTML ListBox
Список
HTML Hidden Field
Скрытое поле ввода
HTML File Upload
Поле ввода нменн файла с кнопкой Обзор
HTML Anchor
Гиперссылка
HTML Table
Таблица
HTML span
Область страницы, для которой используется особый стиль
отрисовки
HTML Div
Область страницы, для которой используется особый стиль отрисовки
HTML Flow Panel
«Плавающая» область DIV
HTML Grid Panel
Фи ксирован ная область DIV
HTML Horizontal Rule
Горизонтальная линия
Использование HTML-элементов в программах на Delphi вызывает определенные трудности. Дело в том, что многие из них (кнопки, например) требуют программной поддержки в виде сценариев. В результате теряется одно из главных преимуществ ASP.NET — отделение логики приложения от HTML-текста страницы. Кроме того, IIS не поддерживает язык программирования Delphi, так что сценарии приходится писать на C# или Visual Basic
ПРИМЕЧАНИЕ
В приводимых далее примерах в некоторых случаях используются сценарии на языке Visual Basic NET. В приложении Г приводится справка по этому языку программирования.
Компоненты категории Web Controls
В отличие от НТМL-компонентов, компоненты категории Web Controls являются полноценными компонентами со своими методами, свойствами и событиями. Это позволяет связать с ними логику управления приложением.
ПРИМЕЧАНИЕ
Некоторые обработчики собы гий определены в окне инспектора объектов, но недоступны в программе. К таковым, например, относятся событие SelectedltemChanged д.1я списков, событие CheckedChange для флажков и переключателе!! и т. п. Если понадобится программная реакция на такое событие, обработчик события необходимо писать в виде сценария. Таким образом, полное отделение логики программы от HTML-кода в элементах категории Web Controls тоже не достигается.
Элемент Ad Rotator
Элемент AdRotator предназначен для размещения на веб-странице рекламных баннеров. Файл, содержащий рекламную информацию, указывается в свойстве AdvertismentFile. В соответствующем XML-файле нужно указать сам рекламный фа11Л, гиперссылку на страницу, к которой ведет этот баннер, альтернативный текст 11 некоторые другие параметры. Например (проект ChlO\AdRotator\ AdRptator.dpr, рис. 10.2):
<Advertisementв>
<Ad>
<ImageUrl>click.g i f </ImageUr1>
<NavigateUrl>http://wxvw.borland.com</NavigateUrl>
<AlternateText>Borland.com</AlternateText>
<Keyword>Computers</Keyword>
<Хтргев81опв>80</Хтргевв1опв>
</Ad>
</Advertisementв>
Можно не определять свойство AdvertismentFile, а использовать обработчик события AdCreated:
procedure TWebForml.AdRotatorl_AdCreated(sender: System.Object; e: System.Web.UI.WebControls.AdCreatedEventArgs);
begin
e.ImageUrl :二'click.gif';
e.NavigateUrl := 'http://www.borland.com';
e.AlternateText := 'Borlan6.com'; end;
Для нормальной работы компонента достаточно задать три параметра:
ImageUrl — файл рекламного баннера;
NavigateURL — гиперссылка на страницу, которая вызывается щелчком на баннере;
AlternativeText — альтернативный текст, заменяющий изображение, если оно по каким-либо причинам недоступно.
Кроме того, можно задействовать два необязательных параметра:
Keyword — определяет категории, которые могут использоваться для фильтрации баннеров;
Impressions — число, указывающее на то, как часто баннер появляется на
странице.
Кнопки
Категория Web Controls содержит три варианта кнопок: обычная (Button), графическая (ImageButton) и с шперссылкой (LinkButton). Все три кнопки выполняют одну и ту же функцию: при щелчке на кнопке серверу передаются некоторые связанные с формой данные. Рисунок 10.3 создан с помощью формы, код которой представлен в листинге 10.1 (файл ChlO\ButtonsDemo\WebForml.aspx).
©Haw ” 0,曲 1@ 心:戶Поиск ☆ И»6tMНюе @
^^^ 圈 htt叩严Д^МогцОую^сЬРоггМ.мр園 目 Пв^М 二矮吋金
Демонстрация кнопок
!葭甚崛九』;4mB^ Lottos i
Щелчок на кнопке LinkButton
Рис. 10.3. Демонстрация кнопок
Листинг 10.1. Демонстрация кнопок
v%@ Page Lan.guage=Bc#'* Debug= HtrueM Codebehind="WebForml.pas" AutoEventWireup= иfalse•* lnherits= "WebForml • TWebForml"%>
<!DOCTYPE HTML PUBLIC #-//W3C//DTD HTML 4.01 Transitional//ENtt>
<html>
<head>
<title></title>
v /head>
<body>
<hl >Демонстрация кнопок</Ы>
vfoxm runat=n server">
<table cellspacing= '• 1n cellpadding^" 1 * width="30G“ border="l">
<tbody>
<tr>
<td style="WIDTH: 92рхи>
<asp:Button id=MButtonle ruriat=**serverH width="84px" text="Button"></asp:Button>
</td>
<td style= "WIDTH: lOBpxf
<asp:XmageButton id=“imageButtonl" runat=Hserver" imageurl=ttclickhere.gif"></asp:XmageButton>
</td>
<td>
<asp:LixikButton id="LinkButtonl * runat=" server•*> LinkButton</asp:Lixi)cButton>
</td>
</tr>
</tbody>
</table>
<asp:Label id="Label1"
Style="Z-INDEX: 1; LEFT: 14px; POSITION: absolute;
TOP: 150pxe runat=йserverи font-size="Largeи font-bold=,,True"></aep:Label>
</fonn>
</body>
</html>
Обработчики событий Click кнопок определены в pas-файле следующим образом:
procedure TWebForml.LinkButtonl_Click(sender: System.Object;
e: System.EventArgs);
begin
Label1.Text := 'Щелчок на кнопке LinkButton1 end;
procedure TWebForml.ImageButtonl_Click(sender: System.Object;
e: System.Web.UI.imageClickEventArgs);
begin
babell.Text := 'Щелчок на кнопке XmageButton'
end;
procedure TWebForml.Buttonl_Click{sender: System.Object;
e: System.EventArgs}; begin
Label1.Text := 'Щелчок на кнопке Button';
end;
Обратите внимание: аргументы обработчика кнопки imageButton отличаются от аргументов обработчиков двух других кнопок. Связано эго с тем, что в объекте е : System.Web.UI. ImagedickEventArgs передаются координаты X и Y указателя мыши в момент щелчка (рис. 10.4). Это может оказаться полезным, если кнопка имеет непрямоугольную форму (файл ChlO\ImageBtnDemo\WebFormsl.aspx).
Рис. 10.4. Использование координат мыши для определения области щелчка на кнопке
Все кнопки имеют строковые свойства CommandName и CommandArg. Эти свойства отсылаются серверу при щелчке на кнопке связанным со щелчком событием Command. Значения этих свойств могут быть произвольными. Например, они могут использоваться для идентификации кнопки.
В следующем примере (файл ChlO\BtnCommand\WebFormsl.aspx) создается окно, показанное на рис. 10,5. В окне три гиперкнопки имеют зашифрованные названия стран. При щелчке на кнопке появляется строка с расшифровкой названия (листинг 10.2).
Листинг 10.2. Использование события Command
<%@ Page Language-"с#" Debugs"true" Codebehind="WebForml.pas" AutoEventWireup^" false" Inherits="WebForml ,TWebForml*'%>
< ! DOCTYPE HTML PUBLIC H-//W3C//DTD HTML 4.01 Transitional//EN,) >
<html>
<head>
<title></title>
v/head>
<body ms_positioning= MGridLayout*>
<form runat-Hserver">
<hl>Демонстрация события Command</hl>
<aspsLinkButton id= ” LinkButtonl"
styles"Z-INDEX: 1; LEFT: 46px; POSITION: absolute;
TOP: 7Opx” runat="serverH commandargument ="Russia'* commandnaine= ^Country" >RU< /asp s LiakBut ton>
<asp:LinkButton id="LinkButton2"
style="Z-INDEX: 2; LEFT: 150px; POSITION: absolute;
TOP: 70px" runat^"server" commandargument="Unated States commandname="Country">US</asp:LinkButton>
<asp:LinkButton id="LinkButton3"
L-tyle^"Z~INDEX: 3; LEFT: 254px; POSITION: absolute;
TOP: 70px" runat^"server* commandargument="South AfricaB commandname="O>:匚try ” >SA</asp:LinkButton>
<asp:Label id二"Label1w
style^-Z-INDEX: 4; LEFT: 46px; POSITION: absolute;
TOP: HOpx*'匚una匕二"£6£\/2匚"font-bold=HTrueR></asp:Label> </form>
</body>
</html>
Все три кнопки (гиперссылки) имеют такой обработчик события Command:
procedure TWebForml,LinkButtonl—Command(sender: System.Object;
e: System.Web.UI.Webcontrols.CommandEventArgs); begin
Labell.Text := 'Your choice is: 1 + e.ConmandArgmnent.ToString end;
Переключатели
Для создания переключателей используются элементы RadioButton и RadioButtonList. Переключатели объединяются в группу. Каждый из них может быть установлен или сброшен. В группе переключателей в установленном состоянии в любой момент времени может быть только один переключатель: при установке другого переключателя первый автоматически сбрасывается.
Элемент RadioButton представляет собой одиночный переключатель. Он объединяется с другими переключателям с помощью своего строкового свойства GroupName. Если логическое свойство AutoPostBack содержит значение True» при установке переключателя данные формы, в которой он расположен, автоматически передаются серверу. Свойство checked позволяет определить состояние переключателя (True, если установлен). Свойство Text определяет надпись переключателя, а свойство TextAlign — выравнивание надписи относительно границ элемента, С переключателем связано событие CheckedChanged, которое возникает при изменении его свойства Checked.
Элемент RadioBu11onL 1st представляет собой группу переключателей. Его удобно использовать для отображения полей таблицы базы данных или коллекций. Свойства элемента представлены в табл. 10.3.
Таблица 10.3. Свойства элемента RadloButtonUst
Свойство
Описание
property AutoPostBack: Boolean;
Если содержит True, то при установке переключателя па сервер автоматически пересылает данные формы, в которой он расположен
property CellPadding:Integer;
Указывает количество пикселов между границей элемента и переключателем
property CellSpasing:Integer;
Устанавливает расстояние между отдельными переключателями
property DataMember: String;
Идентифицирует связываемую с элементом таблицу в источнике данных
property Datasource: Object;
Идентифицирует источник данных для элемента
property DataTextField: String;
Идентифицирует поле с данными для элемента
property Items:
ListltemCollection;
Содержит коллекцию элементов списка
property RepeatColwnns: Integer;
Определяет количество столбцов
Таблица 10.3 (продолжение)
Свойство
Описание
property RepeatDirection: RepeatDirection;
property Selectedlndex:
Указывает направление, в котором должны повторяться переключатели
Возвращает индекс установленного переклю-
Integer;
property Selectedltem: String;
property TextAlign: TextAlign;
чате/ы
Возвращает имя установленного переключателя
Определяет иыраиниванис налписи относительно границ переключателей
Переключатели имеют событие CheckedCanged, возникающее при изменении состояния элемента. Однако обработчик этого события может быть реализован только в виде сценария.
Большинство серверных элементов управления имеют свойство AutoPostBack, позволяющее передать серверу изменившиеся данные формы. Сервер, в свою очередь, может изменить страницу и вернуть ее браузеру пользователя. В следующем примере установка того или иного переключателя приводит к автоматическому изменению цвета формы (рис. 10.6). Соответствующий код представлен в листинге 10.3 (файл ChlO\RadioButtonListAutoPostBack\WebForml.aspx).
файл Правка В.ид ^бршнм С^еис Ф*ка
◎ a . 0 ■ ОЙ 国启:апоиск ☆МзeРе 电候"辱圈 " 1;J 就Й 斗冲抬 f^http:Mocafr»st/adtoButtonL耽AutoPostBack/WebFarmhaspx 一…~^].目 Переход ' Ссылки.专
Демонстрация свойства AutoPostBack
®YeUow О Blue О Green
О White〜
⑥Те . 、—一,_ :.:_.::……「二士、」④££:二二二盡
Рис. 10.6. Демонстрация свойства AutoPostBack
Листинг 10.3. Демонстрация свойства AutoPostBack
<htxnl>
<head>
<script language=Mvb" runat^"Server">
Dim strBackColor As String = "white"
Sub RadioButtonList!_SelectedIndexChanged(s As Object,
e As EventArgs)
strBackColor = RadioButtonListl.Selectedltem.Text
End Sub
</script>
</head>
<body bgcolor=<,<%=strBackColor%>">
<form runat="servern >
<М>Демонстрапия свойства AutoPostBack</hl>
<aep:RadioBu11onLlet id=”RadioButtonList1M
style="Z-INDEX: 1; LEFT: 54px; POSITION: absolute;
TOP: 94px" runat="server" autopostback="True" onselectedindexchanged=
"RadioButtonListl_SelectedIndexChanged'*>
<aep:LietItem value=''Yellow">Yellow</aepiLietItem>
<aep:LietXtem value="Blue">B1ue</aap:Lietltem>
<aep:LietItem value="Green">Green</aep:LietItem>
<aep:LietXtem value="White"
selected="True,,>White</aBp:LietIteni>
</aep:RadioButtonLiet>
</form>
</body>
</html>
В этом коде имеется сценарий на языке Visual Basic, в котором объявляются глобальная переменная strBackColor и обработчик RadioButtonl_Selected- IndexChanged. Глобальная переменная используется в качестве значения атрибута BgColor тега <body>:
<body bgcolor="<%=strBackColor%>">
Обработчик изменяет значение этой переменной, и данные формы отсылаются серверу, сервер возвращает данные в браузер, в результате меняется цвет формы.
Флажки
Флажок обычно используется для представления логических значений (Да или Нен, Включено или Выключено и т. д.). Флажки, как и переключатели, можно объединить в группу, но» в отличие от переключателей, в одной группе может быть одновременно установлено несколько флажков.
Для представления флажков на страницах ASP.NET служат два элемента управления: CheckBox и CheckBoxList.
Элемент CheckBox создает единственный флажок. Его свойства полностью повторяют свойства элемента RadioButton за исключением свойства GroupName, так как флажок может не включаться в группу.
Элемент CheckBoxList создает группу флажков. Его свойства и события повторяют свойства и события элемента RadioBut tonLi st.
В следующем примере (файл ChlO\CheckBoxList\WebForml.aspx) группа Check- BoxListl содержит три флажка, свойства Value которых имеют значения 1, 2 и 3. При щелчке на кнопке подсчитывается сумма зыачений установленных флажков (рис. 10.7).
382 「лава 10 • Веб-формы и серверные элементы управления382 「лава 10 • Веб-формы и серверные элементы управления雙айп Зек。 вид Избранное Сджис «правка戀雙айп Зек。 вид Избранное Сджис «правка戀0^^ " 0,国囱扣?Понос费哂анное ^0 ;价金囱1」注: 厶&宓*;;前 http://localhost/ChedeoAist/WebForml Л5рх.a 1ra . 3螂?0^^ " 0,国囱扣?Понос费哂анное ^0 ;价金囱1」注: 厶&宓*;;前 http://localhost/ChedeoAist/WebForml Л5рх.a 1ra . 3螂?
382 「лава 10 • Веб-формы и серверные элементы управления
382 「лава 10 • Веб-формы и серверные элементы управления
雙айп Зек。 вид Избранное Сджис «правка戀
雙айп Зек。 вид Избранное Сджис «правка戀
0^^ " 0,国囱扣?Понос费哂анное ^0 ;价金囱1」注: 厶&宓*;;前 http://localhost/ChedeoAist/WebForml Л5рх.a 1ra . 3螂?
0^^ " 0,国囱扣?Понос费哂анное ^0 ;价金囱1」注: 厶&宓*;;前 http://localhost/ChedeoAist/WebForml Л5рх.a 1ra . 3螂?
Демонстрация элемента CheckBoxList
ЕОдин ЕДва в три LsM
Сумма значений установленных флажков: 6
丽£7 …“二二二ZZZL^ 二二二□j^^^ZZTT二
Рис 10.7. Демонстрация компонента CheckBoxList
Обработчик щелчка на кнопке имеет следующий вид:
procedure TWebForml.But ton1_Сlick(sender: System.Obj ecr;
e: System.EventArgs}; var
S: Integer;
CB: Lis11em;
begin
S : = 0;// Начальное значение суммы
for CB in CheckBoxListl.Items do // Цикл по флажкам
if CB.Selected then// Флажок установлен?
S := S + Int32.Parse(CB.Value); //-Да. Учитываем его значение
Labell.Text := 'Сумма значений установленных флажков: 1 +
S.ToString end;
Значение Value флажка определено как строка, поэтому при суммировании оно преобразуется к целому числу. Для преобразования используется функция Parse типа данных Int32.
Флажки имеют событие CheckedChange, обработчик которого может быть реализован только в виде сценария.
Элемент Label'
Элемент Label (мадпись) используется для вывода текста и является экземпляром класса System .Web .UI. WebControls . Label. Свойство Text содержит отображаемый в надписи текст. С помощью свойств BorderColor, ForeColor if BackColor можно указать цвет границы, текста и фона надписи.
Элемент Text Box
Элемент TextBox предназначен для ввода текста. Тип элемента определяется свойством TextMode, которое может принимать одно из следующих значений:
Single — стандартное однострочное поле;
MultiLine — многострочное поле;
Password — поле для ввода пароля.
Свойство MaxLength устанавливает максимальное количество отображаемых символов. Свойство Columns определяет ширину поля в символах, а свойство Rows —— высоту поля в количестве отображаемых строк (имеет значение только для многострочного поля).
Для элемента определено событие TextChanged, которое доступно только с помощью сценария.
Списки
Элементы ListBox и DropDownList представляют собой списки. Элементами списка являются экземпляры класса Listltem, совокупность которых образует коллекцию Items элемента.
Список ListBox всегда раскрыт л демонстрирует все предусмотренные в нем элементы. Доступ к элементам списка DropDownList осуществляется только после щелчка на кнопке раскрытия списка.
Свойство Selectedltem возвращает выбранный элемент списка, а свойство SelectedValue — связанную с элементом строку. Если свойство SelectedMode имеет значение Multiple, список позволяет выбирать несколько значений. Списки имеют событие SelectedlndexChange, обработчик которого реализуется в виде сценария.
В следующем примере, код которого представлен в листинге 10.4 (файл ChlO\ ListBox\WebForml,aspx), на форме располагается список с названиями цветов. Изменение выбора в списке приводит к соответствующему изменению цвета надписи (рис. 10.8).
Рис. 10.8. Использование обработчика события SelectedlndexChanged списка
Листинг 10.4. Демонстрация списков
<htnl>
<head>
<script language=,*vbM runat=" Server" >
Dim strColor As String = "black"
Sub ListBoxl_SelectedIndexChanged(в As Obj ect,
e As EventArgs) strColor = ListBoxl.Selectedltem.Text
End Sub
</script>
</head>
<body ms_pQSitioning=nGridLayout"xfont
colQr="<%=:strColor%>,* size=,,8,*>Привет!</ £ont>
〈form runat="server">
<a0p:LietBox id=ttListBoxl** runat=иserverи
onselectedindexchanged="ListBox1_SelectedlndexChanged" autopostback="True” >
<a0p:L10tXtem value=nBlackn
selected="True">Black</aep:L10tXtem>
<aep:Listltem value="Red">Red</asp:L10tltem>
<aep: List Item value=" Yellow** >Yellow</asps LiBtItem>
<asp:Listltem value=“Blue°>Blue</asp:L10tXten>
</a0p:L10tBox>
</form>
</body>
</htBDll>
Обратите внимание: свойство AutoPostBack элемента ListBoxl имеет значение True. Только в этом случае смена выбранного в списке элемента приведет к немедленному изменению цвета текста.
Элемент Image
Элемент Image предназначен для вставки на веб-страницу графического изображения, Для указания графического файла используется свойство imageURL.
В следующем примере, код которого представлен в листинге 10.5 (файл О)Ю\ Image\WebForml .азрх), элемент отображает один из трех рисунков, выбранных с помощью переключателя RadioButtonl (рис. 10.9).
Листинг 10.5. Демонстрация элемента Image
<%@ Раде Language=,,c#*• Debugsиtrue* Codebehind=MWebForml .pas*
AutoEventWireup="false仲 Inherits="WebForml.TWebForml"%>
<I DOCTYPE HTML PUBLIC H-//W3C//DTD HTML 4.01 Transitional//ENH>
<html>
<head>
<titlex/title>
</head>
<body ms_positioning=*'GridLayout.,,>
f ОПП LYlflci:; ~ " server " >
Ы>ГемГ'Н..-: :?гЧ^;::-1 储и」:;广u,:i j ]「》「•!「」••『 hl :■
asp: ImageJ sly ! c " 7 - 1 N: I ;丨止1
口 ’二厂;; T・吓:.-:"
i 1 3二 7「x ” 二/asp: image ■ ■ ; :.: ': RadioButtonList i广二 ” hvd i.「力 i 匸「口匸 L i 0“ 1 "
1 _ " 7' ■ I МГ'ГО^ : ? ; L 卜卜I] ! 2: .n [' s С' 1 : 2'_ ';
T<. ~■
asp : Listitem v^ !•二小:宀 ми . j「“ .
i“:>F= лО'-иг4'-. /asp: Listltem..-
asp: Listitem 1,:; 1」五「" Wnk a「. 卜勺".>?jкстс /asp: Listitem?-
asp : Listitem " a 1 l*一 " 二;:ы,」 . i [口"、3匕]大l. / a8P: Listitem ■
■ asp:RadioButtonList•
asp : Button : 1 - " В и f. л I :- у :: *TjLX :》;LEFT : ?;
l-'QSITTCN:二4: x"
r \ л; - " r "丨; asp : Button.- form >
■. body
html
-; v: ■ -^J h^rp.//localhost,I'lmage/WebFofrnl .asps-; v: ■ -^J h^rp.//localhost,I'lmage/WebFofrnl .aspsДемонстрацияДемонстрация◎ Закат◎ Закат:?■ Зима:?■ Зима1g Готово1g ГотовоГолч'Ьые хслмыГолч'Ьые хслмы/ ' Fistj ' Ц>бра1тное/ ' Fistj ' Ц>бра1тное至} http://bce(host/lm^e/WebForni1.a$px • Microsoft Internet Fxphrer
-; v: ■ -^J h^rp.//localhost,I'lmage/WebFofrnl .asps
-; v: ■ -^J h^rp.//localhost,I'lmage/WebFofrnl .asps
Демонстрация
Демонстрация
◎ Закат
◎ Закат
:?■ Зима
:?■ Зима
1g Готово
1g Готово
Голч'Ьые хслмы
Голч'Ьые хслмы
/ ' Fistj ' Ц>бра1тное
/ ' Fistj ' Ц>бра1тное
компонентакомпонента* 二 f iafes^* 二 f iafes^ПоказатьПоказатьI Файл Правке 酊门 Избранное Сервис (2прзека
компонента
компонента
* 二 f iafes^
* 二 f iafes^
Показать
Показать
386 Глава 10 • Веб-формы и серверные элементы управления
В модуле WebForml.pas определен такой обработчик щелчка на кнопке Показать:
procedure TWebForml.Buttonl_Click(sender: System.Object;
e: System.EventArgs);
begin
Imagel.ImageUrl :二 RadioButtonListl.SelectedValue
end;
Элемент Calendar
Элемент Calendar предназначен для показа календаря. С его помощью можно выбрать нужную дату, которая доступна программе в свойстве SelectedDay. Свойство SelectionMode определяет режим выбора и может иметь одно из следующих значений:
Day — выбирается один день (значение по умолчанию);
DayWeek — выбирается один день или неделя;
DayWeekMonth — выбирается день, неделя или месяц;
None — выбор запрещен.
После перевода календаря в режим DayWeek слева от каждой недели появляется гипертекст, задаваемый свойством SelectWeekText: щелчок на гипертексте выделяет нужную неделю, как показано на рис. 10.10 (файл ChlO\Calendar\ WebForml.aspx).
片回区片回区
片回区
片回区
Файл Правка 啟伍 Избранное Савис Спрмк^
Назад
Адрес;,範 ht^://iocalhort/CalerKiar/WebFonnl .aspx
Режим выбора дат:Режим выбора дат:Демонстрация календаря
Режим выбора дат:
Режим выбора дат:
Месящ Пн Вт Ср Чт Пт Сб Вс
Непел 気28 29 3 c131 1 2 3 ODay
忍耽^自旦互2旦纟坦0 DayWeek Неделя 1112 13 14 IS 16 17 i ©DayWeekMonth Неделя 18 19 20 21 22 23 24
неделя g
Неделя 2 3 4 5 6 7 8:
Первая дата: 25.04.2005. Последняя дата: 01.05.2005
В режиме DayWeekMonth, кроме того, в левом верхнем углу появляется гипертекст, задаваемый свойством Se 1 ectMonthText. Щелчок на этой гиперссылке выделяет нужный месяц. В обоих случаях диапазон выбранных дат возвращается в коллекции свойства SelectedDates.
Рисунок 10.10 создан программой, в которой определены следующие обработчики событий:
procedure TWebForml.Calendarl_SelectionChanged(sender:
System.Object; e: System.EventArgs); begin
caae Calendarl.SelectionMode of
CalendarSelectionMode.None: Label2.Text := * 1;
CalendarSelectionMode.Day: Labels.Text := 'Выбрана дата *
+ DateToStr(Calendarl.SelectedDate); else
Label2.Text := 1 Первая дата: ' +
DateToStr(Calendarl.SelectedDates[0]) +
*. Последняя дата: 1 + DateToStr(Calendarl.SelectedDates[ Calendarl.SelectedDates.Count - 1]);
end;
end;
procedure TWebForml • RadioButtonLi s11—Se 1 ectedlndexChanged (sender: System.Object; e: Syetem,EventArgs);
var
k: Listitem;
Integer;
begin
for k in RadioButtonListl.Items do
if k.Selected then i := StrTolnt(k.Value); case i of
0: Calendarl.SelectionMode := CalendarSelectionMode.None;
1: Calendarl.SelectionMode := CalendarSelectionMode.Day;
Calendarl-SelectionMode :* CalendarSelectionMode.DayWeek;
Calendarl.SelectionMode := CalendarSelectionMode.DayWeekMonth; end;
end;
Помимо описанных, элемент имеет многочисленные свойства оформительского характера, некоторые из которых перечислены в табл. 10.4.
Таблица 104 Свойства элемента Calendar
СвойствоОписание
property Cel 1 Fading : Integer;Указывает расстояние в пикселах между coaq)-
жимым ячейки и ее гранкцамн
property Cellspacing: Integer; Определяет расстояние в пикселах между ячейками
продолжение 界
Таблица 10.4 (продолжение)
Свойство
Описание
property DayNameFonna t:
Устанавливает формат представления дней не-
DayName Forma t;
дели: FirstLetter — первая буква названия дня; FirstTwoLetters — первые две буквы; Full — полное название; Short — краткое название (по умолчанию)
property NextMonthText : String;
Указывает текст для пшерссылки на следующий месяц
property NextPrevFormat:
Указывает формат птсрссылок па предыдущий
Next PrevFormat;
и следующий месяцы: CustomText — текст в свойствах NextMonthText и PrevMonthText (по умолчанию); FullMonth — полное название месяца; ShortMonth — краткое название месяца
property PrevMonthText: String;
Указывает текст для пшерссылки на предыдущий месяц
property ShowDayHeader:
Если содержит True, выводится строка с на-
Boolean;
property ShowGridLines;
званиями дней недели
Если содержит True, ячейки отделяются ли-
Boolean;
1П1ЯМИ
property ShowNext PrevMont h: Boolean;
Если содержит True, выводятся гиперссылки на предыдущий и следующий месяцы
property ShowTitle: Boolean;
Если содержит True, выводится заголовок
property TitleFormat :
Определяег формат заголовка: Month — название
TitleFormat;
property TodaysDate: DateTime;
property visibleDate: DateTime;
месяца; MonthYear — название месяца и год
Содержит текущую дату
Содержит показываемый месяц
При отрисовке очередной ячейки календаря возникает событие DayRender. Программист в обработчике события может изменить стандартный вид ячейки. Обработчик события DayRender в параметре е : DayRenderEventArgs получает свойства, некоторые из которых перечислены в табл. 10.5.
Таблица 10.5. Свойства, получаемые в параметре DayRenderEventArgs
Свойство
Описание
property Cell: Tab!eCell ; property Cell.ColumnSpan:
Ячейка таблицы с визуализируемым днем Количество столбцов таблицы, которое должна
Integer;
занимать ячейка
property Cell.HorizontalAlign:
Горизонтальное выравнивание текста ячейки:
HorizontalAlign;
Center — по центру; Justify — по левому и правому краям одновременно; Left — по левому краю; NoSet — не установлено (по умолчанию); Right — по правому краю
Серверные элементы управления 389
Свойство
Описание
property Cell.Rowspan:Integer;
Количество строк таблицы, которое должна занимать ячейка
property Cell.Text: String;
Текст в ячейке
property Cell.VerticalAlign:
Вертикальное выравнивание текста ячейки:
VerticalAlign;
Bottom — по нижнему краю; Middle — по центру; NoSet — ие установлено (по умолчанию); Тор — по верхнему краю
property Cell.Wrap: Boolean;
Если содержит True, разрешается перенос текста на новую строку
property Day: CalendarDay;
Объект, содержащий визуализируемый день
property Day.Date: DateTime;'
Визуализируемая дата
property Day.DayNumberText:
String;
Визуализируемый текст
property Day.isOtherMonth: Bolean;
Если содержит True, дата не входит в текущий месяц
property Day.IsSelectable: Boolean;
Если содержит True, дата выбрана
property Day.IsToday: Boolean;
Если содержит True, отображается текущая дата
property Day.IsWeekend:
Boolean;
Если содержит True, дата относится к субботе или воскресенью
В следующем примере (файл ChlO\CalendarRender\WebForml.aspx) выделяются все субботы и воскресенья, а также текущий день (рис. 10.11).
Обработчик выделения текущей даты и нерабочих дней выглядит следующим образом:(
procedure TWebForml.Calendarl_DayRender(sender: System.Object; e: System.Web.UI.WebControls.DayRenderEventArgs);
begin
if e.Day.IsToday then// Текущий день?
e.Cel1,BackColor := Color.Orange //-〃a
else if e.Day.isWeekend then// Конец велели?
e.Cell.BackColor := color.Yellow; //-Да end;
Элемент Literal
Элемент управления Literal предназначен для вывода на веб-страницу небольших фрашентов текста. В отличие от элемента Label, свойство Text элемента Literal не может содержать HTML-текст.
Чаще всего элемент Literal используется для точного указания места вывода текста. В следующем примере, код которого представлен в листинге 10.6 (файл СЫ0\ LiteralDemoXWebFormLaspx), элементы Literal вставляются в ячейки таблицы
390 Глава 10 • Веб-формы и серверные элементы управления
(рис. 10.12). Поскольку такие элементы недоступны в обработчике Page_Load формы WebForml.pas, в файле WebForml.aspx используется сценарий на языке Visual Basic .NET.
Файл Правка Е^ Избранное Сервис Справка* 鄒
謬 WiA ' 0 ■曲園卷;志^玄iE 0:
呉爲pec;
Событие DayRender
%ю金嗨* #霓1七5^ .:*%ю金嗨* #霓1七5^ .:*JTh夕叫痂%(3c28293。32124567w3II1213241516红IS19202122232425警点:噺27232930234567JTh夕叫痂%(3c28293。32124567w3II1213241516红IS19202122232425警点:噺27232930234567
%ю金嗨* #霓1七5^ .:*
%ю金嗨* #霓1七5^ .:*
JTh
夕
叫
痂
%
(3c
28
29
3。
32
1
2
4
5
6
7
w
3
II
12
13
24
15
16
红
IS
19
20
21
22
23
24
25
警点:噺
27
23
29
30
2
3
4
5
6
7
JTh
夕
叫
痂
%
(3c
28
29
3。
32
1
2
4
5
6
7
w
3
II
12
13
24
15
16
红
IS
19
20
21
22
23
24
25
警点:噺
27
23
29
30
2
3
4
5
6
7
Рис. 10.11. Выделение текущей даты, а также нерабочих дней
файл Правка Вид Избранное С^еис Справкафайл Правка Вид Избранное С^еис Справка
файл Правка Вид Избранное С^еис Справка
файл Правка Вид Избранное С^еис Справка
Намд *
Лдрос; j紛 http;//locdhost/UteralOemo/Webforfnl .а$рхЛдрос; j紛 http;//locdhost/UteralOemo/Webforfnl .а$рхM 目 Переход Sim ”M 目 Переход Sim ”
Лдрос; j紛 http;//locdhost/UteralOemo/Webforfnl .а$рх
Лдрос; j紛 http;//locdhost/UteralOemo/Webforfnl .а$рх
M 目 Переход Sim ”
M 目 Переход Sim ”
[旦切|gp』[旦切|gp』Демонстрация элемента Literal
[旦切|gp』
[旦切|gp』
Количестео щелчков на кнопке = 3
蜀 Готус;蜀 Готус;.—дМта^И^расет». ~~~.—дМта^И^расет». ~~~
蜀 Готус;
蜀 Готус;
.—дМта^И^расет». ~~~
.—дМта^И^расет». ~~~
Вставка текста в таблицу
16:29
27.04.2005
Листинг 10.6. Демонстрация элементов Literal
<%@ Page CodeBehind= "WebForml.pas • lnherits="WebForml. TWebForml" %>
<head>
<titlex/title>
<script language=Hvb" runat="server">
Sub Page_Load(s As Object, e As EventArgs)
litTime.Text = DateTime.Now.ToShortTimeString() litDate.Text = DateTime.Now.ToShortDateString() End Sub
</8CXipt>
</head>
<body onload= ° Page__Load" ms_pos i t i on ing=" GridLayout" >
<fom runat=" server" >
<Ы>Демонстрация элемента Literal</hl>Количество щелчков на кнопке =
<aspiLiteral id="Literallw runat=n server * text="0">
</asptLiteral>
<asp: Button id=,^Buttonlи
sty1e= *Z-INDEX: 1; LEFT: 294px; POSITION: absolute;
TOP; 70px" runat="server" text ="Button"></asp:Button>
<asp:Table id=eTablel"
style="Z-INDEX: 2; LEFT: 22px; POSITION: absolute;
TOP: 126px" runat= **server* gridlines= "Vertical"
backcolor="Yellow" bordercolor="Black" borderwidth=elpxB borderstyle=" Solid"wiclth=" 219px"
caption="Вставка текста в таблицу" height=и3Зрх"> eg t TableRow>
vasp:TableCellxasp:Literal id= "litTime" runat= "Server"/> </a8ptTableCell>
<&sp t TableCellxasp : Literal id="litDate" runat= * server ** / >
</aspsTableCell>
</asp:TableRow>
</asp:Table>
</fonn>
</body>
</h.tml>
Как видно из приведенного кода, в форме используются три элемента Literal. Элемент Literall помещен на форму обычным перетаскиванием из палитры компонентов, а вот элементы litTime и litDate вставлены вручную (редактированием текста файла WebForml.aspx). В результате они не видны в файле WebForml.pas, а программный доступ к ним возможен только с помощью сценария. Заметьте, что эксперт создания приложения ASPJ4ET вставляет в начало HTML- текста страницы такие строки:
%@ Page Language="c#" Debug=" true1* Codebehind= "WebForml.pas1 AutoEventWireup="false" Inherits="WebForml• TWebFormlrt%>
%@ Register tagprefix="bor1and4 Nainespace="Borland.Data.Web" Assembly="Borland.Data.Web"%>
1 DOCTYPE HTML PUBLIC *-//W3C//DTD HTML 4.01 Transitional//ENM>
392 Глава 10 • Веб-формы и серверные элементы управления
В них указывается язык программирования C# (атрибут Language) и запрещается автоматическое возникновение события onload (атрибут AutoEventwireup). Эти строки нужно заменить такой:
<%@ Page CodeBehind=nWebForml .pas'* Inherits= *'WebForml.TWebForml" %>
В результате сохраняется связь с файлом WebForml.pas и становится работоспособным обработчик щелчка на кнопке.
В дескриптор <body> добавлен атрибут onload=н Page_Load"; если этого не сделать, событие onload обработано не будет.
Поскольку элемент Literal 1 вставлен в форму обычным способом, он доступен в файле WebForml.pas:
procedure TWebForml.Buttonl_Click(sender: System.Object; e: System.EventArgs);
var
k: Integer;
begin
k := Int32.Parse(Literall.Text} + 1;
Literal1.Text := k.ToString;
end;
Элемент Panel
Элемент Panel используется для группировки нескольких элементов управления. Используя свойство Visible, панель вместе с расположенными на ней элементами можно прятать и показывать, как это сделано в проекте ChlO\PanelDemo\ PanelDemo.dpr (рис. 10.13).
файл Орадка 件(Д ©бранное Сдэеис Справке,号"二丁•尊挙■「:广二 窩
◎ a @ 面酒 i^pПоиск ☆и56рЕе ◎合 З—圖* L.J 缴 离》к; j^j http://locaho5t/PanelDemo/WebForml .aspx…隔:0 .К ,£?>^м
Демонстрация панели
Введите свое имя и щелкните на кнопке "Ввод1*恒吧 JL駅甌]Привет г Валерия!Введите свое имя и щелкните на кнопке "Ввод1*恒吧 JL駅甌]Привет г Валерия!©Панель показать О Панель спрятать
Введите свое имя и щелкните на кнопке "Ввод1*
恒吧 JL駅甌]
Привет г Валерия!
Введите свое имя и щелкните на кнопке "Ввод1*
恒吧 JL駅甌]
Привет г Валерия!
В модуле проекта определены такие обработчики:
procedure TWebForml.btName_Click(sender: System.Object;
e: System.EventArgs);
begin
IbName.Text := 'Привет, <i>* + tbName.Text + '</i>!'; end;
procedure TWebForml-btHide_Click(sender: System.Object;
e: System.EventArgs); begin
if rbHide.Items[0].Selected then Panell.Visible := True
else
Panell.Visible := False end;
Замечу, что для элемента RadioButtonList в окне инспектора объектов указано событие SelectedltemChanged, возникающее при установке другого переключателя. Однако в модуль Delphi это событие не передается. В этом нетрудно убедиться:
procedure TWebForml.rbHide_SelectedTndexChanged(sender:
System.Object; e: System.EventArgs); begin
Panell.Visible := not Panell.Visible end;
Несмотря на то что обработчик определен, он не реагирует на установку другого переключателя, поэтому изменение видимости панели осуществляется в обработчике щелчка на кнопке Выполнить.
Любопытной особенностью элемента является отсутствие у него свойства Text, хотя определены такие свойства, как Font, ForeColor, HorizontalAlignment, Wrap. Связано это с тем, что при вставке элемента в форму между тегами <asp: Panel> и </asp:Panel> вставляется текст с именем панели, так что переадс- ленные свойства относятся к этому тексту. Изменить или удалить текст можно только непосредственным редактированием aspx-файла.
Элемент Table
Элемент Table предназначен для создания таблиц. Строки таблицы являются экземплярами класса Tabi eRow, а их совокупность хранится в коллекции свойства Rows. Каждая строка состоит из ячеек, которыми являются экземпляры класса TableCell.
В табл. 10.6 указаны наиболее важные свойства элемента.
Свойство Rows — основное свойство элемента. С помощью редактора этого свойства можно определить строки и ячейки таблицы на этапе создания формы, а с помощью методов Add, Insert, Remove свойства Rows — на этапе прогона.
Таблица 10.6. Свойства элемента Table
Свойство
Описание
property BackColor: Color;
Определяет умалчиваемый цвет фона ячеек и границ
property BacklmageUrl : String;
Задает имя файла с фоновым рисунком
property Bordercolor: Color;
Определяет цвет линий гранни
property Borderstyle:
Определяет стиль границ рядов: NotSet — не
Borderstyle;
установлен (по умолчанию); None — нет границы; Dotted — линия из точек; Dashed — линия из тире; Solid — сплошная линия; Double — двумя линиями; Groove — в виде желоба; Ridge — в виде гребня; Inset — эффект тиснения; Outset —эффект выпуклости
property Borderwidth:Integer;
Определяет толщину границ строк
property Caption: String;
Задает заголовок таблицы
property CaptionAlign:
Определяет выравнивание заголовка: Bottom —
CaptionAlign;
снизу и по центру; Left — влево; NotSet — не определено (по умолчанию); Right — вправо; Тор — сверху и по центру
property CellPadding: Integer;
Расстояние в пикселах между текстом и границами ячейки
property Cellspacing:Integer;
Расстояние в пикселах между соседними ячейками
property Font : Font;
Шрифт заголовка
property ForeColor: Color;
Цвет заголовка
property GridLines: GridLines;
Определяет стиль линий, разделяющих соседние ячейки: Both — по вертикали и горизонтали; Horizontal — по пфизонтали; None — нет линий; Vertical — по вертикали
property Rows:
TableRowsCollection;
Содержит коллекцию объектов класса TableRow
Класс TableRow имеет собственные оформительские свойства BackColor, BorderColor, Borderstyle, BorderWith, Font, ForeColor» HorizontalAlign, которые аналогичны по назначению одноименным свойствам таблицы, но относятся только к одной ее строке. По умолчанию значения этих свойств такие же, как и у таблицы, но программист может их изменять по своему усмотрению, выделяя ту или иную строку собственным цветом, стилем границ, шрифтом и т. д. Центральным свойством класса TableRow является свойство Cells, определяющее коллекцию ячеек — объектов класса ТаЫeCell. Любопытно, что количество ячеек в каждой строке может быть разным, что позволяет создавать таблицы причудливой формы. Каждая ячейка имеет свой набор оформительских свойств,
это дает возможность выделять отдельные ячейки. В классе TableCell определено свойство Text, задающее демонстрируемый в ячейке текст.
В проекте ChlO\TableDemo\TableDemo.dpr создается окно, показанное на рис. 10.14.
◎ * - 0,國團公戶понос费иэбр»电:改輻[◎ * - 0,國團公戶понос费иэбр»电:改輻[Адрес* [⑥ http://tocafritt5yTa^kpemo/Wetf^rmjLas^x ^j 8Я Л^>ехад;:出ОШУ^Адрес* [⑥ http://tocafritt5yTa^kpemo/Wetf^rmjLas^x ^j 8Я Л^>ехад;:出ОШУ^Демонстрация элемента TableДемонстрация элемента TableРис. 10.14. Демонстрация таблицыРис. 10.14. Демонстрация таблицы1234567091024601012141618203691215182124273040121620242В3236405101520253035404550б1218243036424854607142128354249566370а1624324048566472609182736455463728190[1020304050607080901оо]1234567091024601012141618203691215182124273040121620242В3236405101520253035404550б1218243036424854607142128354249566370а1624324048566472609182736455463728190[1020304050607080901оо]Таблица умноженияТаблица умножения
◎ * - 0,國團公戶понос费иэбр»电:改輻[
◎ * - 0,國團公戶понос费иэбр»电:改輻[
Адрес* [⑥ http://tocafritt5yTa^kpemo/Wetf^rmjLas^x ^j 8Я Л^>ехад;:出ОШУ^
Адрес* [⑥ http://tocafritt5yTa^kpemo/Wetf^rmjLas^x ^j 8Я Л^>ехад;:出ОШУ^
Демонстрация элемента Table
Демонстрация элемента Table
Рис. 10.14. Демонстрация таблицы
Рис. 10.14. Демонстрация таблицы
1
2
3
4
5
6
7
0
9
10
2
4
6
0
10
12
14
16
18
20
3
6
9
12
15
18
21
24
27
30
4
0
12
16
20
24
2В
32
36
40
5
10
15
20
25
30
35
40
45
50
б
12
18
24
30
36
42
48
54
60
7
14
21
28
35
42
49
56
63
70
а
16
24
32
40
48
56
64
72
60
9
18
27
36
45
54
63
72
81
90
[10
20
30
40
50
60
70
80
90
1оо]
1
2
3
4
5
6
7
0
9
10
2
4
6
0
10
12
14
16
18
20
3
6
9
12
15
18
21
24
27
30
4
0
12
16
20
24
2В
32
36
40
5
10
15
20
25
30
35
40
45
50
б
12
18
24
30
36
42
48
54
60
7
14
21
28
35
42
49
56
63
70
а
16
24
32
40
48
56
64
72
60
9
18
27
36
45
54
63
72
81
90
[10
20
30
40
50
60
70
80
90
1оо]
Таблица умножения
Таблица умножения
В модуле проекта определен такой обработчик события Page_Load:
procedure TWebForml.Page_Load(sender: System.Obj ect;
e: System.EventArgs); var
, j * k: Integer;
TR: TabieRow;
TC: TableCell;
begin
for i := 1 to 10 do begin
TR : = TableRowXreate;
Tablel.Rows.Add(TR); for j := 1 to 10 do begin
TC := TableCell.Create; k : = i * j ;
// Цикл по строкам
// Создаем новую строку
// Вставляем ее в таблицу
// Цикл по ячейкам
/ / Создаем ячейку
ТС.Text := k.ToString;// Помещаем в нее текст
Tablel.Rows[i - 1].Cells.Add(TC);// Добавляем в строку end; end; end;
Элемент PlaceHolder
Элемент PlaceHolder используется для резервирования на веб-странице места, на которое впоследствии будет помещен элемент управления. Его свойство Controls определяет коллекцию размещаемых на нем элементов.
При размещении элемента на форме он автоматически занимает положение в левом верхнем углу незанятой части формы. Изменить это его положение перетаскиванием нельзя, так как для него не определен атрибут Style.
В следующем примере (файл Ch 10\PlaceHolderDemo\WebForm 1.pas) создается окно, показанное на рис. 10.15.
Рис. 10.15. Кнопки в окне помещены на элемент PlaceHolder
На этапе конструирования на форме размещаются заголовок, обрамленный тегами <hl> и </Ы>, элемент PlaceHolder и элемент Label. В обработчике события Load формы в элемент PlaceHolder вставляются две кнопки:
procedure TVJebForrnl. Page_Load (sender : System. Object ; e: System.EventArgs);
var
Bt: Button;
begin.
Bt := Button.Create;// Создаем первую кнопку
Bt.Text :二'Желтый';// Надпись на ней
Include(Bt.Click, BtnYellow_Click);// Обработчик события Click PlaceHolderl.Controls.Add(Bt) ;// Помещаем на PlaceHolder
Bt : = Button.Create;// Создаем вторую кнопку
Bt.Text := * Белый *;
Include(Bt.Click, BtnWhite_Click);
PlaceHolderl.Controls.Add(Bt); end;
procedure TWebForml.BtnYellow_Click(S: ^Object; e: EventArgs);
begin
Label1.BackColor := Color.Yellow; end;
procedure TWebForml.Btnwhite_C1ick(S: &Object; e: EventArgs); begin
Label1.BackColor := Color.White;
end;
Обратите внимание на два момента. Во-первых, кнопка Bt в обработчике Page. Load создается дважды. Если не обратиться к конструктору для создания второй кнопки, объект Bt будет ссылаться на прежнюю область памяти и на элемент PlaceHolder будет дважды помещена только вторая кнопка. Во-вторых, в при- ложеш<ях ASP.NET связывать с динамически создаваемым объектом обработчик события можно только с помощью перекрытой процедуры Include.
Элемент HyperLink
Элемент HyperLink реализует гиперссылку на веб-странице. Для этого у него определено свойство NavigateURL, в которое нужно поместить требуемый URL-адрес. При щелчке на элементе происходит смена страниц в окне браузера. Если свойство Navi gat eURL не определено (содержит пустую строку), элемент полностью повторяет функциональность элемента Label. Если в свойство ImageURL поместить маршрут доступа к графическому файлу, элемент будет демонстрировать соответствующее изображение» щелчок на котором позволит перейти на страницу, определяемую свойством NavigateURL.
Элемент XML
Элемент XML предназначен для отображения X М L-доку ментов в соответствии с указанным XSL-стилем. Отображаемый документ задается свойством Document- Source, XSL-файл — свойством Trans formSource.,
Проверка данныхПроверка данных
Проверка данных
Проверка данных
В интерактивных системах важную роль приобретает контроль над возможными действиями пользователя. Типичный пример — пользователь щелкнул на кнопке вызова другой формы, оставив незаполненными поля, предназначенные для обязательного заполнения (для регистрации, например). В категории Web Controls есть группа элементов, предназначенных для проверки данных:
RequiredFieldValidator — проверяет, введены ли в элементе управления данные при потере им фокуса ввода;
RangeValidator — контролирует попадание введенного значения в заданный диапазон;
RegularExpressionValidator — проверяет соответствие введенных данных заданной маске или регулярному выражению;
CompareValidator — сравнивает введенное значение с заданным;
CustomVal idator — позволяет программисту написать собственный код для проверки данных;
Vai idat ionSummary — отображает сводку обо всех ошибках ввода.
В этой главе рассматриваются перечисленные компоненты.
Две формы проверки
Существует две формы проверки — на стороне сервера и на стороне клиента. Проверка на стороне сервера требует дополнительного трафика, так как данные отсылаются серверу, который проверяет их и возвращает клиенту результат проверки. В случае клиентской проверки в HTML-страницу вставляется сценарий на языке JavaScript. Этот сценарий интерпретируется клиентским браузером, который и принимает решение о корректности данных. Клиентская проверка снижает загрузку сети и значительно сокращает время реакции на ввод данных, однако не
все браузеры могут интерпретировать сценарии JavaScript, к тому же разные версии одного и того же браузера поддерживают разные версии этого языка, что не всегда гарантирует правильную работу.
Разработчики ASP.NET разработали шумные» элементы проверки» которые генерируют как клиентский, так и серверный код. Если браузер клиента поддерживает JavaScript, ему автоматически пересылается нужный сценарий, в противном случае проверка реализуется сервером.
Следует помнить, что клиентская проверка данных работает только в некоторых браузерах, в частности в Internet Explorer версии 4.0 и выше.
Настройка клиентской проверки
Элементы проверки данных в случае клиентской проверки используют сценарии, хранящиеся в файле WebUIValidation.js. Этот файл по умолчанию устанавливается в папку Inetpub\wwwroot\aspnet_client\system_web\l_l_4322 сервера при установке на машине программного обеспечения технологии ASP.NET. Если файл перенести в другую папку, нужно соответствующим образом откорректировать файл machine.config в папке Windows\MiCTOSoft.NET\Framework\vl. 1.432\Config.
В папке Windows\Microsoft.NET\Framework\vl. 1.432 хранится утилита aspnet.regiis.exe, предназначенная для установки/удаления библиотечного файла WebUIValidation.js. Эта утилита запускается из командной строки с ключом -с для установки библиотеки и с ключом -е для ее удаления.
Отключение клиентской проверки
Если по каким-либо причинам необходимо отключить клиентскую проверку веб-страницы, в ее начало следует поместить следующую директиву:
<%@ Page ClientTarget=*'downlevel" %>
Технология ASP.NET позволяет отключать клиентскую проверку не для всей страницы, а лишь для некоторых элементов проверки: каждый такой элемент имеет логическое свойство EnabledClient Script, в которое в этом случае следует поместить значение False.
Элемент RequiredFieldValidator
Элемент RequiredFieldValidator проверяет, введены ли необходимые данные в контролируемый им элемент. Как правило, он используется для контроля над содержимым полей TextBox, но его можно использовать и с любым другим элементом, способным получать фокус ввода.
Свойства элемента представлены в табл. 11.1.
Элемент имеет метод Validate, который осуществляет проверку и обновляет свойство IsValid. Программный вызов этого метода обычно не требуется, так как он вызывается автоматически при попытке смены страницы.
Свойство
Назначение
property ControlToValidate:
String;
Содержит имя контролируемого элемента
property Display:
VaiidatorDisplay;
Определяет место вывода сообщения об ошибке, содержащегося в свойстве Text: Static — текст появляется на месте размещения элемента; Dynamic — текст появляется на свободном месте страницы; None — текст не появляется
property EnabledClientScript:
Разрешает или запрещает клиентскую про-
Boolean;
property Enabled: Boolean;
property ErrorMessage : String;
верку
Разрешает или запрещает любую проверку
Содержит сообщение, которое выводится в элементе ValidationSummary, если свойство Text не установлено
property Init-Value: String;
Содержит начальное значение контролируемого элемента
property IsValid: Boolean;
Содержит True, если проверка корректности данных прошла успешно
property Text: String;
Определяет сообщение об ошибке
В следующем примере (файл Chll\RequiredFieldValidater\WebForml.aspx) на форме размещаются два поля и кнопка вызова другой станицы (рис. 11.1).
На форме есть также два элемента ReqiredFieldValidator, каждый из которых контролирует содержимое одного из полей. В обработчике щелчка на кнопке анализируется результат проверки:
procedure TWebForml.Buttonl_Click(sender: System.Object;
e: System.EventArgs);
begin
if RequiredFi eldValidatorl.IsValid and
RequiredFieldValidator2.IsValid then
Response.Redirect('WebForm2.aspx'};
end;
В каждом приложении ASP.NET определен объект Response, содержащий ответ на запрос клиента. Метод Redirect этого объекта осуществляет переадресацию запроса на другую страницу. Помимо объекта Response в ASP.NET определены также объекты Request, Server, Application и Session.
Элемент RangeValidator
Элемент RangeValidator позволяет проверить, попадает лн введенное пользователем значение в заданный диапазон. В качестве границ диапазона могут использоваться числа, даты, денежные суммы и строки. Свойства Minimumvalue н MaxiimiinValue хранят границы диапазона. Свойство Туре определяет тип данных и может иметь значение Integer, Double, Currency, Date или String. Остальное свойства элемента такие же, как у элемента RequiredFieldValidator.
ПРИМЕЧАНИЕ
Дата может вводиться только в формате 20/1/2005 или 20-1-2005.
Рисунок 11.2 иллюстрирует использование элемента RangeValidator (файл Chll\ RangeValidator\WebForml.aspx).
Элемент RegularExpressionValidator
Элемент RegularExpressionValidator сравнивает введенные пользователем данные с некоторым регулярным выражением. В качестве такового используется строка, задающая шаблон ввода. Эта строка помещается в свойство ValidationExpression элемента. Остальные свойства элемента такие же, как у элемента RequiredFieldValidator.
В простейшем случае регулярное выражение — это просто строка. В этом случае ввод пользователя должен просто повторить эту строку. Такая проверка, например» применяется для контроля правильности введенного пароля (см. рис. 11.1). В этом примере (файл Chll\RegularExpessionValidator\WebForml.aspx) свойство ValidationExpression содержит строку Delphi. Более сложные проверки реализуются вставкой в строку шаблона специальных метасимволов.
ПРИМЕЧАНИЕ
В окне инспектора объектов в строке свойства Vai idationExpession имеется кнопка, щелчок на которой открывает список стандартных для ASP.NET шаблонов.
Метасимвол \w определяет любой словообразующий символ (латинскую букву, знак подчеркивания или цифру). Метасимвол \w+ определяет любое количество словообразующих символов. Следующее регулярное выражение определяет произвольный латинский текст:
(\wl \s) +
Здесь метасимвол \ s задает пробел, метасимвол I означает выбор одного из двух метасимволов» а скобки группируют метасимволы, так что метасимвол + относится к заключенному в скобки выражению. Показанное ниже выражение определяет произвольный латинский текст, начинающийся символами begin и заканчивающийся символами end:
begin(\wl \s) +end
ПРИМЕЧАНИЕ
Текст в шаблоне чувствителен к регистру символов. Таким образомt введенная в элемент RegularExpressionValidator строка BEGlN_end для указанного ранее регулярного выражения будет ошибочной.
Метасимвол \d задает цифру. Следующее регулярное выражение определяет телефонный номер в формате 555-55-55:
\d{3}\-\d{2}\~\d{2}
С помощью фигурных скобок можно указать количество допустимых символов. Подстрока \d{3) означает три и только три цифры. Можно указывать диапазон. Например, следующее регулярное выражение определяет строку длиной от 2 до 5 символов:
\w{2,5}
ПРИМЕЧАНИЕ
Элемент RegularExpressionValidator никак не реагирует па отсутствие данных, поэтому его обычно дополняют элементом RequiredFieldValidator.
Элемент CompareValidator
Элемент CompareValidator выполняет сравнение данных в поле формы с другими данными. Сравниваемыми данными могут быть числа, даты, денежные суммы, строки. Помимо свойств элемента RequiredFieldValidator у элемента CompareValidator есть свойства ControlToCompare, ValueToCompare, Operator и туре. Первое определяет второй элемент с данными: сравнение осуществляется между ним и элементом ControlToCompare. Например, при вводе диапазона дат начальная дата не должна превышать конечную. Свойство Operator задает операцию сравнения и может иметь одно из следующих значений: Equal — равно, NotEqual — не равно, GreaterThen — больше, GreaterThenEqual 一 больше или равно, LessThen — меньше, LessThenEqual — меньше или равно, СompareDateCheck — проверить правильность даты. Свойство Туре устанавливает тип сравниваемых данных и может иметь значение Integer, Double, Currency, Date или String.
ПРИМЕЧАНИЕ
Дата можег вводиться только в формате 20/1/2005 или 20-1-2005.
На рис. 11.3 показано окно программы, в которой элемент CompareValidator используется для сравнения дат (файл Chll\CompareValidator\WebForml.aspx). Специфичные для элемента свойства имеют такие значения: ControlToValidate = TextBoxl (начальная дата), ControlToCompare = TextBox2, Operator = GreaterTnenEqual, Type = Date.
404 Глава 11 • Проверка данных
Элемент Validationsummary
Элемент Vai idat ionSummary создает отчет обо' всех ошибках в данных веб-формы. Его особенно удобно применять на громоздких формах с множеством элементов контроля. Специфические свойства элемента перечислены в табл. 11.2.
Таблица 11.2. Свойства элемента Validationsummary
Свойство
Назначение
property DisplayMode:
Устанавливает формат сообщений об ошиб-
ValidationSummaryDisplayMode;
ках: BulletList — в маркированном списке; List — в простом списке; SingleParagraph —в одном абзаце
property EnabledClientScript:
Разрешает/запретаст клиентскую проверку
Boolean;
данных
property Enabled: Boolean;
Разреи1ает/запрешает любую проверку
property HeaderText: String;
Определяет заголовок отчета
property ShowMessageBox:
Если содержит True, отчет выводится во
Boolean;
всплывающем окне
property ShowSummary: Boolean;
Разрешаст/запрей(ает »ывод отчета
На рис. 11.4 показаны все три формата отчета об ошибках, устанавливаемые свойством DisplayMode (файл Chll\ValidationSummary\WebForml.aspx).
О•方、同图G戶m②:济冷,扇”Adpa^J稿http:/flocdhcMt/Vaidation5ummary/We№OTil.a4Bx献目ПУ^ '窓吋 域О•方、同图G戶m②:济冷,扇”Adpa^J稿http:/flocdhcMt/Vaidation5ummary/We№OTil.a4Bx献目ПУ^ '窓吋 域
О•方、同图G戶m②:济冷,扇”
Adpa^J稿http:/flocdhcMt/Vaidation5ummary/We№OTil.a4Bx献目ПУ^ '窓吋 域
О•方、同图G戶m②:济冷,扇”
Adpa^J稿http:/flocdhcMt/Vaidation5ummary/We№OTil.a4Bx献目ПУ^ '窓吋 域
Ваше имя:;
Операционная система cwingows NT
□Windows XP
BulletLIstList
Eb; 3s6b】nH зэпапнить <л>?дуЮ!лу1е г-оля
•匕君出日RM9广史上干口[**介М2
• Опер^цноннэя системаEd*占韜мн
SingleParagraph
Rh! 3分5h冃н?аполнить еп^укдци^ гК]е е口:沿>*阴 仆:*;个工⑪广浦田сист^мп
Рис. 11.5. Всплывающее окно с отчетомРис. 11.5. Всплывающее окно с отчетомНа рис. 11.5 показано всплывающее окно с отчетом об ошибках (свойство ShowMessageBox элемента имеет значение True).
Рис. 11.5. Всплывающее окно с отчетом
Рис. 11.5. Всплывающее окно с отчетом
Элемент CustomValidator
Элемент CustomValidator позволяет программисту самому организовать проверку
данных как на стороне сервера, так и в клиентском браузере. Для этого в первом случае он должен написать обработчик события ServerValidate, а во втором — создать сценарий на языке JavaScript (напомню, что этот сценарий интерпретирует браузер клиента, которьпЬ в отличие от 1IS, не обязан «понимать» язык C# 15“ Visual Basic .NET). Как обработчик, так и функция JavaScript принимают два параметра: первый содержит объект CustomValidator и имеет тип Obj ect, а второй инкапсулирует связанные с событием параметры в виде объекта класса ServerVal idateEventArgs. Этот класс имеет два свойства: логическое
IsValid и строковое Value. Обработчик ана-чизирует свойство Value и возвращает результат в свойстве IsValid.
В следующем примере (файл Chll\CustomValidator\WebForml.aspx) используется такой обработчик:
procedure TOebF'orml. CascomVal idatorl_ServerValidate (
source: System.Object; args: ServerValidateEventArgs);
var
k: Integer;
begin
k : = Int32.Parse(aigs.Value);
args.IsValid :二 not odd(k);
end;
Результат показан на рис. 11.6.
Файл Правка &на Иэбранное Сервис СправкаФайл Правка &на Иэбранное Сервис СправкаААНамд ▼Намд ▼Лдрес^ j 葡 http :y/localhost/CustomVabdator/WebForml <aspxЛдрес^ j 葡 http :y/localhost/CustomVabdator/WebForml <aspx[v]目 Переход 3*[v]目 Переход 3*◎ 3@企户me ☆哂2 0,氏◎ 3@企户me ☆哂2 0,氏Введите четное число:'123I Эю иечстнсе число!Введите четное число:'123I Эю иечстнсе число!朝^Готово . .■■",呵Маа^;йнтр«»^朝^Готово . .■■",呵Маа^;йнтр«»^
Файл Правка &на Иэбранное Сервис Справка
Файл Правка &на Иэбранное Сервис Справка
А
А
Намд ▼
Намд ▼
Лдрес^ j 葡 http :y/localhost/CustomVabdator/WebForml <aspx
Лдрес^ j 葡 http :y/localhost/CustomVabdator/WebForml <aspx
[v]目 Переход 3*
[v]目 Переход 3*
◎ 3@企户me ☆哂2 0,氏
◎ 3@企户me ☆哂2 0,氏
Введите четное число:
'123I Эю иечстнсе число!
Введите четное число:
'123I Эю иечстнсе число!
朝
^Готово . .■■",呵Маа^;йнтр«»^
朝
^Готово . .■■",呵Маа^;йнтр«»^
Работа с базами данныхРабота с базами данных
Работа с базами данных
Работа с базами данных
Публикация баз данных в Интернете является одной из наиболее интересных задач, решаемых с помощью технологии ASP.NET. В Delphi 2005 есть возможность использовать как стандартные для .NET Framework средства работы с данными, так м средства, разработанные корпорацией Borland. Последние сосредоточены в категориях Borland Data Provider и DB Web палитры компонентов. В этой главе рассматриваются обе группы средств.
Доступ к данным
Доступ к данным в рамках приложений ASP.NET реализуется с помощью технологии ADO.NET, достаточно подробно рассмотренной в главе 2. При создании приложений ASP.NET компоненты этой технологии сосредоточены в категориях Data Components и Borland Data Provider палитры компонентов Delphi. В этом разделе кратко описываются указанные компоненты.
Компоненты доступа к MS SQL Server
В категории Data Components представлены компоненты доступа к базам данных, обслуживаемым сервером MS SQL Server. Напомню, что отделение этих компонентов от других позволило использовать быстрый протокол TDS (Tabular Data Stream — протокол передачи табличных данных) и тем самым ускорить доступ к данным. Компонент SqlConnection устанавливает связь приложения с серверной базой данных. С помощью редактора свойства Connectionstring формируется строка связи, содержащая все необходимые данные для доступа к БД.
Компонент SqlDataAdapter формирует запросы к БД для чтения и модификации данных и осуществляет связь с компонентом DataSet.
Компонент Sql Command используется для выполнения транзакций или хранимых процедур.
Компоненты доступа к другим источникам данных
Для доступа к другим источника данных используются компоненты BdpConnect- ion, BdpDataAdapter и DataSet. Связной компонент BdpConnection позволяет взаимодействовать с промышленными серверами MS SQL Server, DB2, Oracle, Sybase, InterBase, а также с таблицами MS Access. Адаптер BdpDataAdapter формирует SQL-запросы к одной или нескольким таблицам БД, представлениям или хранимым процедурам. Этот компонент формирует все четыре SQL- запроса, которые хранятся в его свойствах De 1 е t eCommand, Insert Command, SelectConunand и UpdateCommand. При представлении данных на веб-страницах часто бывает удобнее вместо адаптера применять компонент BdpCommand, который реализует единственную команду, хранящуюся в свойстве CommandText. При этом, если команда возвращает данные, используется его метод Execut eReader или ExecuteScalar, в противном случае — ExtcuteNonQuery. Набор данных (класс DataSet) предоставляет удобный механизм чтения и обновления данных и инкапсулирует в себе в общем случае множество таблиц и связей между ними. При необходимости можно включить еще два компонента: ODBCConnection и ODBCDataAdapter. Эти компоненты рассчитаны на доступ к данным по технологии ODBC, но по умолчанию не устанавливаются. Для их установки следует выбрать команду Components ► Install .NET Components, разыскать их в списке компонентов и установить соответствующие флажки. После закрытия окна компоненты появятся в категории Data Components.
Визуализация данных
Визуализировать данные, хранимые в компоненте DataSet, можно либо с помощью стандартных компонентов категории Web Controls, либо с помощью компонентов категории DB Web. Последние разработаны корпорацией Borland и, как показывает практика, намного удобнее стандартных. Для их связи с наборами данных DataSet используются компоненты-клапаны DBWebDataSource, играющие такую же роль, как и компоненты TDataSource в VCL-приложениях.
Простой пример
Рассмотрим пример, в котором создается окно, показанное на рис. 12.1 (файл Chl2\DataPublicDemo\WebForml.aspx).
Как видно из рисунка, программа публикует таблицу BOOKS из БД <Книголюб».
Начните новый проект ASP.NET. Если вы еще не создавали соединение с БД C:\BIBLDATA\IB_BIBL.GDB( создайте его. Для этого в правой верхней панели окна менеджера проектов щелкните на вкладке со значком Data Expkxer для вызова окна одноименной утилиты. В этом окне щелкните правой кнопкой на узле Interbase и в контекстном меню выберите команду Add New Connection. В появившемся окне введите имя нового соединения, например IBConn. После этого раскройте узел Interbase, щелкните правой кнопкой мыши на новом соединении,
в контекстном меню выберите команду Modify Connection и fiacnpoii re соединение так, как показано на рис. 12.2.
файл Правка g №бранмоо Ctfet
0z, ◎,豆懑冷 ,**у 丿紀 hrtpJ/tocehort/DetaPubkDemo/W
ebFomi.ftspx'^ Переход ■
Демонстрация публнкаинн данных
CtJ®ILiLJLiLm) m 1±й 覧;
BOOKID
BNAME
BAUTHGR
BPUBLI3H
BYEAI I
:10 минут на урок MS Wo:
Эйткен
:5иЛьЯМС
;199Э
10 имкут мв урок Uindovs 90
Фултоя
Диалектика
1995
3
10 юшут на урок.Оса。* самостоятельно MS Excel 2000
Фултон
ВИЛЬЯНС
1999
4
100 коипоневтов общего пазпачекия бмвпкотекх Delphi 5
Лрхапгелъсг.ик
Биаом
19Й9
5
1001 секрет реестра Vindoиз NT
Дэниелс
Русская Редакция
1999
6
12 уроков тенниса.Самый доступный самоучитель для всех
Нмчук
Терра-Спорт
1959
1
*J Местная «нтрвсвтъ' J
Рис. 12.1. Окно работающей программы
Comechon 豆eWng$! ОЫйЬмдComechon 豆eWng$! ОЫйЬмдlocalho*t:CABiblData\IB Bllocalho*t:CABiblData\IB Bl:卜;Passwordk?;? UserNanoe陋爵扱綴次^g^fiMc'!?■■■ CommitRetainj LoginPronnpt,QuoteObiectsI RoleName}S er verChacS etI SQLDialect纟* Ttansadroritolation卜岂 WaitOnLockst ; Assembly陽? Hi':-:卜;Passwordk?;? UserNanoe陋爵扱綴次^g^fiMc'!?■■■ CommitRetainj LoginPronnpt,QuoteObiectsI RoleName}S er verChacS etI SQLDialect纟* Ttansadroritolation卜岂 WaitOnLockst ; Assembly陽? Hi':-■ masterkey .sjfsdbe■ masterkey .sjfsdbeFalse False False myroteFalse False False myroteReadCommKtedFalseReadCommKtedFalse,Bcnland.Data.lntesbase, Ve( ■,Bcnland.Data.lntesbase, Ve( ■Cancel. ICancel. I
Comechon 豆eWng$
! ОЫйЬмд
Comechon 豆eWng$
! ОЫйЬмд
localho*t:CABiblData\IB Bl
localho*t:CABiblData\IB Bl
:卜;Password
k?;? UserNanoe
陋爵扱綴次^g^fiMc
'!?■■■ CommitRetain
j LoginPronnpt
,QuoteObiects
I RoleName
}S er verChacS et
I SQLDialect
纟* Ttansadroritolation
卜岂 WaitOnLocks
t ; Assembly
陽? Hi':-
:卜;Password
k?;? UserNanoe
陋爵扱綴次^g^fiMc
'!?■■■ CommitRetain
j LoginPronnpt
,QuoteObiects
I RoleName
}S er verChacS et
I SQLDialect
纟* Ttansadroritolation
卜岂 WaitOnLocks
t ; Assembly
陽? Hi':-
■ masterkey .sjfsdbe
■ masterkey .sjfsdbe
False False False myrote
False False False myrote
ReadCommKted
False
ReadCommKted
False
,Bcnland.Data.lntesbase, Ve( ■
,Bcnland.Data.lntesbase, Ve( ■
Cancel. I
Cancel. I
ВНИМАНИЕ
При работе с таблицами InterBase в технологии ASP.NET маршруту доступа к файлу БД должен предшествовать префикс с DNS-именем узла сети, на котором запущен сервер InterBase, например: localhost :С: \Data\MyData.gdb. Если префикс не указать, то на этапе редактирования формы сетка будет заполняться данными, но при прогоне программы появится сообщение Unavailable database (База данных не- до(ггунна).
В окне Data Explorer раскройте узел соединения с БД «Книголюб», затем раскройте узел Tables н перетащите таблицу BOOKS в окно формы. В нижней часта формы появятся два компонента: связной компонент BdpConnec t i onl, настроенный на связь с БД IB_BIBL.GDB, и адаптер BdpDat aAdaptег 1 т настроенный на отображение всех полей таблицы BOOKS.
Присоедините к ним компонент DataSet (категория Data Components)
В свойство DataSet адаптера поместите ссылку на компоиент DataSetl и активизируйте адаптер (Active * True).
Присоедините к проекту компонент DBWebDa t a So u гс е (категория DB Web) и в его свойство Datasource поместите ссылку на таблицу BOOKS.
Поместите на форму компоненты DBWebNavigator и DBWebGrid (категория DB Web) и настройте их: в свойства Datasource поместите ссылки на компонент DBWebDataSourcel, а в свойства ТаЫeName — ссылки на таблицу BOOKS. Сетка должна наполниться данными.
Итак, мы решили довольно сложную задачу, не написав ни одной строчки кода1! Как мы увидим дальше, использование классических элементов ASP.NET из категорий Data Components и Web Controls для решения той же задачи требует значительно больших усилий. Другим немаловажным преимуществом компонентов категории DB Web является то, что они «живут> (наполняются данными) не только на этапе прогона программы, но и на этапе конструирования формы.
Стандартные элементы для работы с базами данных
В этом разделе рассматриваются возможности стандартных серверных элементов применительно к базам данных. Компоненты категории DB Web описаны в разделе «Элементы категории DB Web».
На самом деле это не так: если вы запустите проект, то увидите, что в компоненте DBWebNaViдаtor кнопка подтверждения сделанных изменений недоступна. Чтобы полностью реализовать все возможные действия (вставка, удаление и изменение записей), следует определить обработчик события DBWebDataSource. OnApplyChangesRequest (подробнее см. раздел <Элемент DBWebDataSource>).
Привязка данных
Все компоненты технологии ASP.NET унаследованы от класса Control, который передает своим потомкам метод DataBind. Этот метод осуществляет так называемую привязку данных, представляющую собой динамическую установку значения некоторого свойства элемента управления. Таким образом, любой из рассмотренных в главе 11 серверных элементов управления можно при желании связать с данными из БД или XML-файла.
ПРИМЕЧАНИЕ
На всб-страницс может находиться множество элементов управления, связанных с данными. Чтобы не обращаться к методу DataBind каждого элемеггга, вызовите этот метод для страницы, которая также является наследником класса Control. Связывание страницы с данными приведет к автоматическому связыванию всех расположенных на ней элементов управления.
В качестве примера рассмотрим программу, которая создает окно, показанное на рис. 12.3 (файл Chl2\DataBindingDemo\WebForml.aspx).
Рис. 12.3. Отображение данных в элементах TextBox
В шести элементах TextBox этого окна отображаются данные из шести полей первой записи таблицы BOOKS базы данных IB_BIBL.GDB. С веб-страницей связаны не показанные на рисунке компоненты BdpConnection, BdpDataAdapter и DataSet. Для каждого элемента TextBox щелчок на кнопке свойства DataBindings открывает окно, показанное на рис. 12.4.
ДанныхДанныхСм电唾 a(w游ащие g»WСм电唾 a(w游ащие g»W■•為:囲也駡■•為:囲也駡AccessKey BackColw BocdefCokx BorderStyle BorderWidth Columns CssQaxs Enabled Font FaeColoi Hei^it MaxLength Readonly Rows t«4 ToolTipAccessKey BackColw BocdefCokx BorderStyle BorderWidth Columns CssQaxs Enabled Font FaeColoi Hei^it MaxLength Readonly Rows t«4 ToolTipw,w,<!■<!■Привязке для Те4 - 介 Л росшая привдзк«:Привязке для Те4 - 介 Л росшая привдзк«:■ Q3 (Несвязанный)儲)DataSetlW「30 BOOKSW;罩 DefaullView邑• £3 DefaulWiew (0)营® BAUTHOR理班变二二产…」:・ ияушр:.「"I "~2 T: '■ Q3 (Несвязанный)儲)DataSetlW「30 BOOKSW;罩 DefaullView邑• £3 DefaulWiew (0)营® BAUTHOR理班变二二产…」:・ ияушр:.「"I "~2 T: 'Г усебоваырАжене примэкхГ усебоваырАжене примэкхbwJ,l / ^ J ( <^*5 心 СbwJ,l / ^ J ( <^*5 心 СОшена ] Оф^З jОшена ] Оф^З j
Данных
Данных
См电唾 a(w游ащие g»W
См电唾 a(w游ащие g»W
■•為
:囲
也駡
■•為
:囲
也駡
AccessKey BackColw BocdefCokx BorderStyle BorderWidth Columns CssQaxs Enabled Font FaeColoi Hei^it MaxLength Readonly Rows t«4 ToolTip
AccessKey BackColw BocdefCokx BorderStyle BorderWidth Columns CssQaxs Enabled Font FaeColoi Hei^it MaxLength Readonly Rows t«4 ToolTip
w,
w,
<!■
<!■
Привязке для Те4 - 介 Л росшая привдзк«:
Привязке для Те4 - 介 Л росшая привдзк«:
■ Q3 (Несвязанный)
儲)DataSetl
W「30 BOOKS
W;罩 DefaullView
邑• £3 DefaulWiew (0)
营® BAUTHOR
理班变二二产…」:・ ияушр:.「"
I "~2 T: '
■ Q3 (Несвязанный)
儲)DataSetl
W「30 BOOKS
W;罩 DefaullView
邑• £3 DefaulWiew (0)
营® BAUTHOR
理班变二二产…」:・ ияушр:.「"
I "~2 T: '
Г усебоваырАжене примэкх
Г усебоваырАжене примэкх
bwJ,l / ^ J ( <^*5 心 С
bwJ,l / ^ J ( <^*5 心 С
Ошена ] Оф^З j
Ошена ] Оф^З j
Въ&嬲杆e a曲g 曲я привязки, Зари восполь碑йп4 川& простой привязкой для лрмвяжк. ^ вйементу даннЬж и «мания Фсрм«гмрсв4Нй^ либо позоветельской Лри^экой для; ыкки Мйражения привязки.
Рис. 12.4. Окно редактора свойства Data Bindings
В левом списке этого окна выбирается свойство, допускающее привязку, а в правом — поле с данными. Чтобы наполнить поля ввода данными, используется такой обработчик:
procedure TWebForml.Page_Load(sender: System.Object; e: System.EventArgs);
begin
if not Self.IsPostBack then
Self.DataBind;
end;
Проверка свойства IsPostBack приложения делается для того, чтобы данные в поля ввода загружались единственный раз — при первой загрузке формы.
ПРИМЕЧАНИЕ
Любое приложение ASP.NET автоматически снабжается обработчиком события Load, которое возникает при загрузке страницы. Он доступен в pas-файле и ио умолчанию ничего не делает.
Программа носит чисто иллюстративный характер, поэтому возможное изменение данных в полях никак не влияет на собственно данные в таблице. Если бы мы захотели действительно изменять табличные данные, нам нужно было бы предусмотреть кнопку, обработчик щелчка на которой вызывал бы метод AcceptChanges набора данных DataSet. Еще одна особенность программы — в ней не предусмотрены средства навигации по таблице. Проще всего решить эту задачу можно с помощью компонентов категории DB Web, которые рассматриваются в разделе «Элементы категории DB Web».
Элемент Repeater
Элемент управления Repeater, как и рассматриваемые далее элементы DataList и DataGrid, предназначен для вывода наборов данных — таблиц, запросов, представлений (виртуальных таблиц). Но он может связываться также с любыми другими источниками множества данных, например с XML-файлами, коллекциями и т. п.
Элемент визуализируется только в том случае, если он привязан к источнику данных. Если разместить компонент на форме, то в нем вы увидите такой текст: <Для правки шаблонов элементов переключитесь в режим HTML》. Это сообщение напоминает, что данные в элементе и сам он не будут отображаться до тех пор, пока вы не создадите в aspx-файле шаблоны для их форматирования.
Элемент имеет пять шаблонов со следующими тегами:
<HeaderTemplate> — управляет форматированием верхнего колонтитула;
<ItemTemplate> — управляет форматированием каждого элемента данных;
<AltematingItemTemplate> — управляет форматированием альтернативных элементов данных;
<SeparatorTemplate> — управляет разделителем между элементами данных;
<FooterTemplate> — управляет форматированием нижнего колонтитула.
В типичном варианте вывода данных в форме таблицы в верхнем колонтитуле содержится тег объявления таблицы <table> и теги <tr>, <th>( </th>, </tr>, определяющие форматирование шапки (первой строки) таблицы. В шаблоне <ItemTemplate> размещаются теги <tr>, <td>, </td>T </tr>, определяющие обычную строку таблицы. Наконец, в шаблоне <FooterTemplate> размещается тег окончания таблицы </table>. Для привязки данных в обычной строке таблицы между тегами <td> и </td> помещаются специальные теги привязки:
<%#Container.Dataltem("ИмяЛоля")%>
Здесь ИмяПоля — имя поля таблицы базы данных.
ПРИМЕЧАНИЕ
Если при прогоне программы источник данных по каким-либо причинам недоступен, отладчик ASP.NET выдает неверную диагностику: он выделяет строку с тегами привязки и заявляет, что эта строка ссылается на свойство, в то время как требуется метод (рис. 12.5).
Должен сказать, что использовать элемент Repeater в приложениях Delphi непросто. Мне, например, не удалось добиться его нормальной работы по обычной схеме: поместить в свойство DataSource ссылку на набор данных и в обработчике Page_Load вызвать его метод DataBind, В следующем примере (файл Chl2\RepeaterDemo\WebForml,aspx) элемент выводит три поля таблицы Authors базы данных Pubs (демонстрационная БД, поставляемая с сервером MS SQL Server). Окно программы показано на рис. 12.6.
Стандартные элементы для работы с базами данных 413
Ошибк^ сервера 込 у.}нсс*®гмм ;/^(?рс?агегГ)сгпо1'.
Ошибка компиляции
Стро«а 14 :Clpjr.n 15:52" 1,: e▼…IRiСтро«а 14 :Clpjr.n 15:52" 1,: e▼…IRi□писание; 0»>4гв гфм »ctowi*iw< ресурс», rpefivoMoto дпо овся/**»«<|« >тога млрсса Иiv^rre en»Ay<9iv<*подровгм с*«я»«н<о ЦвтаА ивмАкамкшмпе*cmj|wa вщ Сооб—енне об ошмбк» киниипаюра: CSD' 13 ТЗ^гт Wct> □ WebLartrnb Нерыаег|«пп bfUteffi'oeoiM^tT 'cicActio*.шцв ашчи^я "матч* □ ■мбк* нсгочммк*:
Стро«а 14 :
Clpjr.n 15:
52" 1,: e▼…IRi
Стро«а 14 :
Clpjr.n 15:
52" 1,: e▼…IRi
исмодпыЯ Фойл: с Wieii4*i|r-*wwioat**et*rtftl,w,"?'VveU wul “о* Стро»»: 1Е
CtWi*»,mjа^Щ|««№ cifi^Hbie и*|*мс ПЖПКЯИ1ШЖ
01Р§ва・・гь попмый HcrcAJg им J2 AtfwmftMw
информация а версии: плагзрма м^гман rcT rfm«*<u>. »яра>я 1,”?? 20k ASPECT. 1 вся,i 14 82 2033
Рис. 12.5. Сообщение отладчикаРис. 12.5. Сообщение отладчикаФ311ЛПравка Вид убранное Cepwc £праека3 W 图、R «рм!唱 http://kxaiho5t/RepeaterC>emo/WebFc/ml.espxФ311ЛПравка Вид убранное Cepwc £праека3 W 图、R «рм!唱 http://kxaiho5t/RepeaterC>emo/WebFc/ml.espx
Рис. 12.5. Сообщение отладчика
Рис. 12.5. Сообщение отладчика
Ф311Л
Правка Вид убранное Cepwc £праека
3 W 图、R «рм
!唱 http://kxaiho5t/RepeaterC>emo/WebFc/ml.espx
Ф311Л
Правка Вид убранное Cepwc £праека
3 W 图、R «рм
!唱 http://kxaiho5t/RepeaterC>emo/WebFc/ml.espx
Демонстрация элемента Repeater
First Name:Last NamePhoneJohnsonWhite408 496-7223•: Maijone:Green:415 986-7020 jCherylCarson^415 548-7723 :Michael;O'Leary.408 286-2428 j■ Duan;Straight^15 834-2919 ;■ MeanderSmith込13 543-0462 :.Abraham:Benriet;415 658-9932 |Й.Г?тсео ..First Name:Last NamePhoneJohnsonWhite408 496-7223•: Maijone:Green:415 986-7020 jCherylCarson^415 548-7723 :Michael;O'Leary.408 286-2428 j■ Duan;Straight^15 834-2919 ;■ MeanderSmith込13 543-0462 :.Abraham:Benriet;415 658-9932 |Й.Г?тсео ..
First Name
:Last Name
Phone
Johnson
White
408 496-7223
•: Maijone
:Green
:415 986-7020 j
Cheryl
Carson
^415 548-7723 :
Michael
;O'Leary
.408 286-2428 j
■ Duan
;Straight
^15 834-2919 ;
■ Meander
Smith
込13 543-0462 :
.Abraham
:Benriet
;415 658-9932 |
Й.Г?тсео ..
First Name
:Last Name
Phone
Johnson
White
408 496-7223
•: Maijone
:Green
:415 986-7020 j
Cheryl
Carson
^415 548-7723 :
Michael
;O'Leary
.408 286-2428 j
■ Duan
;Straight
^15 834-2919 ;
■ Meander
Smith
込13 543-0462 :
.Abraham
:Benriet
;415 658-9932 |
Й.Г?тсео ..
В отличие от щ)угих элементов» для элемента Repeater практически весь следующий текст приходится набирать вручную:
<%@ Import namespace="System.Data.SqlClient"%>
<html>
<head>
<tltle>RepeaterTable.aspx</tltle>
<scrlpt langu3^e=MVB" runat="Server * >
Sub Page一Load
Dim conPubs As SqlConnection
Dim cmdSelect As SqlCommand
Dim dtrAuthors As SqWataReader
conPubs = New SqlConnection ( **Server=localhost;" &_
BUID=sa;PWD=123;Database=Pube,')
cmdSelect = New SqlCommand ( ** Select * From Authors", conPubs ) conPubs.Open()
dtrAuthors = cmdSelect.ExecuteReader()
rptAuthors.DataSource = dtrAuthors
rptAuthors.DataBind()
dtrAuthors・ Close()
conPubs.Close()
End Sub
</8Orlpt>
</head>
<body>
<£om runats "Server • >
<Ы>Демонстрация элемента Repeater</hl>
<asp:Repeater id=n rptAuthors" runat="Server">
<HeaderTeinpl&te>
<table border="1" cellpadding=•4и >
<tr bgcolor="yellow">
<th>First Name</th>
<th>Last Name</th>
<th>Phone< / th>
</tr>
</HeaderTexqplate>
<ltemTexqplate>
<tr>
<td><%# Container. Dataltem ( "au_fname" ) %>
</td>
<td><%# Container.Dataltem( Bau_lname" ) %>
</td>
<td><%# Container.Dataltem( "phone" ) %>
</td>
</tr>
</ItemTemplate>
<AltematingltemTemplate>
<tr bgcolor = "ye 1 low •* >
<tdx%# Container.Dataltem ( "au^^fname" ) %>
</td>
<td><%# Container.Dataltem( "au^lname" ) %>
</td>
<td><%# Container.Dataltem( "phone** ) %>
</td>
</tr>
</AltematingItemTenqplate>
<Foot еЛелф1 ate>
</table>
</FooterTenqplate>
</asp:Repeater>
</form>
</body>
</html>
В обработчике Page_Load данные привязываются к элементу динамически. Сначала создается соединение conAuthors класса SqlConnection — в строке соединения указаны пользователь sa и пароль 123 (как указать нужный пароль, описано в разделе <Работа с транзакциями* главы 4). Затем создается объект cmdSelect класса Sql Command, в который помещается запрос, выбирающий все записи из таблицы Authors. Наконец, создается объект dtrAuthors класса SglDataReader, который и устанавливается как источник данных для элемента rptAuthors.
Элемент DataList
Элемент DataList предназначен для вывода множества данных в виде списка. Подобно элементу Repeater, он имеет шаблоны, управляющие форматированием отдельных его частей. Таким образом, объем ручного кодирования в нем приблизительно такой же} как и в случае элемента Repeater. В отличие от последнего, он имеет множество свойств оформительского характера, позволяющих указать заголовок, шрифт, цвет, наличие разделительных линий и т. д.
В следующем примере (файл Chl2\DataUstDenw\WebForml.aspx) в элементе DataList выводится содержимое поля Title таблицы Titles из БД Pubs (рис. 12.7).
Как и в примере RepeaterDemo.aspx, практически весь следующий текст нужно набирать вручную:
<%@ Import namespace=яSystem.Data.SqlClientи%>
<htnl>
<head>
<script language=nVBH runat= " Server '* >
Sub Page_Load
Dim conPubs As SqlConnection
Dim cmdSelect As SqlCommand
Dim dtrTitles As SqlDataRea^er
史айл Оавка 恥 фбрамюе Сашк Справка.龎
◎3 . » ®就&仍m,☆i(《«' @改斑圜、□緻咨[:〕 fgKqj^httpy/locdhort/DataUstDemoMebFofmLaspx.;;:;—]一… Ц^|;В^ПерехоА &ыл;н:”
工sFriendly?
Computer Phobiu AND Non-Phobiu Individuals: Reh&viQr Variations
Cooking with Computers: Surreptitious Ba工&nue Sheets
Emotiona工 Security: A New Algorithm
Fifty Ye&rs in 日uukingham P&lau❷ Kituh❷ns Anger the Enemy?
LiE❷ Uithout Fe&r
Net Etiquette
Onions, Leeks, and Garlic: Cooking Seurets o£ the Meditert&ne&n
Prolonged Data Deprivation; Four Cas❷ Stud工❷自 Secrets Silicon V&lley
Silicon Vali❷号tronomiu Treats Straight Talk About Computers
Sushi, Anyone?
The Busy Ex❷uutive's D&t&b&s❷ Guide
The Gourmet Miurow&v❷
The PsyuhologyComput❷r Cooking
You C&n Combat Computer Btressl
Рис. 12.7. Демонстрация элемента DataList
conPubs = New SqlConnection( "Server=localhost;UlD=sa;" &_
"PWD=123;Database=Pubsw )
cmdSelect = New SqlCoinmand{ "Select Title From Titles", conPubs ) conPubs.Open()
dtrTitles = cmdSelect.ExecuteReader()
dlstTitles.Datasource = dtrTitles
dlstTitles.DataBind()
dtrTitles.Close() conPubs.Close() End Sub script> </head>
vbody ms_posit ioning=nGridLayout">
<foxm runat = "server4 >
<asp:DataList id=,1 dlstTitles" style=HZ-INDEX: 1; LEFT: 14px; POSITION: absolute; TOP: 14px" runat=nservern caption=
"Демонстрация элемента DataList"
font-пал1ез=и Courier New" border style=** Sol id" borderwidth= "Ipx" bordercolor="Black" backcolor="#FFFF80" gridlines="Horizontal">
<1ЪехпТех!ф1аЪе><%# Container.DataItem( "Title") %>
</ltemTemplate>
</aspsDataList>
</form>
</body>
</html>
Поскольку обработчик Page_Load практически такой же, как н примере RepeaterDemo.aspx, я не буду его комментировать. Обратите внимание на многочисленные атрибуты тега определения элемента. Все они созданы в окне инспектора объектов на стадии редактирования формы — это безусловное достоинство элемента. Кроме того, у элемента в окне инспею'ора объектов определены свойства Headerstyle, ItemStyle, Alternating!temStyle м т. д„ которые дают доступ к соответствующим шаблонам и позволяют установить свойства шаблонов еще на этапе редактирования.
Элемент DataGrid
Элемент DataGrid предназначен для вывода данных из наборов данных или ХМЬ-фагаов в виде сетки. В отличие от рассмотренных ранее элементов Repeater и DataList, его умалчиваемые свойства таковы, что позволяют свести объем ручного кодирования к минимуму. В следующем примере (файл Ch 12\DataGridTаЫе\ WebForml.aspx) в сетке выводятся данные из таблицы BOOKS БД «Книголюб» (рис. 12.8).
шз
з ажм х Ммжи СК Симам
*^變•滋@窜炉2t¥-@&Si2・二黴♦鶉:
-М»ж-[ I Нир1/Яхй10«ДШяО1<П1ЫаЛ«М!Я>т|.мк處 jO<WH^
>'■ 4tn.UK* *■
Демонстрация элемента DataGrid
Сшссок iunm KiBOOKS
F a 汇 r;火*,:
^it'^ni^UiJISVI'T^l;.
F'. iJT 公**就
1
10 «шут ■■ У90Ж as Vocd 2000
Мтмн
3«Л»*КГ
1999
гое
5-в459-
<
2%44
42
46,2
2
10 КЖМП* я* урон eiudow М
•ултом
Джлвптюи
19W
256
5-в<59-
30
П
М,1В9
21
23, 1
3
10 кммут на урок.Освой оаиостошедьмо К9 Excel 20D0
•уятов
Вшлътс
1950
224
5-8459-
J2
:т
Z0.44
42
46.2
4
100 мжвомевчс» о Вше го вшиатчвммя 6м0ляот«км Delphi 5
Архмгелкстис*
Емком
1999
m
5-79*
X
1
40
40
44
S
1001 секрет рйметра vindo«» МТ
Дэшелс
Редмммя
199»
320
5-1502-
12
35
35,011
35
*0<5
6
12 уроков темкмаа■ Сшшй лвстушшй самоучхтеяь для вс«х
Яичук
Терр*~Сворт
L9”
3。
93127-
во
6
10
”
15,4
13 тмгсв к усшху мхм практически* вомчи мя Смотре жютжчъ карьер* в
Пошпчхяхкв
1999
91
5-9496'
SO
39
q
6
6,6
8
ХСсНухрмтермл.Сакаучмтчль.Вкражх
7.5 ■ 7.7 в вопросах к ответах
КОМЯРНН
Тр”Ф
1999
400
5-
6
23
131.25
190
209
3—00,6亠
,二.电ЙЙМ"^Й&發後蕊泳歯
14 Зак. 449
После размещения на форме компонентов BdpConnec t i on, BdpDataAdapter, DataSet и их настройки (см. раздел <Простой пример») был создан следующий обработчик события Load
procedure TWebForml.Page一Load(sender: System.Object;
e: System.EventArgs);
begin
DataGridl.DataBind;
end;
Все оформительские свойства элемента доступны в окне инспектора объектов и позволяют придать данным нужный вид еще на этапе редактирования.
Источником данных может быть XML-файл. В этом случае следует воспользоваться методом DataSet. ReadXML:
ixqplementation
uses System.IO; // В этом пространстве имен определен класс
// StreaznHeader
procedure TWebForml.Page_Load(sender: System.Object;
e: System.EventArgs);
// Загружает XML-файл в НД и связывает его с сеткой var
SR: StreamReader;
DV: DataView;
FileName: String;
begin
DataSetl.Tables.Clear;
FileName := Server.MapPath('books.xml•);
// Очищаем ВД
// Полное имя файла
SR := StreamReader.Create(FileName);
// Создаем поток
DataSetl.ReadXML(SR);
// Читаем данные в ВД
SR.Close;
〃 Закрываем поток
DV := DataView.Create(DataSetl.Tables[0]);
// Создаем
DataGridl.DataSource := DV;
// представление // Связываем его
DataGridl.DataBind;
// с элементом
end;
Встроенный объект Server (этот объект есть в каждом приложении ASP.NET) имеет метод MapPath, который возвращает полный маршрут доступа к указанному файлу по его имени при условии, что файл располагается в одной из обслуживаемых сервером папок. Если при обращении к методу указана пустая строка» он возвращает полный маршрут доступа к приложению ASP.NET.
Сетка DataGrid может сортировать публикуемые данные по отдельным столбцам. Для этого в ее свойство AllowSorting нужно поместить значение True. В результате заголовки столбцов будут оформлены как гиперссылки, а щелчок на заголовке вызовет событие SortCommcind, обработчику которого пер力щется имя столбца. На рис. 12.9 показано окно программы примера (файл О) 12\DataGridSort\WebFbrm 1 .aspx), в котором представлены книги из таблицы BOOKS, причем сетка позволяет сортировать книги по любому столбцу.
02 ・ 0 • .®.湎新户поиа禽宀》• 0 今協倒*岂修,生
2* i4b t^-tflcu^oet^eG^^ll^Fm .«px
Сортировка сетки DataGrid
В1Ш,№
;^М
Адмнвястративвое право
К0М8
1 BpeiO"。 нешвестие
河6 j
Аигло-руссхий бнзиес-словврь
Керолькемх
1 Временно мсязвестно
95.7 j
Арбитраж процесв
Ярков
1 Времевмо неювесгко
68,2 :
Банковское право России
Тосуняя
1 Временно нензвестио
753
Вшотные оиерацмм жоммбаяков
Сяпожвиков
1 Времевно неиэввство
37.4 j
Взыск>вве долгов и кримявал
Скобликов
1 Временно ионзвесггно
20.9
Всеобщая история гос-м в права
ЧерняловскО
1 Временно неизвестно
64,9
Рис. 12.9. Пример сортировки по столбцу BPubllsh
Для воспроизведения примера поместите на пустую форму элемент DataGrid и напишите такие строки кода:
type
TWebForml 二 class(System.Web.UI.Page)
private
procedure SortDataGrid(Column: String); f Private Declarations J
public
f Public Declarations }
end;
implementation
procedure TWebForml.Page_Load(sender: System.Object; e: System.EventArgs);
/ / Сортирует книги no названию в момент загрузки страницы begin
if not TsPostBack then
SortDataGrid(* BName');
end;
procedure TWebForml.DataGridl_SortCommand(source: System.Object; e: System.Web.UI.WebControls.DataGridSortCommandEventArgs);
// Сортирует книги по забранному столбцу
begin
SortDataGrid(e.SortExpression);
end;
procedure TWebForml> SortDataGrid(Column: String); / / Реализует сортировку книг
Con: BdpConnect i on;
Cmd: BdpCommand;
begin
// Создаем соединение с БД:
Con := BdpConnection.Create(1assembly=Borland.Data.Interbase, 1 +
* Version=2.0.0.0, Culture=neutral,'十
'PublicKeyToken=91d62ebb5b0dlblb;' +
'vendorclient=gds32.dll;1 +
1database=localhost:C:\BiblData\IB_BIBL.gdb;' +
'provider=lnterbase;username=sysdba;password=masterkey');
// Создаем объект-команду;
Cmd := BDPCommand.Create(* Select BName, BAuthor, BPublish, ' +
'BRozn From Books Order By 1 + Column,'BRozn From Books Order By 1 + Column,Con.Open;Con.Open;DataGridl.Datasource := Cmd.ExecuteReader; //DataGridl.Datasource := Cmd.ExecuteReader; //DataGridl.DataBind;Con.Close;DataGridl.DataBind;Con.Close;// //// //Con);Открываем Считываем Связываем ЗакрываемCon);Открываем Считываем Связываем Закрываемсоединение данные данныесоединениесоединение данные данныесоединение
'BRozn From Books Order By 1 + Column,
'BRozn From Books Order By 1 + Column,
Con.Open;
Con.Open;
DataGridl.Datasource := Cmd.ExecuteReader; //
DataGridl.Datasource := Cmd.ExecuteReader; //
DataGridl.DataBind;
Con.Close;
DataGridl.DataBind;
Con.Close;
// //
// //
Con);
Открываем Считываем Связываем Закрываем
Con);
Открываем Считываем Связываем Закрываем
соединение данные данные
соединение
соединение данные данные
соединение
end;
Сетка может содержать столбцы разных типов» в том числе:
е BoundColumn — обычный столбец для отображения данных;
HyperLinkcolumn — вывод записей в виде гиперссылок;
е TemplateColumn — вывод записей с форматированием по шаблону;
ButtonColumn — вывод записей в виде кнопок;
е EditConwnandColumn — вывод команд редактирования Edit, Update и Cancel. По умолчанию элемент DataGrid выводит все столбцы набора данных в формате Boundcolumn. Но если в свойство AutoGenerateColumns поместить значение False, столбцы можно создавать вручную, что дает разработчику более полный контроль над видом элемента.
Отключать автоматическое создание столбцов и добавлять вручную столбцы BoundColumn можно в том случае, когда не все поля НД нуждаются в опубликовании. Если, например, использовать стандартный прием перетаскивания на веб-страницу таблицы BOOKS, в НД появятся все поля этой таблицы. Однако для прайс-листа многие из них не нужны. В этом случае в свойство AutoGenerateColumns следует поместить значение False и щелчком на кнопке в свойстве Columns вы* звать окно редактора столбцов (рис. 12.10).
С помощью редактора можно выбрать тип столбца и указать его заголовок. На рис. 12.10 показан процесс формирования первого столбца прайс-листа. В строке Выражение форматир. данных можно ввести регулярное выражение, определяющее формат выводимых данных. В частности, символы {0:с} предписывают выводить вещественные числа в денежном формате. Эти символы используются для форматирования данных в поле BRozn. Окно с прайс-листом показано на рис. 12.11 (файл Chl2\DataGridColumn\WebForml.aspx).
г: i общий:.
■■ ■ ■ ' ■F ^мкивагь столбцы аетомогически во время вьлалнения
^Пострани*^ проа^ Досп^ные столбцы.
%;中 срмк;『. 田 Грмцы
电 Столбец привязки
;+ Столбец кнопки' §] Отрока гиперссылки福 Строка шаблона
.BourtdCokimn ссоАств: :^-:••……
■ Т ексг &ep2fHBro колойтигм
;•他звание
Выбранные столбцы: .ГИ Назыкйв..
Т вкст цижк^о копонгигулд
Г^ЙДвййяк</:
駛(毎沏比惠вер杵《м колонгипр!
|BNanw
ВырвжаниеФорЁртмр. «айнь*:
. Г* Только чгегае
• Взажение.сортирое^ ,
j^™™^ :^' 8.ью/нв.акр®1:.
门£№哂冲《裨 е»,тот ciioii6eu 息 стилбеи шаб/
Рис. 12.10. Окно редактора столбцов
£йя [рмка М Цюрмюа С^вмс yva»
4Е :通 bttp;,M4*«MVDat«&ldCckmi/Wei>FwEl .呻>
Ссниоп хккг
•:Qt^0<[:
Ц&эьаюш
Автор
-во
Цена
10 ммиут нм урок MS Vocd 2000
Мтхен
Зил»яме
《6,20р.
10 ммжут я* уронее
•ултои
Дкалектмкв
23, Юр.
!□ текут на урок.Освой самоста*тельна as Exuel 2QOD
*ултаи
В ИЛ* ЯНС
46,ZOp -
100 компепемггав сРивего жазшченха бибшилем) belph' 5
Крх маг е ль а ямА
Бм№К
44.DUp.
1001 секрет рмстра sindowa NT
Дэниеле
Руссг.вд Релакшы
60,5cp.
12 уроков те ккмеа. Caxml лоетушшй с*ка учите ль л ля всех
Чмчук
Террл-Сгорт
15,4Dp.
13 шагов п успеху кш првхтмчеенке совет ккк быстро хоитичь пор»срм
Полмтехкхп.
6,60p.
1СЕвухгалтсрмл.Сямоучкталк.Версхм 1.S м Т.7 ・ мопрос«х м ответам
Канягнн
Триулф
Z09,00s-
,D Studio НАХ г.S спр・аоч・мк
Паров
Пит«р
66,gp.
3D Studio RAX 3 .Уч*бх>пй курс + CB-ROH
Яйроа
Пмтвр
t * $,SOp.
30 Scudl。НАХ R3 .Спксгэффектм м л»Ш(и + CD-ROM
ДмчЛенткпа
143,70p.
,。Studio НАХ.Вкутгскккй мхр.Том 2 + СВ-RON
Зспмншя-Эгмляр
Дм.СофТ
16SrMp.
зь Studio Max 3.0 ат обмятв до квкмаакм + CB-ROff
Кулагми
ВНУ-Саигт-Пет«рв>т>г
110,ocp.
600 хауковмх м мутмк«лъкмх программ
КММХИ.КН
8НУ-Саккт-Петербург
ез.лор.
Э8 вопросов по Vindcvo 98 с отаетакя
4"Qnu・
Сопок
7ft, IQp .
Access 2000 для полъ?омтелн.Руомфмамрсжпмял версив
UauBRo
»HV-K*ifcs
93,5Qp.
Хссеяэ 97.Руководство по иккроязыку м УВА ♦ CD-рои
Но&аллс
пари
187,DOj:.
lecess 97.Энцкклопедмл папь,обатекп ♦ СЬ-РСЕ
Пва*н
ПмаСофТ
215, ODj:.
IdkinietceEing SQL Server 7. Сертмфхкшиюкпсй вманен-зкетернем (70-
「•Мус
Питер
•U,5Bp.
甘^bw^tMTj^TTM
城区*
422 Глава 12 • Работа с базами данных
Вставка столбца с гиперссылками помогает отобразить таблицы, связанные реляционным отношением главная—детальная. В этом случае гиперссылки размещаются в главной таблице и содержат URL-адрес страницы для отображения детальной таблицы. Проект Chl2\DataGridMastDet\DataGridMastDet.dpr создает два окна, показанных на рис. 12.12 и 12.13.
Главная таблицаГлавная таблицаПИЖЛЛ ;<OW^-.ПИЖЛЛ ;<OW^-.£««* ttw« Ока Фбсмме Семик Сгамак*◎ а ' <0 3 昼心户 м -<^ид»«в ®・£««* ttw« Ока Фбсмме Семик Сгамак*◎ а ' <0 3 昼心户 м -<^ид»«в ®・5<Л> фаш fru фбрмм <^в»с Ctmu о図激心 #4队,;^} http:/jbx«*KMtiDttt«&KM*rtDot/Merf<i -мрт5<Л> фаш fru фбрмм <^в»с Ctmu о図激心 #4队,;^} http:/jbx«*KMtiDttt«&KM*rtDot/Merf<i -мрт七,йg,:./:gw^№^в幾二?^^^11□1.О3.1ОООТсчгл■ Соцх&яъмкй укпвсрсжтетПраяшса н& рввлхзшш550,ООр-Спнсом01.Q3.2OODЯноаерПреямка с прелонлатойJ33.920.Спхсокэ01.03.2000ИКС ОООПродан* н« ре&лмзаиж0.75Q5 337,58.Cn¥F"□1.03.2000Д£СС-П*блмивр1Пркход по оОнсяу6 762,Ойр-5□1.03.3000Роэшсчкы продажаЛрояша с лрелоплвтой1,04234,00р.Сшкок6Di.os.sooaТочка. КГИЭИйрояаха и* реадмхшиоо1.Х2 328.70р.Спж^>м701.03.1000ООО Изамтакитво "Яплвдж"Постам* и* реелмзацмо1*55 $1О,ООР.смел□ 1.О3.2О&О-□poa«unnOауояаха к* реализацшВ, 75Z 757,50р.二?Ж?mO1.O3-2QDGИЛМЕПродажа на реалмзаииюD. 75655,00р.С П5' G>1ю01.03.2OOUООО Имя-гфдьс-пю "НолЮЖ"Пост*»* к* реым9attMc1155 б10,00р>CCXGQN11QL.03.£0Q0ТП4УИ.Цродаха к* реалмзацкп3,1526 4«Q,00p.1201.03-2000КалмнмиМ“р・т ор<иш2 359,90р.:XWJRt13D1.O3.2DOOТржумф-кнккшя торговляПаетавхк к* реалмзашк6 4Г?,5”・r"nwr-/»wL4O1.D3.2DDDПродалит^кПролаем на рсадмзацжо,вв 149,60р.CjJMCOX1501.03.2000ИлмтяПролах。нв р**лмашиао0,вэ4 790,76р.';23316oi.oi.aoooПохпвмтсльяяя книгаПряхол пс обхеку122 г»5лЧ0р.1701.03.2C0C"0 Центр мвфсрмкшмжшх технолог^Проявка ш р*«лм>ииоо□,вз2 319.02р.1В01.03.2000Ро.хячикд пред ежаПродажа с прыоплвто*1,С472!ВОр.Ггткса?1Qni.. m ・2ftcinРпчямыняа npnnirr*ГТпе»»*»* С ЯП*ПППЯ!»ЧУ1в,,п«Ггаиня»七,йg,:./:gw^№^в幾二?^^^11□1.О3.1ОООТсчгл■ Соцх&яъмкй укпвсрсжтетПраяшса н& рввлхзшш550,ООр-Спнсом01.Q3.2OODЯноаерПреямка с прелонлатойJ33.920.Спхсокэ01.03.2000ИКС ОООПродан* н« ре&лмзаиж0.75Q5 337,58.Cn¥F"□1.03.2000Д£СС-П*блмивр1Пркход по оОнсяу6 762,Ойр-5□1.03.3000Роэшсчкы продажаЛрояша с лрелоплвтой1,04234,00р.Сшкок6Di.os.sooaТочка. КГИЭИйрояаха и* реадмхшиоо1.Х2 328.70р.Спж^>м701.03.1000ООО Изамтакитво "Яплвдж"Постам* и* реелмзацмо1*55 $1О,ООР.смел□ 1.О3.2О&О-□poa«unnOауояаха к* реализацшВ, 75Z 757,50р.二?Ж?mO1.O3-2QDGИЛМЕПродажа на реалмзаииюD. 75655,00р.С П5' G>1ю01.03.2OOUООО Имя-гфдьс-пю "НолЮЖ"Пост*»* к* реым9attMc1155 б10,00р>CCXGQN11QL.03.£0Q0ТП4УИ.Цродаха к* реалмзацкп3,1526 4«Q,00p.1201.03-2000КалмнмиМ“р・т ор<иш2 359,90р.:XWJRt13D1.O3.2DOOТржумф-кнккшя торговляПаетавхк к* реалмзашк6 4Г?,5”・r"nwr-/»wL4O1.D3.2DDDПродалит^кПролаем на рсадмзацжо,вв 149,60р.CjJMCOX1501.03.2000ИлмтяПролах。нв р**лмашиао0,вэ4 790,76р.';23316oi.oi.aoooПохпвмтсльяяя книгаПряхол пс обхеку122 г»5лЧ0р.1701.03.2C0C"0 Центр мвфсрмкшмжшх технолог^Проявка ш р*«лм>ииоо□,вз2 319.02р.1В01.03.2000Ро.хячикд пред ежаПродажа с прыоплвто*1,С472!ВОр.Ггткса?1Qni.. m ・2ftcinРпчямыняа npnnirr*ГТпе»»*»* С ЯП*ПППЯ!»ЧУ1в,,п«Ггаиня»Рис. 12.12. Главная таблицаРис. 12.12. Главная таблица
Главная таблица
Главная таблица
ПИЖЛЛ ;<OW^-.
ПИЖЛЛ ;<OW^-.
£««* ttw« Ока Фбсмме Семик Сгамак*
◎ а ' <0 3 昼心户 м -<^ид»«в ®・
£««* ttw« Ока Фбсмме Семик Сгамак*
◎ а ' <0 3 昼心户 м -<^ид»«в ®・
5<Л> фаш fru фбрмм <^в»с Ctmu о図激心 #4队,;^} http:/jbx«*KMtiDttt«&KM*rtDot/Merf<i -мрт
5<Л> фаш fru фбрмм <^в»с Ctmu о図激心 #4队,;^} http:/jbx«*KMtiDttt«&KM*rtDot/Merf<i -мрт
七,й
g,
:./:gw^
№^в
幾二?^^^1
1
□1.О3.1ООО
Тсчгл■ Соцх&яъмкй укпвсрсжтет
Праяшса н& рввлхзшш
550,ООр-
Спнсом
01.Q3.2OOD
Яноаер
Преямка с прелонлатой
J33.920.
Спхсок
э
01.03.2000
ИКС ООО
Продан* н« ре&лмзаиж
0.75
Q5 337,58.
Cn¥F"
□1.03.2000
Д£СС-П*блмивр1
Пркход по оОнсяу
6 762,Ойр-
5
□1.03.3000
Роэшсчкы продажа
Лрояша с лрелоплвтой
1,04
234,00р.
Сшкок
6
Di.os.sooa
Точка. КГИЭИ
йрояаха и* реадмхшиоо
1.Х
2 328.70р.
Спж^>м
7
01.03.1000
ООО Изамтакитво "Яплвдж"
Постам* и* реелмзацмо
1
*55 $1О,ООР.
смел
□ 1.О3.2О&О-
□poa«unnO
ауояаха к* реализацш
В, 75
Z 757,50р.
二?Ж?m
O1.O3-2QDG
ИЛМЕ
Продажа на реалмзаиию
D. 75
655,00р.
С П5' G>1
ю
01.03.2OOU
ООО Имя-гфдьс-пю "НолЮЖ"
Пост*»* к* реым9attMc
1
155 б10,00р>
CCXGQN
11
QL.03.£0Q0
ТП4УИ.
Цродаха к* реалмзацкп
3,15
26 4«Q,00p.
12
01.03-2000
Калмнми
М“р・т ор<иш
2 359,90р.
:XWJRt
13
D1.O3.2DOO
Тржумф-кнккшя торговля
Паетавхк к* реалмзашк
6 4Г?,5”・
r"nwr-/»w
L4
O1.D3.2DDD
Продалит^к
Пролаем на рсадмзацж
о,в
в 149,60р.
CjJMCOX
15
01.03.2000
Илмтя
Пролах。нв р**лмашиао
0,вэ
4 790,76р.
';233
16
oi.oi.aooo
Похпвмтсльяяя книга
Пряхол пс обхеку
1
22 г»5лЧ0р.
17
01.03.2C0C
"0 Центр мвфсрмкшмжшх технолог^
Проявка ш р*«лм>ииоо
□,вз
2 319.02р.
1В
01.03.2000
Ро.хячикд пред ежа
Продажа с прыоплвто*
1,С4
72!ВОр.
Ггткса?
1Q
ni.. m ・2ftcin
Рпчямыняа npnnirr*
ГТпе»»*»* С ЯП*ПППЯ!»ЧУ1в
,,п«
Ггаиня»
七,й
g,
:./:gw^
№^в
幾二?^^^1
1
□1.О3.1ООО
Тсчгл■ Соцх&яъмкй укпвсрсжтет
Праяшса н& рввлхзшш
550,ООр-
Спнсом
01.Q3.2OOD
Яноаер
Преямка с прелонлатой
J33.920.
Спхсок
э
01.03.2000
ИКС ООО
Продан* н« ре&лмзаиж
0.75
Q5 337,58.
Cn¥F"
□1.03.2000
Д£СС-П*блмивр1
Пркход по оОнсяу
6 762,Ойр-
5
□1.03.3000
Роэшсчкы продажа
Лрояша с лрелоплвтой
1,04
234,00р.
Сшкок
6
Di.os.sooa
Точка. КГИЭИ
йрояаха и* реадмхшиоо
1.Х
2 328.70р.
Спж^>м
7
01.03.1000
ООО Изамтакитво "Яплвдж"
Постам* и* реелмзацмо
1
*55 $1О,ООР.
смел
□ 1.О3.2О&О-
□poa«unnO
ауояаха к* реализацш
В, 75
Z 757,50р.
二?Ж?m
O1.O3-2QDG
ИЛМЕ
Продажа на реалмзаиию
D. 75
655,00р.
С П5' G>1
ю
01.03.2OOU
ООО Имя-гфдьс-пю "НолЮЖ"
Пост*»* к* реым9attMc
1
155 б10,00р>
CCXGQN
11
QL.03.£0Q0
ТП4УИ.
Цродаха к* реалмзацкп
3,15
26 4«Q,00p.
12
01.03-2000
Калмнми
М“р・т ор<иш
2 359,90р.
:XWJRt
13
D1.O3.2DOO
Тржумф-кнккшя торговля
Паетавхк к* реалмзашк
6 4Г?,5”・
r"nwr-/»w
L4
O1.D3.2DDD
Продалит^к
Пролаем на рсадмзацж
о,в
в 149,60р.
CjJMCOX
15
01.03.2000
Илмтя
Пролах。нв р**лмашиао
0,вэ
4 790,76р.
';233
16
oi.oi.aooo
Похпвмтсльяяя книга
Пряхол пс обхеку
1
22 г»5лЧ0р.
17
01.03.2C0C
"0 Центр мвфсрмкшмжшх технолог^
Проявка ш р*«лм>ииоо
□,вз
2 319.02р.
1В
01.03.2000
Ро.хячикд пред ежа
Продажа с прыоплвто*
1,С4
72!ВОр.
Ггткса?
1Q
ni.. m ・2ftcin
Рпчямыняа npnnirr*
ГТпе»»*»* С ЯП*ПППЯ!»ЧУ1в
,,п«
Ггаиня»
Рис. 12.12. Главная таблица
Рис. 12.12. Главная таблица
Детальная таблица
Кннш ПФ К8КЯЯДЯ0Й JA16
;A*TQg
МмЁв・*О“
•学:注*.出
Internee .Сак-ли бммлосо чшЬшка
Эуев
Лабохторм бмошск дмакя*
Х4
?明g卩,
Поиное руисевяства по КЗ Вindovs 9В
Тмхаясь
Л«бсф«тормя безоПИХ эж*кх*
М.СЮр.
Учкксм раБотвтъ на компывтере.Сакй/чхтепь длл детей м родителей
*ролоа
Л»борв-гормя баз。》* ,м*кк*
32,00р.
Млюишстрмромяие сети ИЗ vindoite КТ 4.0.Дла еамостоятелькеЯ пол готовя
Русскм РыакПКД
]0
104,00р.
Злентронвгпетмт-Оенйвкме э ало ли
Крохоа
Х2ор・тормл бзоамх ・тххЯ
4й,оар<
Ocrqim патохиимм. УчеБнмк лля тлкпнлеюп ВУЗов
ЭЛБИ
*6
104,00р.
De Iphi, Томио^тм прпгряхммрпмнмя
Кучеренко
Поэк&мтельмял нкмгх
56
22.40о,
Нехаммка, Оеповше >акокм
Нроао»
Л*бор«тормя базоешх зпвяяй
14
40,00>
CoreiDRIB 9.Рукеволство полквователл с ершмракм м упрахкенмммх
Петров
Лаборатормд Оазоямх якшоей
70
120,00р.
CorelDRAP 9.0.дучом・ с яучпмх
Варашш
Пвзк«лател»м*л кши>а+
4a
Зб.оар.
Оп*р・пмоннал инекх。ИЗ Ulndnwa 98 ЛЕ
Леонтьев
ПвтммтсАъи” ямкга+
48
40,00;-
ЛсгсоийлъимА хомямугср . Лрогряжж>е сб«слеч«м>м
Яврмовв
Потниате4к" тлел»
72
20,00?-
На рис, 12,12 показана таблица NAKLS. Правая колонка сетки содержит гиперссылки такого рода (рис. 12.14):
De匸ails.aspx?naklid={0}
□ Общий :.□ Общий :.)53 Столбцы :飞 包 Пистр»гмйй лросм._* Формат tg Гра«щы)53 Столбцы :飞 包 Пистр»гмйй лросм._* Формат tg Гра«щыГ" £оздамть столбцы автомвтичесхм во время выю/ммаГ" £оздамть столбцы автомвтичесхм во время выю/ммаСписок столбцовДу^>у^п^ьс,匸厂 □ TName± S1 Столбец кнопкиСписок столбцовДу^>у^п^ьс,匸厂 □ TName± S1 Столбец кнопкиЬ4$р»«1Ь№ Столбцу <?. ':-Ь4$р»«1Ь№ Столбцу <?. ':-雷 Стрсжа гиперссылки j^;<J3国工:雷 Стрсжа гиперссылки j^;<J3国工:Ням^№>1итпсво^^Ням^№>1итпсво^^¥*b caP№w'O колонтитула:¥*b caP№w'O колонтитула:|книги по нам|книги по нам:л.:л.^ЭОбра* В WP»WM RCwWHTMTyi^ЭОбра* В WP»WM RCwWHTMTyiTfiW,TfiW,|Слисок^^йкегововтлес|Слисок^^йкегововтлес『$*рП^国QPMggjeKgra;二『$*рП^国QPMggjeKgra;二^фесап^фесапm Коэфф園 Cg4aS3 Книги пойаклm Коэфф園 Cg4aS3 Книги пойаклTygr 1яжнуо кйлрнгигала'Tygr 1яжнуо кйлрнгигала'§百p我丽*ейпгироёки:W:• : •;干■ :,「• • ■厂Tff®"三:砂.用酬皿前蜘:§百p我丽*ейпгироёки:W:• : •;干■ :,「• • ■厂Tff®"三:砂.用酬皿前蜘:йапеияи::■'"2 f 砌 63Строка Фб(^гирам№ю UR\|Dei2kaspx?TH^йапеияи::■'"2 f 砌 63Строка Фб(^гирам№ю UR\|Dei2kaspx?TH^
□ Общий :.
□ Общий :.
)53 Столбцы :飞 包 Пистр»гмйй лросм._
* Формат tg Гра«щы
)53 Столбцы :飞 包 Пистр»гмйй лросм._
* Формат tg Гра«щы
Г" £оздамть столбцы автомвтичесхм во время выю/мма
Г" £оздамть столбцы автомвтичесхм во время выю/мма
Список столбцов
Ду^>у^п^ьс,匸
厂 □ TName
± S1 Столбец кнопки
Список столбцов
Ду^>у^п^ьс,匸
厂 □ TName
± S1 Столбец кнопки
Ь4$р»«1Ь№ Столбцу <?. ':-
Ь4$р»«1Ь№ Столбцу <?. ':-
雷 Стрсжа гиперссылки j^;
<J3国工:
雷 Стрсжа гиперссылки j^;
<J3国工:
Ням^№>1итпсво^^
Ням^№>1итпсво^^
¥*b caP№w'O колонтитула:
¥*b caP№w'O колонтитула:
|книги по нам
|книги по нам
:л.
:л.
^ЭОбра* В WP»WM RCwWHTMTyi
^ЭОбра* В WP»WM RCwWHTMTyi
TfiW,
TfiW,
|Слисок
^^йкегововтлес
|Слисок
^^йкегововтлес
『$*рП^国QPMggjeKgra;二
『$*рП^国QPMggjeKgra;二
^фесап
^фесап
m Коэфф
園 Cg4a
S3 Книги пойакл
m Коэфф
園 Cg4a
S3 Книги пойакл
Tygr 1яжнуо кйлрнгигала'
Tygr 1яжнуо кйлрнгигала'
§百p我丽*ейпгироёки:W:• : •;干■ :,「• • ■
厂Tff®"三:砂.用酬皿前蜘:
§百p我丽*ейпгироёки:W:• : •;干■ :,「• • ■
厂Tff®"三:砂.用酬皿前蜘:
йапеияи::■'
"2 f 砌 63
Строка Фб(^гирам№ю UR
\|Dei2kaspx?TH^
йапеияи::■'
"2 f 砌 63
Строка Фб(^гирам№ю UR
\|Dei2kaspx?TH^
Птобмзо1мгтьзтог сп?лб«11/здб 岡业証 J
OK } Отмену I %f e I Оправка f
Рис. 12.14. Назначение гиперссылки
ПРИМЕЧАНИЕ
Столбцы типов, отличных от BoundColumnet доступны в окне редактора столбцов ниже узла (возможно, пустого) Столбец привязки.
В этой гиперссылке перед знаком вопроса указана веб-страница, предназначенная для отображения детальных данных, а после знака вопроса — передаваемые eii данные. Эти данные задаются именем (naklid) и значением {0}. Такая строка форматрования означает, что в качестве значения будет передаваться значение поля, выбранного в списке Поле URL. Обработчик Page_Load стран и цы Detailse.aspx имеет такой вид:
procedure TWebForm2.Page_Load(sender: System.Object; e: System.EventArgs); begin
Label1.Text :二'Книги по накладной №' +
Request.QueryString.Item[0];
424 Глава 12 • Работа с базами данных
BdpCommandl.CommandText :二'SELECT BNAME, BAUTHOR, BPublish, ' + 'MQUAN, MPRICE FROM MOVES, BOOKS WHERE MBOOK=BOOKID ' +
* and NAKLID=' + Request.Querystring.ItemlO];
BdpConnectionl.Open;
DataGridl.Datasource := BdpCommandl.ExecuteReader;
DataGridl.DataBind;
BdpConnectionl.Close;
end;
Замечу, что в форме Details.aspx используются элемент BdpConnectionl, настроенный на связь с БД «Книголюб», никак не настроенный элемент BdpCommandl и сетка DataGridl. Свойство Querystring . Item объекта Request открывает доступ к параметрам запроса, а первый и единственный параметр Item[0] содержит интересующий нас параметр NakllD.
В ряде случаев над данными нужной строки сетки требуется выполнить некоторые действия. Этому может способствовать столбец с кнопками, оформленными в виде гиперссылок. Щелчок на кнопке вызывает событие ItemChanged, обработчику которого передаются в объекте е класса DataGridEvent Args два важных параметра: строка CommandName, идентифицирующая нажатую кнопку, и объект Item, содержащий исчерпывающую информацию □ строке сетки. В проекте Chl2\DataGridBtn\DataGrigBtn.dpr представлена программа, которая содержит два столбца кнопок (рис. 12.15).
◎3-0凶曲心:户2费Mr« 1.;电 http7/lout<0tt/[MaGfltfitnA#e№irmk◎3-0凶曲心:户2费Mr« 1.;电 http7/lout<0tt/[MaGfltfitnA#e№irmkВставка в сетку кнопокВставка в сетку кнопок)0 минут н» урок,8gx иамоитожтеллво ИЗ £x“j :亚и 1QQ конпоисптов общего мазмачепмл Окблмотежм Delphi S 1001 секрет реестра UindoYw NTурахпе теккксв.Саижй копчусшмЯ самаучмтел* алл хекпаго» к успеху нлк практичеехме совет и*к Бистро воетичь карьеры вICiБухгалтерия.Самоучитель.берекк 7.5 и 7.1 в вопрос&х и ответах血;式認卜:лй^落】g:Ьйййййй…: : '犷室飯|赫:皿瘍;炳询ее + К> П» 3eud,O RJLX. R3 ,спацэффек0 ・ Л・,ыЬ| + CD-ROR 3D Studio КАХ.Влутрекммй нмр.Том 2 + CD-RCMJ)0 минут н» урок,8gx иамоитожтеллво ИЗ £x“j :亚и 1QQ конпоисптов общего мазмачепмл Окблмотежм Delphi S 1001 секрет реестра UindoYw NTурахпе теккксв.Саижй копчусшмЯ самаучмтел* алл хекпаго» к успеху нлк практичеехме совет и*к Бистро воетичь карьеры вICiБухгалтерия.Самоучитель.берекк 7.5 и 7.1 в вопрос&х и ответах血;式認卜:лй^落】g:Ьйййййй…: : '犷室飯|赫:皿瘍;炳询ее + К> П» 3eud,O RJLX. R3 ,спацэффек0 ・ Л・,ыЬ| + CD-ROR 3D Studio КАХ.Влутрекммй нмр.Том 2 + CD-RCMJТрмумфТрмумф209,ООр,209,ООр,|<t、jii^y*学.,森*...».;*《& 4iMKi 10.' g 沖:血i: 9#ПГ': wilpiew#;##|<t、jii^y*学.,森*...».;*《& 4iMKi 10.' g 沖:血i: 9#ПГ': wilpiew#;##.!!£^ :ми»;.!!£^ :ми»;60,5Dp.25,40р「60,5Dp.25,40р「АржакгельспийДэниелаАржакгельспийДэниелаЗстшоэа-Згмл&рЗстшоэа-Згмл&ркпмм#K二Т吋f:40二:': Вкльямскпмм#K二Т吋f:40二:': ВкльямсРуеемя Реаакцмп Террк-СпортРуеемя Реаакцмп Террк-СпортНхядектмх* ДмаСоТНхядектмх* ДмаСоТРис. 12.15. Сетка с кнопкамиРис. 12.15. Сетка с кнопкамиПслмтвхнкмПслмтвхнкм也2А』Н也2А』НIGS.OOp. "d*IGS.OOp. "d*
◎3-0凶曲心:户2费
Mr« 1.;电 http7/lout<0tt/[MaGfltfitnA#e№irmk
◎3-0凶曲心:户2费
Mr« 1.;电 http7/lout<0tt/[MaGfltfitnA#e№irmk
Вставка в сетку кнопок
Вставка в сетку кнопок
)0 минут н» урок,8gx иамоитожтеллво ИЗ £x“j :亚и 1QQ конпоисптов общего мазмачепмл Окблмотежм Delphi S 1001 секрет реестра UindoYw NT
урахпе теккксв.Саижй копчусшмЯ самаучмтел* алл хек
паго» к успеху нлк практичеехме совет и*к Бистро воетичь карьеры в
ICiБухгалтерия.Самоучитель.берекк 7.5 и 7.1 в вопрос&х и ответах
血;式認卜:лй^落】g:Ьйййййй…: : '
犷室飯|赫:皿瘍;炳询ее + К> П» 3eud,O RJLX. R3 ,спацэффек0 ・ Л・,ыЬ| + CD-ROR
3D Studio КАХ.Влутрекммй нмр.Том 2 + CD-RCMJ
)0 минут н» урок,8gx иамоитожтеллво ИЗ £x“j :亚и 1QQ конпоисптов общего мазмачепмл Окблмотежм Delphi S 1001 секрет реестра UindoYw NT
урахпе теккксв.Саижй копчусшмЯ самаучмтел* алл хек
паго» к успеху нлк практичеехме совет и*к Бистро воетичь карьеры в
ICiБухгалтерия.Самоучитель.берекк 7.5 и 7.1 в вопрос&х и ответах
血;式認卜:лй^落】g:Ьйййййй…: : '
犷室飯|赫:皿瘍;炳询ее + К> П» 3eud,O RJLX. R3 ,спацэффек0 ・ Л・,ыЬ| + CD-ROR
3D Studio КАХ.Влутрекммй нмр.Том 2 + CD-RCMJ
Трмумф
Трмумф
209,ООр,
209,ООр,
|<t、jii^y*学.,森*...».;*《& 4iMKi 10.' g 沖:血i: 9#ПГ': wilpiew#;##
|<t、jii^y*学.,森*...».;*《& 4iMKi 10.' g 沖:血i: 9#ПГ': wilpiew#;##
.!!£^ :ми»;
.!!£^ :ми»;
60,5Dp.
25,40р「
60,5Dp.
25,40р「
Аржакгельспий
Дэниела
Аржакгельспий
Дэниела
Зстшоэа-Згмл&р
Зстшоэа-Згмл&р
кпмм
#K二Т吋f:40二:': Вкльямс
кпмм
#K二Т吋f:40二:': Вкльямс
Руеемя Реаакцмп Террк-Спорт
Руеемя Реаакцмп Террк-Спорт
Нхядектмх* ДмаСоТ
Нхядектмх* ДмаСоТ
Рис. 12.15. Сетка с кнопками
Рис. 12.15. Сетка с кнопками
Пслмтвхнкм
Пслмтвхнкм
也2А』Н
也2А』Н
IGS.OOp. "d*
IGS.OOp. "d*
Щелчок на кнопке Выбрать выделяет ряд фоновым цветом и выводит текст в нем полужирным шрифтом. Щелчок на кнопке Отменить отменяет выделение. Все действия решшзует такой обработчик:
procedure TWebForml. DataGridl」匸emCommanci (source: System.Obj ect; e: System.Web.UI.WebControls.DataGridCommandEventArgs);
Стандартные элементы для работы с базами данных 425
begin
if е.CommandName 二'Выбрать' then
begin
e.Item.BackColor :二 System.Drawing.Color.LightGreen;
e.Item.Font.Bold := True
end else begin
e.Item.BackColor :丁 System.Drawing.Color.White;
e.Item.Font.Bold := False
end
end;
Свойство Comm-andName определяется содержимым поля Имя команды в окне редактора колонок элемента DanaGrid (рис. 12.16).
厂 £оэд«мггь столбщн «цтомвтически ва время вып^анфнш厂 £оэд«мггь столбщн «цтомвтически ва время вып^анфншiDO&iwft j 53 Столбцы ¥ 包 Посгражчный 1*4 Формэт ,由 Гра^шЫ :iDO&iwft j 53 Столбцы ¥ 包 Посгражчный 1*4 Формэт ,由 Гра^шЫ :j : £>эдеок сголбцое -гросм,":』рсгупнь« столбимj : £>эдеок сголбцое -гросм,":』рсгупнь« столбим£ S Столбец кнопки 尼".;:: :.、.Я Выбор、叶■出 Правка, Обновил;; ^" t£ S Столбец кнопки 尼".;:: :.、.Я Выбор、叶■出 Правка, Обновил;; ^" tВь^анные столбцы:ЕЗ ЦенаВь^анные столбцы:ЕЗ Цена■ И Удалить■ И УдалитьXI ОтменитьXI Отменить
厂 £оэд«мггь столбщн «цтомвтически ва время вып^анфнш
厂 £оэд«мггь столбщн «цтомвтически ва время вып^анфнш
iDO&iwft j 53 Столбцы ¥ 包 Посгражчный 1*4 Формэт ,由 Гра^шЫ :
iDO&iwft j 53 Столбцы ¥ 包 Посгражчный 1*4 Формэт ,由 Гра^шЫ :
j : £>эдеок сголбцое -гросм,":』рсгупнь« столбим
j : £>эдеок сголбцое -гросм,":』рсгупнь« столбим
£ S Столбец кнопки 尼".;:: :.、.
Я Выбор、叶
■出 Правка, Обновил;; ^" t
£ S Столбец кнопки 尼".;:: :.、.
Я Выбор、叶
■出 Правка, Обновил;; ^" t
Вь^анные столбцы:
ЕЗ Цена
Вь^анные столбцы:
ЕЗ Цена
■ И Удалить
■ И Удалить
XI Отменить
XI Отменить
Butt{MVColut¥inСВОЙСТВТек^ве₽1^оК0лонп<г9ла:Butt{MVColut¥inСВОЙСТВТек^ве₽1^оК0лонп<г9ла::Teikcr £tu)u4^o колбнгитэла::Teikcr £tu)u4^o колбнгитэла:
Butt{MVColut¥inСВОЙСТВ
Тек^ве₽1^оК0лонп<г9ла:
Butt{MVColut¥inСВОЙСТВ
Тек^ве₽1^оК0лонп<г9ла:
:Teikcr £tu)u4^o колбнгитэла:
:Teikcr £tu)u4^o колбнгитэла:
旌占阳颱沦еу>*мколокгигуп旌占阳颱沦еу>*мколокгигупДйВХМ^е? сфг 吟 киДйВХМ^е? сфг 吟 ки{ВыбратьТекст^оеполе:{ВыбратьТекст^оеполе::Има-коматьс::Има-коматьс:三| Р Выл млакран三| Р Выл млакранОтрока 空ормвкф. текВ^ ; ;*Отрока 空ормвкф. текВ^ ; ;*|Еы 而 ат;Тйп 绘ктс|ur*Buiton**~|Еы 而 ат;Тйп 绘ктс|ur*Buiton**~33EkEkггАтсп; ргрс物ijs сгорай талонаггАтсп; ргрс物ijs сгорай талонаококртмаиа I ^ - ^I Справкартмаиа I ^ - ^I Справка
旌占阳颱沦еу>*мколокгигуп
旌占阳颱沦еу>*мколокгигуп
ДйВХМ^е? сфг 吟 ки
ДйВХМ^е? сфг 吟 ки
{Выбрать
Текст^оеполе:
{Выбрать
Текст^оеполе:
:Има-коматьс:
:Има-коматьс:
三| Р Выл млакран
三| Р Выл млакран
Отрока 空ормвкф. текВ^ ; ;*
Отрока 空ормвкф. текВ^ ; ;*
|Еы 而 ат;
Тйп 绘ктс|ur*Buiton**~
|Еы 而 ат;
Тйп 绘ктс|ur*Buiton**~
3
3
Ek
Ek
ггАтсп; ргрс物ijs сгорай талона
ггАтсп; ргрс物ijs сгорай талона
ок
ок
ртмаиа I ^ - ^I Справка
ртмаиа I ^ - ^I Справка
Рис. 12.16. Определение имени связанной с кнопкой команды
Наконец, элемент DataGri d нс только может отображать данные, но и позволяет их редактировать. Для этого в состав его столбцов следует включить столбец с кнопками (гиперссылками) Правка, Обновить и Отмена. Следует отметить, что 9TH кнопки (проект Chl2\DataGridEdit\DataGridEditdpr) предоставляют лишь необходимые интерфейсные средства, но не осуществляют изменения в исходном наборе данных (рис. 12.17).
Ф0ил Правка % Иэбранное Сероне Справка驚
卷На…0•国君腌;戶吟☆йзби ®合” 2圖"GJ " A®&V j蛰 h*):“loEx)g/pataGridEdqwebForELaspx •^用‘附^飙飞气吧!「:;
Вставка кнопок редактирования
購
T”ir:,雜l话ЙЙН。羨哆乐
0
^Поставка на реализацию^
Обновить Отмена
1
Продажа на реализацию
Правка
2
Возврат поставки
Правка
3
Возврат продажи
Правка
4
Приход по обмену
Правка
5
Уход по обмену
Правка
6
Поставка с предоплатой
Правк旦
7
Продажа с предоплатой
Правка
Рис. 12.17. Редактирование данных
При щелчке на кнопке Правка набор данных переводится в режим редактирования н появляются кнопки Обновить и Отмена. Щелчок на кнопке Правка порождает событие EditCommand, обработчик которого получает имя кнопки и номер строки, в которой произошел щелчок на кнопке. В нашем примере обработчик просто переводит строку в состояние редактирования:
procedure TWebForml.Page_Load(sender: System.Object; e: System.EventArgs};
// Реализует начальное связывание данных begin
if not IsPostBack then
DataGridDataBind;
end;
procedure TWebForml.DataGridDataBind;
// Получает л связывает данные var
Cmd: BdpCommand;
begin
// Создаем команду (элемент BdpConnecti ол1 присоединен к проекту // на этале конструирования формы л связан с БД л Книголюбм/: Cmd :二 BdpCominand. Create (
'SELECT * FROM TYPES', BdpConnectionlf NIL);
// Открываем соединение〃 Читаем данные// Связываем данные// Закрываем соединение// Открываем соединение〃 Читаем данные// Связываем данные// Закрываем соединениеBdpConnectionl.Open;
// Открываем соединение
〃 Читаем данные
// Связываем данные
// Закрываем соединение
// Открываем соединение
〃 Читаем данные
// Связываем данные
// Закрываем соединение
DataGridl.DataSource := Cmd.ExecuteReader;
DataGridl.DataBind;
BdpConnectionl.Close;
•nd;
procedure TWebForml.DataGridleEditCommand(source: System.Object;
e: System.Web.UI.WebControls«DataGridCommandEventArgs);
// Щелчок на кнопке "Правка"
begin
DataGridl.Editltemlndex := e.Item.Itemindex; // Переводим строку
DataGridDataBind;// в режим
// редактирования end;
Для действительного изменения данных или для отказа от изменении предусмотрены связанные с элементом события Cancel Command и UpdateCommcind, которые возникают при щелчках на кнопках Отмена к Обновить соответственно:
procedure TWebForml. DataGr idl_UpdateContmand (source : System. Obj ect ; e : System.Web. UI.WebControls. DataGridCommandEventArgs);
// Подтверждает изменения (кнопка "Обновить"). Ключевое поле TypelD
Н не может изменяться (оно только для чтения)
var
ТВ: TextBox;
Cmd: BdpCommand;
ID, Name: Btxrlng;
begin
ID := e.item.Itemlndex.ToString;// Значение ключевого поля
ТВ := е.Item.Cells[1J «Controls[0] as TextBox; // Элемент
// редактирования
Name := ТВ.Text;H Новый текст поля TMame
// Создаем команду изменения значения:Cmd := BdpCommand.Create(* UPDATE TYPES SET TNAME= *'1 + Name +// Создаем команду изменения значения:Cmd := BdpCommand.Create(* UPDATE TYPES SET TNAME= *'1 + Name +—WHERE TYPEID= * + ID,—WHERE TYPEID= * + ID,BdpConnectionl.Open;IICmd・ ExecuteNonQuery;//BdpConnectionl.Close;〃DataGridl.Editltemlndex := -1; // //BdpConnectionl.Open;IICmd・ ExecuteNonQuery;//BdpConnectionl.Close;〃DataGridl.Editltemlndex := -1; // //Открываем Выполняем ЗакрываемОткрываем Выполняем ЗакрываемBdpConnectionl, NXL); соединение изменение соединениеBdpConnectionl, NXL); соединение изменение соединениеDataGridDataBind; end;DataGridDataBind; end;Прекращаем редактирование строкиПрекращаем редактирование строки
// Создаем команду изменения значения:
Cmd := BdpCommand.Create(* UPDATE TYPES SET TNAME= *'1 + Name +
// Создаем команду изменения значения:
Cmd := BdpCommand.Create(* UPDATE TYPES SET TNAME= *'1 + Name +
—WHERE TYPEID= * + ID,
—WHERE TYPEID= * + ID,
BdpConnectionl.Open;II
Cmd・ ExecuteNonQuery;//
BdpConnectionl.Close;〃
DataGridl.Editltemlndex := -1; // //
BdpConnectionl.Open;II
Cmd・ ExecuteNonQuery;//
BdpConnectionl.Close;〃
DataGridl.Editltemlndex := -1; // //
Открываем Выполняем Закрываем
Открываем Выполняем Закрываем
BdpConnectionl, NXL); соединение изменение соединение
BdpConnectionl, NXL); соединение изменение соединение
DataGridDataBind; end;
DataGridDataBind; end;
Прекращаем редактирование строки
Прекращаем редактирование строки
procedure TWebForml.DataGridl_CancelCommand(source: System.Object; e: System.Web•UI.WebControls.DataGridCommandEventArgв);
/ / Щелчок на кнопке "Отмена ”
begin
DataGridl.Editltemlndex := -1;// Отменяем редактирование строки
DataGridDataBind;
end;
Элементы категории DB Web
Разработчики Delphi дополнили стандартные компоненты для работы с базами данных новыми, которые существенно упрощают доступ к данным и не требуют от программиста дополнительных усилий на ручное кодирование aspx-файлов. По сравнению со стандартными элементами они имеют следующие преимущества:
не требуют связывания данных методом DataBind;
представляют данные на этапе редактирования формы;
автоматически подтверждают изменения в данных;
дают средства навигации по набору данных.
Элемент DBWebDataSource
Элемент DBWebDataSource играет ту же роль, что и компонент TDataSource в VCL-приложениях. Он является клапаном, через который остальные компоненты категории DB Web получают доступ к данным. В дополнение к этому своему основному назначению элемент осуществляет привязку данных методом DataBinding к обслуживаемым им элементам отображения данных (DBWebGrid, DBWebLabel, DBWeblmage и т. п.).
В табл. 12.1 представлены некоторые свойства элемента.
Таблица 12.1. Свойства элемента DBWebDataSource
Свойство
Описание
property AutoRefresh: Boolean;
Если содержит False (по умолчанию), данные обновляются только по требованию клиента( в противном случае — когда загружается страница
property Aut oUpda t eCashe : Boolean;
Если содержит False (по умолчанию), измененные данные записываются в XML-файл только в обработчике события On Арр 1у С h ang е s t в противном случае — при каждом изменении (при этом свойство UseUniquiFileName игнорируется)
property CascadingDeletes:
CscadingDeleteOptions;
Определяет изменение таблиц главная—детальная (см. далее)
property CascadingUpdates:
CascadingUpdateOptions;
Определяет возможность изменения внешнего ключа в таблицах плавная—детальная (см. далее)
property DataSource: Object;
Содержит ссылку на набор данных
property ErrorOption:
ErrorHtmlOptions;
Определяет обработку ошибок (см. далее)
property UseUniqueFileName: Boolean;
Если содержит True, при записи ХМL-файла будет создаваться уникальное имя
СвойствоОписание
property XMLFileName: string; Имя читаемого или записываемого файла XML property XCQShemaFile; String; Имя файла, содержащего схему XML-файла
Свойство CascadingDeletes определяет реакцию на удаление записи в таблицах главная—детальная и может принимать одно из следующих значений:
NoMas terDelete (по умолчанию) — запрещает удаление записи главной таблицы. Это значение устанавливается, когда сервер накладывает на главную таблицу ограничение внешнего ключа. В этом случае пользователь должен самостоятельно удалить ненужные записи детальной таблицы и подтвердить удаление с помощью, например, метода BdpDe t ai 1 Adapt er. Au t oUpda t e, затем удалить запись в главной таблице и подтвердить изменение с помощью метода BdpMasterAdapter. AutoUpdate;
ServerCascadeDelete — устанавливается, когда сервер настроен на поддержку каскадных удалений. В этом случае до подтверждения изменений пользователь может отменить удаление, и при этом восстанавливаются главная запись и все связанные с ней детальные записи. Если сервер не поддерживает каскадные изменения, детальные записи сохранятся после уничтожения главной записи;
ServerNoForeignKey — устанавливается, когда сервер не накладывает на главную таблицу ограничение внешнего ключа. В этом случае уничтожение главной записи вызывает автоматическое уничтожение всех связанных с ней детальных записей. Если до подтверждения изменений пользователь отменит удаление, главная и детальная таблицы восстанавливают свой первоначальный ввд. Если на главную таблицу наложено ограничение внешнего ключа, это значение при уничтожении главной записи вызовет ошибку.
Свойство Cascadingupdates определяет возможность каскадных изменений внешнего ключа в таблицах главная—детальная и может принимать одно из следующих значений:
NoMasterUpdate (по умолчанию) — запрещает изменение ключевого поля главной таблицы;
ServerCascadeUpdate — устанавливается, когда сервер поддерживает каскадное изменение ключевого поля в записях детальной таблицы:
ServerNoForeignKey — разрешает изменение ключевого поля главной записи и автоматически корректирует ключевые поля в записях детальной таблицы. Это значение можно устанавливать только в том случае, когда сервер не накладывает на главную таблицу ограничения внешнего ключа.
Свойство Erroroption определяет реакцию на возникшую ошибку и может содержать одно из следующих значений:
logOnSamePage (по умолчанию) — сообщение об ошибке появляется на вебстранице;
logOnErrorPage — сообщение появляется на отдельной странице с кнопкой ОК;
logWithErrorEvent — сообщение не появляется, так как установлен обработчик события OnError.
Элемент DBWebDataSource может оперировать XML-файлами. При этом, если свойство XMLFileName содержит имя существующего файла, этот файл становится базовым источником данных для элемента. Если свойство содержит имя несуществующего файла, в момент загрузки страницы файл будет создан и наполнен данными из набора данных DataSet.
Элемент не имеет специфических методов. Его события перечислены в табл. 12.2.
Таблица 12.2. События элемента DBWebDataSource
Событие
Описание
property OnAfterSetChanges: WebContro1sEvent;
Возникает после подтверждения изменений
property OnApplyChangesRequest:
WenControlsEvent;
Возникает, когда пользователь требует подтверждения сделанных им изменений
property OnAut оApplyReques t: WebControlsEvent;
Возникает^ когда пользователь требует автоматического подтверждения делаемых им изменений
property OnError: OnErrorEvent;
Возникает при обнаружении ошибки в процессе обработки запроса. Обработчику передается список всех сообщений об ошибках и список всех предупреждающих сообщений
property OnGetPostCollecton: PostCollecionEvent;
Возникает перед получением изменений на странице клиента (см. далее)
property OnRefreshRequest: WebContro1sEvebt;
Возникает при необходимости обновить данные
property OnScroll: OnScrollEvent;
Некоторые компоненты (DBWebGrid, DBWeb- TextBox и DBWebListBox) поддерживают прокрутку данных. Объект класса OnScrollEvent содержит имя таблицы, текущую запись и запись, которая была текущей до прокрутки
Важную роль играет событие OnApplyChangesRequest, так как именно в обработчике этого события можно вызвать метод AutoUpdate адаптера BdpData- Adapter и, таким образом, подтвердить сделанные изменения. Метод имеет такую сигнатуру:
procedure AutoUpdate(DS: DataSet; TableNaiue: String;
DataMode: BdpDataMode);
Здесь DS — набор данных; Tab! eName — имя обновляемой таблицы; DataMode — параметр, определяющий обновляемые записи (АН — все записи; Changed — измененные записи; Key — записи с заданными значениями ключевого поля). Например:
BdpAdapterl.AutoUpdate(DataSetlr •TYPES *, BdpDataMode.All);
ПРИМЕЧАНИЕ
Только после определения обработчика OnApplyChangesRequist: становится доступной кнопка Apply в навигаторе DBWebNavigator.
Обработчик события OnGetPostCollection получает три параметра: sender — объект, возбудивший событие, е — объект класса PostCollectionEventArgs с параметрами, StopUpdate — логическая переменная. Класс PostCollectionEventArgs порожден от EventArgs и обогащает своего родителя членом PostCollection класса NameValueCollection.
Элемент DBWebNavigator
Элемент DBWebNavigator используется совместно с другими элементами, такими, например, как сетка, и обеспечивает удобные средства навигации по набору данных, а также операции обновления, подтверждения изменений (см. ранее), отмены изменений, вставки и удаления записи. Он от клапана DBDataSource, ссылку на который хранит его одноименное свойство, получает данные из НД, указанного в свойстве TableName.
Элемент имеет 10 (по количеству кнопок) пар свойств ХХХХви 11 on I с on типа String и XXXXButtonVisible типа Boolean. Первое определяет изображение на поверхности кнопки* а второе — наличие соответствующей кнопки в элементе. Свойство ButtonType указывает тип изображений на кнопках. Оно может иметь одно из следующих значений:
Buttonicons — на кнопках демонстрируются изображения, заданные в свойствах XXXXBut ton icon; для согласования размеров изображения и размеров кнопки следует использовать графические файлы в формате GIF;
ButtonSymbols (по умолчанию) — демонстрируются такие комбинации символов: |< (перейти к первой записи), « (к предыдущей записи), » (к следующей записи), >| (к последней записи), + (вставить запись), 一 (удалить текущую запись), [>] (подтвердить изменения), [<] (обновить данные), х (отменить последнее изменение), хх (отменить все изменения);
ButtonText — показываются надписи, поясняющие связанные с кнопкой действия (First, Pervious, Next, Last, Insert, Delete, Apply, Refresh, Undo, UndoAII).
На рис. 12.18 элемент показан в режиме But tonSymbols (верхний ряд кнопок) и ButtonText (нижний ряд кнопок).
Рис. 12.18. Иллюстрация свойства ButtonType
Элемент DBWebGrid
Элемент DBWebGrid предназначен для отображения данных в сетке (рис. 12.19).
謬2 - ◎•同阕謚ам ,£?*««. ®丛烛囱.“微猿"G知応匸 喲 http:Afacahost/DeWebGfa>effTO/WgbFBmLaspx財.ЕЗ・0у弊啤.""М1謬2 - ◎•同阕謚ам ,£?*««. ®丛烛囱.“微猿"G知応匸 喲 http:Afacahost/DeWebGfa>effTO/WgbFBmLaspx財.ЕЗ・0у弊啤.""М1
謬2 - ◎•同阕謚ам ,£?*««. ®丛烛囱.“微猿"
G知応匸 喲 http:Afacahost/DeWebGfa>effTO/WgbFBmLaspx財.ЕЗ・0у弊啤.""М1
謬2 - ◎•同阕謚ам ,£?*««. ®丛烛囱.“微猿"
G知応匸 喲 http:Afacahost/DeWebGfa>effTO/WgbFBmLaspx財.ЕЗ・0у弊啤.""М1
?.」.;• nТипн«<таднойo'Поставка на реализацию!Продежана реализацию2Возврат поставки3Возврат продажи4Приход по обмену5疚о& по обмену:6.(вставка с предоплатой7.Продажа с предоплатой?.」.;• nТипн«<таднойo'Поставка на реализацию!Продежана реализацию2Возврат поставки3Возврат продажи4Приход по обмену5疚о& по обмену:6.(вставка с предоплатой7.Продажа с предоплатойРис. 12.19. Демонстрация элемента DBWebGridРис. 12.19. Демонстрация элемента DBWebGridПРИМЕЧАНИЕ Для подтверждения сделанных изменений необходимо определить обработчик события OnApplyChangesRequist клапана DBWebDataSource (см. файл Ch 10\DBWebGridDemo\ WebForml.pas).ПРИМЕЧАНИЕ Для подтверждения сделанных изменений необходимо определить обработчик события OnApplyChangesRequist клапана DBWebDataSource (см. файл Ch 10\DBWebGridDemo\ WebForml.pas).
?.」.;• n
Типн«<тадной
o'
Поставка на реализацию!
Продежана реализацию
2
Возврат поставки
3
Возврат продажи
4
Приход по обмену
5
疚о& по обмену:
6.
(вставка с предоплатой
7.
Продажа с предоплатой
?.」.;• n
Типн«<тадной
o'
Поставка на реализацию!
Продежана реализацию
2
Возврат поставки
3
Возврат продажи
4
Приход по обмену
5
疚о& по обмену:
6.
(вставка с предоплатой
7.
Продажа с предоплатой
Рис. 12.19. Демонстрация элемента DBWebGrid
Рис. 12.19. Демонстрация элемента DBWebGrid
ПРИМЕЧАНИЕ
Для подтверждения сделанных изменений необходимо определить обработчик события OnApplyChangesRequist клапана DBWebDataSource (см. файл Ch 10\DBWebGridDemo\ WebForml.pas).
ПРИМЕЧАНИЕ
Для подтверждения сделанных изменений необходимо определить обработчик события OnApplyChangesRequist клапана DBWebDataSource (см. файл Ch 10\DBWebGridDemo\ WebForml.pas).
Демонстрация элемента DBWebGrid
Типн накпаднь!х
Вот пример обработчика:
procedure TWebForml.DBWebDataSourcel_OnApplyChangesRequest(
sender: System.Object; e: Borland.Data.Web.WebControlEventArgs); begin
BdpDataAdaprerl.AutoUpdate(dataSetl, 'TYPES’, BdpUpdateMode.All); end;
Обратите внимание: к моменту вызова метода AutoUpdate соединение с источником данных разорвано (это легко проверить, проанализировав свойство State соединения). Метод устанавливает соединение, обновляет данные и затем опять разрывает соединение.
Ключевыми свойствами элемента DBWebGrid являются DBWebDataSource и Tabi eName, в которые нужно поместить ссылки на компонент-клапан DBWeb- DataSource и отображаемый в сетке набор данных соответственно.
Элемент имеет множество свойств оформительского характера, позволяющих разнообразить вид отображаемых данных.
Большинство свойств элемента унаследовано от родительского класса DataGrid. Собственные свойства DBWebGrid представлены в табл. 12.3.
Таблица 1Z3. Свойства элемента DBWebGrid
Свойство
Описание
property AccessKey: String;
Определяет символ быстрого доступа к элементу (в сочетании с клавишей Alt)
property AllowPagging: Boolean;
Управляет разбиением данных на страницы (см. далее)
property DBDataSourse:
Содержит ссылку на элемент-клапан класса
IDBDataSourse;
DBWebDataSourse
property HandleColumnEvents:
Если содержит True (по умолчанию), собы-
Boolean;
тия OnEditCommand и OnCancelCommand обрабатываются автоматически
property HandlePaggingEvents:
Если содержит True (по умолчанию), событие
Boolean;
OnPagelndexChange обрабатывается автоматически
property Readonly: Boolean;
Если содержит True, элемент не может редактировать данные
property TableName: String;
Содержит имя отображаемой таблицы Data- Table
Если свойство AllowPagging содержит значение True, записи автоматически разбиваются на страницы, когда общее количество записей в наборе данных больше значения, указанного в свойстве PageSize. В противном случае свойство Pagesize игнорируется и выводятся все записи НД или то их количество, которое определяется свойством MaxRecords адаптера. Если установлено разбиение на страницы, внизу сетки появляются значки, щелчки на которых меняют отображаемую в сетке страницу данных.
Элемент имеет метод UpdatePagelndex, позволяющий управлять курсором таблицы.
Визуализирующие элементы
В категории DB Web собраны визуализирующие элементы, которые в функциональном плане повторяют обычные элементы категории Web Controls, но разработаны специально для визуализации баз данных. Их главная особенность заключается в том, что они обеспечивают привязку данных автоматически (эта привязка реализуется клапаном DBWebDataSource, с помощью которого элементы DBWebXXXX получают доступ к данным). Вторая особенность — предъявление данных не только на этапе прогона, но и на этапе конструирования формы.
Все визуализирующие элементы имеют свойства DBDataSource, TableName и ColumnNaine, в которые помещаются, соответственно, ссылка на клапан класса DBWebDataSource, имя таблицы и имя поля таблицы^ содержимое которого и визуализирует тот или иной элемент.
434 Глава 12 • Работа с базами данных
Интересной особенностью списочных элементов (DBWebListBox, DBWebDrop- DownList, DBWebRadioButtonList и т. п.) является их способность демонстрировать данные из так называемых подстановочных (lookup) полей. Подстановочными называются поля, содержащие ссылки на поля другах таблиц. Например, в таблице MOVES поле МВООК содержит номер записи из таблицы BOOKS, в которой определены все параметры книги (название, автор, издательство и т. д.). Для работы с подстановочными полями списочные элементы имеют свойства LookupTable» DataTextField и DataValueField: в первом указывается подстановочная таблица, во втором — поле, содержимое которого будет отображаться в элементе, третье определяет ключевое поле для связи с подстановочным.
ПРИМЕЧАНИЕ
Правильное отображение подстановочных полей гарантируется после установки так называемых пакетов обновления Delphi 2005 Architect (www.boriand.corn/downloads/registered/ download_delphi.html) объемом около 50 Мбайт.
В следующем примере (Chl2\DBWebG)ntrols\WebFornril.aspx) демонстрируется применение различных визуализирующих элементов для отображения данных из таблицы NAKLS (рис. 12.20).
файл Орама О^д фбрамим ^еис Орами
3&»4 -
学 О ^вР"»* (?ыл¥
*Х ; Накладная№ 7
ДатаПн Вт Ср Чт Пт С6 Вс|ДатаПн Вт Ср Чт Пт С6 Вс|Тип накладнойТип накладной28 29^2 36 7 8 9 1013 14 15 16 1720 21 22 23 2427 28 29 30 313 4 5 6 728 29^2 36 7 8 9 1013 14 15 16 1720 21 22 23 2427 28 29 30 313 4 5 6 77 511 П: IS豊■ 23守;7 511 П: IS豊■ 23守;©Поставка на реализацисо ОДродажа на реализацию Q Возврат поставки О Возврат продажи О Др вход по обмену ©Уход по обмену О Поставка с предоплатой О Продажа с предоплатой©Поставка на реализацисо ОДродажа на реализацию Q Возврат поставки О Возврат продажи О Др вход по обмену ©Уход по обмену О Поставка с предоплатой О Продажа с предоплатойПартнер[ООО Издательство "Поладу鼠Сумма;155610Партнер[ООО Издательство "Поладу鼠Сумма;155610Q пд.зтй -60201.652Q пд.зтй -60201.652
Дата
Пн Вт Ср Чт Пт С6 Вс|
Дата
Пн Вт Ср Чт Пт С6 Вс|
Тип накладной
Тип накладной
28 29^2 3
6 7 8 9 10
13 14 15 16 17
20 21 22 23 24
27 28 29 30 31
3 4 5 6 7
28 29^2 3
6 7 8 9 10
13 14 15 16 17
20 21 22 23 24
27 28 29 30 31
3 4 5 6 7
7 5
11 П: IS豊■ 23守;
7 5
11 П: IS豊■ 23守;
©Поставка на реализацисо ОДродажа на реализацию Q Возврат поставки О Возврат продажи О Др вход по обмену ©Уход по обмену О Поставка с предоплатой О Продажа с предоплатой
©Поставка на реализацисо ОДродажа на реализацию Q Возврат поставки О Возврат продажи О Др вход по обмену ©Уход по обмену О Поставка с предоплатой О Продажа с предоплатой
Партнер
[ООО Издательство "Поладу鼠
Сумма
;155610
Партнер
[ООО Издательство "Поладу鼠
Сумма
;155610
Q пд.зтй -60201.652
Q пд.зтй -60201.652
Рис. 12.20. Пример использования визуализирующих элементов
В примере используются невидимые на рисунке компоненты класса BdpData- Adapter для получения данных из главной (NAKLS) и двух подстановочных (TYPES и FIRMS) таблиц. Помимо трех адаптеров используются также невидимые
компоненты классов BdpConnection, DataSet и BdpDataSource. Свойства визуализирующих компонентов настроены следующим образом:
компонент DBWebNavigatorl:
о DBDataSource = DBWebDataSourcel;
о TabieName = NAKLS;
компонент DBWebLabell:
DBDataSource = DBWebDataSourcel;
Tabi eName = NAKLS;
ColumnName = NAKLID;
компонент DBWebCa 1 endarl:
о DBDataSource = DBWebDataSourcel;
о TableName = NAKLS;
о CclumnName = NDATE;
компонент DBWebRadioButtonListl:
DBDataSource = DBWebDataSourcel;
TableName = NAKLS;
ColumnName = NTYPE;
О LookupTable = TYPES;
DataTextField = TNAME;
DataValeuField = TYPEIP;
компон^т DBWebDtopDownlist 1:
DBDataSource = DBWebDataSourcel;
TableName = NAKLS;
ColumnName = NFIRM;
LookupTable 二 FIRMS;
Da t aText F i e Id = FNAME;
DataValeuField = FIRMID;
компонент DBWebTextBoxl:
о DBDataSource = DBWebDataSourcel;
о TableName = NAKLS;
о ColurnnName = NSUM;
компонент DBViebTextBox2:
о DBDataSource = DBWebDataSourcel;
О TableName = NAKLS;
O ColumnName = NPAEDSUM.
Веб-службы
Веб-службы представляют собой относительно новое явление в Интернете. Всемирная сеть в ее сегодняшнем виде основана на том, что пользователи посещают различные веб-страницы с помощью своих веб-браузеров. До недавнего времени единственным способом предоставления информации в Интернете являлось ее размещение на веб-странице, которую пользователи могли просматривать. Однако часто возникает необходимость получить по Сети доступ к удаленному программному обеспечению. Такой доступ и реализуется веб-спужбами. Как объявила корпорация Microsoft, с переходом на технологию .NET она решила сделать акцент не на разработке программного обеспечения, а на предоставлении программных услуг. При этом новый программный продукт предлагается на рынке в виде веб-службы. Таким образом, приложение сдастся в аренду, а от пользователя для его применения н обновления требуется постоянное подключение к Интернету.
Эта глава посвящена применению Delphi 2005 и платформы .NET для создания и использования веб-служб.
Создание веб-служб
Процедуру создания простой веб-службы продемонстрируем на основе заготовок, вставленных в файл службы в виде комментариев. Эта служба возвращает строку «Hello World!».
Создайте новую веб-службу. Для этого выберите команду File ► New ► Others и в узле Delphi for .NET Projects выберите значок ASP.NET Web Service Application (рис. 13.1). Назовите проект WSHelloWorld.
На странице WebServicel.pas раскомментируйте следующее объявление в разделе interface:
Создание веб-служб 437
//「
// Sample Web Service Me匚hod [WebMethod]
function HelloWorld: string;
//*;
end;
ItemC^egortes:ItemC^egortes:喲喲LbraryLbraryeePackagePackageConsole ApplicationConsole ApplicationDBWebControl LbraryDBWebControl LbraryECO ASP.NET Web Applk...ECO ASP.NET Web Applk...ECO ASP.NET Web Servic...ECO ASP.NET Web Servic...Cancel I Het> JCancel I Het> JSatellite AssemSatellite AssemfeWindowsFormsA...feWindowsFormsA...ЙVCL Forms AppHsHonЙVCL Forms AppHsHonECO WinForms ApplicationECO WinForms ApplicationРис. 13.1. Выбор значка ASP.NET Web Service ApplicationРис. 13.1. Выбор значка ASP.NET Web Service Applicationf二! C# Projects ■ Г'"! Crystal Reports Rtmaaphift^№r 什编器;■ £j Intraweb,匸 New ASP.NET Files:■ ^J New ECO Files ;1^7 New Files鼻匕 Delphi Projects:白 ActiveX'0 Business Ci Delphi Res'■ L™i Intraweb О WebBrokerj CN WebServices■亡 WebSnap;白 XMLB DeploymentCj Other Hies.€j IWtTestf二! C# Projects ■ Г'"! Crystal Reports Rtmaaphift^№r 什编器;■ £j Intraweb,匸 New ASP.NET Files:■ ^J New ECO Files ;1^7 New Files鼻匕 Delphi Projects:白 ActiveX'0 Business Ci Delphi Res'■ L™i Intraweb О WebBrokerj CN WebServices■亡 WebSnap;白 XMLB DeploymentCj Other Hies.€j IWtTestA5P.NET WebApplicationA5P.NET WebApplicationWeb Control LbraryWeb Control LbraryWhForm Contr...WhForm Contr...
ItemC^egortes:
ItemC^egortes:
喲
喲
Lbrary
Lbrary
e
e
Package
Package
Console Application
Console Application
DBWeb
Control Lbrary
DBWeb
Control Lbrary
ECO ASP.NET Web Applk...
ECO ASP.NET Web Applk...
ECO ASP.NET Web Servic...
ECO ASP.NET Web Servic...
Cancel I Het> J
Cancel I Het> J
Satellite Assem
Satellite Assem
fe
Windows
FormsA...
fe
Windows
FormsA...
Й
VCL Forms AppHsHon
Й
VCL Forms AppHsHon
ECO WinForms Application
ECO WinForms Application
Рис. 13.1. Выбор значка ASP.NET Web Service Application
Рис. 13.1. Выбор значка ASP.NET Web Service Application
f二! C# Projects ■ Г'"! Crystal Reports Rtmaaphift^№r 什编器
;■ £j Intraweb
,匸 New ASP.NET Files
:■ ^J New ECO Files ;1^7 New Files
鼻匕 Delphi Projects
:白 ActiveX
'0 Business Ci Delphi Res
'■ L™i Intraweb О WebBroker
j CN WebServices
■亡 WebSnap
;白 XML
B Deployment
Cj Other Hies
.€j IWtTest
f二! C# Projects ■ Г'"! Crystal Reports Rtmaaphift^№r 什编器
;■ £j Intraweb
,匸 New ASP.NET Files
:■ ^J New ECO Files ;1^7 New Files
鼻匕 Delphi Projects
:白 ActiveX
'0 Business Ci Delphi Res
'■ L™i Intraweb О WebBroker
j CN WebServices
■亡 WebSnap
;白 XML
B Deployment
Cj Other Hies
.€j IWtTest
A5P.NET WebApplication
A5P.NET WebApplication
Web Control Lbrary
Web Control Lbrary
WhForm Contr...
WhForm Contr...
На той же странице раскомментируйте такое объявление в разделе implementation:
// Sample Web Service Method
/ / The following method is provided
// to allow for testing a new web service.
//
function TWebServicel.HelioWorld: string;
begin
Result := * Hello World1;
end;
Откомпилируйте проект.
Наша простая веб-служба создана! К проекту добавлены файлы WebServicel.asmx, WebServicel.pas, bin\WSHelloWorld.dll. Последний, собственно, и содержит веб-службу в виде динамически загружаемой библиотеки.
Содержимое файла WebServicel.asmx показано в листинге 13.1.
Листинг 13.1. Файл WebServfcel.asmx
unit WebServicel;
Interface
uses
System.Collections, System.ComponentModel,
System. Data, Sy st on. Diagnostics # SystCTi.Web, System.Web • Services;
type
TWebServicel = olaas (Syst &n. web. Servi ces. WebService)
strict private
componentss IContainer;
procedure initializeComponent;
strict protected
procedure Dispose(disposing: boolean); override; private
{ Private Declarations / public
constructor Create;
// Пример метода веб-службы
[WebMethod]
Cunction HelloWorld: string; end;
inplenentation
constructor TWebServicel. Create ;
begin
inherited;
InitializeComponent;
end;
procedure TWebServicel.Dispose(disposing: boolean);
begin
i£ disposing and (components <> nil) then
components.Dispose;
iziherited Dispose (disposing); end;
// Дример реализации веб-метода
Cunction TWebServicel.HeiloWorld: string; begin
Result := 1 Hello World';
end;
end.
Класс TWebServicel происходит от 卽stem ・ Web. Services. WebService. Такое наследование обеспечивает доступ к таким популярным объектам, как Application,
Context, Session и т. д. Главное, что отличает этот класс от других, — наличие атрибута [WebMethod] перед объявлением метода HelioWorld в разделе implementation. Именно этот атрибут обеспечивает доступ к службе извне. При запросе URL-адреса веб-службы без параметров ASP.NET возвращает описание службы, как показано на рис. 13.2.
$айй Ом» g цмр«>м» См»нс очмк$айй Ом» g цмр«>м» См»нс очмк&竺、圍 http:/脈 rfW/W^<»loWcriaj>»«tiSfWHl,&竺、圍 http:/脈 rfW/W^<»loWcriaj>»«tiSfWHl,Полдвржнв«ютс« cneAvrauiMt ол«В*инн. Точное 0 npMее・ни・ махмнтет no upecy Опт акиг <11У*ЬыПолдвржнв«ютс« cneAvrauiMt ол«В*инн. Точное 0 npMее・ни・ махмнтет no upecy Опт акиг <11У*Ьы•超cUGKoritf•超cUGKoritfTWebServicelTWebServicel3tq *«&■ служба V х»чест»« п^апр&нста* нч«и rd унояч«иин)исполыуст ЬПр^//1»трит1.огч/.3tq *«&■ служба V х»чест»« п^апр&нста* нч«и rd унояч«иин)исполыуст ЬПр^//1»трит1.огч/.Р・хахем・и”*: Перед предастакланиеп общего доступ# к ■■б-службе XML измените пространство х“с* по умолчанию не другое прострмстао и・・м.Р・хахем・и”*: Перед предастакланиеп общего доступ# к ■■б-службе XML измените пространство х“с* по умолчанию не другое прострмстао и・・м.0 •浊® ^-P1^ 食,0 •浊® ^-P1^ 食,筷咨通S '筷咨通S '
$айй Ом» g цмр«>м» См»нс очмк
$айй Ом» g цмр«>м» См»нс очмк
&竺、圍 http:/脈 rfW/W^<»loWcriaj>»«tiSfWHl,
&竺、圍 http:/脈 rfW/W^<»loWcriaj>»«tiSfWHl,
Полдвржнв«ютс« cneAvrauiMt ол«В*инн. Точное 0 npMее・ни・ махмнтет no upecy Опт акиг <11У*Ьы
Полдвржнв«ютс« cneAvrauiMt ол«В*инн. Точное 0 npMее・ни・ махмнтет no upecy Опт акиг <11У*Ьы
•超cUGKoritf
•超cUGKoritf
TWebServicel
TWebServicel
3tq *«&■ служба V х»чест»« п^апр&нста* нч«и rd унояч«иин)исполыуст ЬПр^//1»трит1.огч/.
3tq *«&■ служба V х»чест»« п^апр&нста* нч«и rd унояч«иин)исполыуст ЬПр^//1»трит1.огч/.
Р・хахем・и”*: Перед предастакланиеп общего доступ# к ■■б-службе XML измените пространство х“с* по умолчанию не другое прострмстао и・・м.
Р・хахем・и”*: Перед предастакланиеп общего доступ# к ■■б-службе XML измените пространство х“с* по умолчанию не другое прострмстао и・・м.
0 •浊® ^-P1^ 食,
0 •浊® ^-P1^ 食,
筷咨通S '
筷咨通S '
Дп・ каждой вев^слтжбы XML тр*6убсе,нлк«л»нее прмтраиспо нк・н, «лоба кпк・нтск>1・ о^иложвилв отпичвлн,тг службу от других служб а с«е ВМ. Дла р・,р・6,»・・・ннх ваб-слтвв X ML доступно лоосп>*нст*о хх・к htfp:/Awnpun ого/, м“к。для опгбликссянмыа р«£-сл;аб KML АОПан© ислтъэйвйтъся болея ПОСТОЯННО» Простренспо ИПв».
веша ••б-сяумба XML доп«па мд«мтм*ицмро*аткся простр»»*ст»ои нкен, которое,онгролнвгет匸"В・к”. н・прн”,о, и・к и・с*ъ npcvctpME, кн・к “・・/ нсяалъ^оватъс* имя локон* Нмт・р”*т 8・з启 «нрка *от* многие прссгр^нствк пя>и ・е6-5рх6 XML выглядят как URl・3pac・,он» не обв1вгвл«по укиыммт “# реальны» р・сурсм в»б. (Првспиист»» нк0“ ««б-служб XML • это URIJ
Дпя в#б-сптжб ХМ1( ияавнмых с п«мош»ю ASP.NET, ч>остр««сг*а ккан по ,・олчаг»о сохка и»нвнит* с поиашмю c*oHcw« N«m»fp«c* ・три6гг・ wbServiee. Атрнфр wtbServic* ・oui”Actby,t м« xnaec, который амиржит ・・maz ■•О'слгхбы XML Нлхе прмевА«н пример км«, гснивьлнвагзшвп: npofHcno ииж *hg 〃m>6>,o%8rn/w・b,・rvic«,/*!
[«0S«cvice UtaaMinMMt«.占 w 〃喇 3。血 n. см/*«1»*к»1а«а/ " | j
public Ема*'»уяяМ*г«1с« I-: : л ::,.?:л...:::
〃 й**»*»**•
S3 б4,©#ет
.VZ8MW0*{ld0**・AS*f:."ntEMmaOM/XB**E*/E3»2aUrC3* M«MEg
CUM
Рис. 13.2. Результат обращения к веб-службе WSHelloWorld
Как видим, страница содержит название класса TWebServicel н перечень объявленных в нем методов веб-службы (в нашем примере — единственный метод HelloWorld). На остальной части страницы выводэтся информация о необходимости замены умалчиваемого пространства имен http://tempuri.org уникальным, отличающим ее от других одноименных служб в Сети (если, разумеется, служба будет опубликована в Интернете). В качестве пространства имен рекомендуется использовать домен вашей фирмы (или любое другое имя, обеспечивающее уникальность, — пространство имен не обязательно должно совпадать с реальным URL-адресом какого-либо сетевого ресурса). Для изменения пространства имен рекомендуется использовать свойство Namespace атрибута [WebService]. Этот атрибут должен предшествовать объявлению класса вебслужбы. Например:
[WebMethod(Namespace='http://MyFirm.ru/WebServices')J
WebServicel = class(System.Web.Services.WebService)
После щелчка на ссылке Описание службы в окне, показанном на рис. 13.1, появляется страница, представленная на рис. 13.3.
<?иги1 vers"*i口r 0,婚“0饰1=”""9・?А
<”£di;Sfinih3ij xmuw.bUp=,http;//bLht»inii*>.xtnh;Mnp.r>n;/w!.d1/tittp/" :.,%…г;.卜="h”p•丿八(Jwm»H xcMcap nrq/r?,dl,'”>《p/'
xm;,\; \^pt,ttp;//<.4V>w.v^ti.ury/2lrt?l/XMlAcbeina* xmi<:.i!':Lp'*^.-rbUp://4cht-fnn\.Hni:so&n.or>)/v;t.^p/i-;r:£ud1i4r;^"
/гМм ЛЛ“K〃ym|«"{,tHW :E;” <G=・Mtu:〃“Mcn“5t 仙a,/v**df/,川“i“tuxt便爪w;hh3‘
y»;”> -i--'-ia''ht!p://scli<iin-ai.j«»tlii!«p.urq/w»iil/mhnv/* t3rg*tN«iTiespac*f=''http://tBmpui1.Drg/'
-«*sc+%">d eEent9fitFDtmOe^uft**qualifle<r t«rgBtNamMp<*ceckhttp://tempurl.org/'>
-<5:tletv.oriT njmc='Hvn<»Wor1d*>
</f,H;,:3E,,
-<-s.tl«i>n?nt ndfTi&o'HelloWoridRVSponS8'>
<S't.L)mpldxTyp4>
■ ,з sequence»
・、F“《iQnt minOccurF='0, п'ал0сЕиг5«'1' rl4пw-''HollaWDгidRвкult', •ypt^'eiuiring1 />
*\->?чийпсел
■:/s:sch9fria:"
-message r>em(>ir'HalloWor1dS<Mp1nF>
n品pa八 L9"*='paremeters・廟RmHMB*tns:«naWodir >a
•,/*s<tl-rri₽5sa^e>
•■ iwEOi.neisagE nj-ne-rHenoWor1deoapOutT>
<*fcr p«rt njme=.'pvromatvrs' eleffwrtlolni:M»|)oWor1dRBspt>n»e, />
<A*rdl.mi»s$,gw>
-<wscl'pf)ff!vpft name^TWabServIcelSoep'^
-<ws,cJi'Ober jtiu<i *itrriu?*HvUoWorld'>
<wjdh input mc35age»Htns:HelloWDrtdBoepln' /';•
vwwl cufput ntastjg&^tnsMvIloWortdSoapout* />
</«-,<:[■ СгЛвГЙ»;ОП>
■ <-s6'A'indi.'ic ndine^'TWvbServIcellioap'1 tvDextnsrTWebSsrvicelBaop'-»
.".^J 一 二 £《:• .?rurnr.rc :@麻Р " ^^受g窑处一G以"".".^J 一 二 £《:• .?rurnr.rc :@麻Р " ^^受g窑处一G以""僚威:期淤寝嚎读底备:?僚威:期淤寝嚎读底备:?уррдигр tran&ptit=*http://sch«mes.xmlsQap.org/soap/hltp' sivi>i- docuntant' /
.".^J 一 二 £《:• .?rurnr.rc :@麻Р " ^^受g窑处一G以""
.".^J 一 二 £《:• .?rurnr.rc :@麻Р " ^^受g窑处一G以""
僚威:期淤寝嚎读底备:?
僚威:期淤寝嚎读底备:?
Рис 13.3. Описание службы на языке WSDL
Обратите внимание на URL-адрес этой страницы: в нем присутствуют символы ?WSDL, предписывающие вывести описание службы на языке WSDL (Web Services Description Language — язык описания веб-служб). Это описание необходимо различным инструментам (в том числе — IDE Delphi), способным автоматически создавать классы и интерфейсы.
Для проверки вновь созданной службы вернитесь на предыдущую страницу (см. рис. 13.2) и щелкните на ссылке HelioWorld. Появится окно, показанное на рис. 13.4. Щелчок на кнопке Вызвать этого окна приведет к появлению следующей страницы (рис. 13.5).
Обращение к службе, как это явствует из текста на странице, изображенной на рис. 13.4, осуществлялось по протоколу HTTP методом POST. Средства этого протокола позволяют обмениваться с веб-службой данными примитивных типов (строками, числами и т. п.). На этой странице также представлен пример запроса к службе, сделанного с помощью протокола SOAP (Simple Object Access Protocol — простой протокол доступа к объекту). Протокол SOAP использует средства языка ХМЬдля обмена с веб-службой данными любой сложности» в том числе данными пользовательских типов, двоичными файлами» наборами данных и т. п.
欝^^^蝇好津甦戀畸^歸耍您綾臓中壁冲望驟壁整里呼整鱒整麼簟學翼现灘 ©2Г/ & 点总.ja [,・а«. ?•沙;姦闻• Z 级壮Л :.
TWebServicel
Ana огобракен”!)оолкаго списка опеоаций ・ы4ермта <хМ_х:/牽V,.
HeiioWorid—"
npcvepKA
:Ana cpo»03«” pJO^Tfc, с нслоп>1О1||п11*н n;OTcroca нТГР POST нйатггв к”а<,кт 'Вмлап>
х”*о “”B%qg“ призер »опр“・ 'ьодр ” ““та нв него &»errs запос”・твсе* должны бмтъ пештале” фктнчцсхн* >х・и・гив.
POST /1IcUK^3«rvHTTVf.i.•
HO”; localho»t■'■
Cottt««-Typ»f »кс/ши utiarmei.ucJg
CsnZDALes^a: lMk«Ui :.
S^APAeblQflt "成3£"g事4£鼻““脚1h00上丄&"
»x»i узмоь^г.ь euee^&kFWF"*:
<csQB№tEQV01op«"x»lus:'Mi.**,bccpi'/Zw»v.tf3.t!iec/2ooi/XKI.i!ieht4*;:but*№:ew 绅InaimMf^*hccbtZ/H・.”3.、(№“N00i/:X)vi4ebe9^* xmihs:0
“ов|имйу» ■, : . ■ .\
<.HeIXfl№rid Xnloa>"http:^/tMtpuci.вс#?* ./> '
<Z*a«P:'tsVBlnpc*
Contanc.-'fypfli"t*xt/'№lj ch*c“Sii«£T.;.;三::I;::」;,’:.
CWt«亠也length ■-;
УвмД^д"*! .0* ftncodiags*UtC-e"?>
Рис. 13.4, Проверка веб-службы
:1 Файл Ставка gMA "браеое С^вис 5PMM馨
ja— ㈡ ⑨誼心:戶* 吟",j.@合 金"Mil瓷*
卜;ре.:: [&批険:,*>caflTO5t/W5Hg8oWodd/WebSerYlce l.asmx/HrfoWorld□кт* ** |i
; <?xml v?「3isn=№" Ancodirig='utf-M" ?>j
cstrmg пемт'ЬНрМ/гетриН.ПЕ/аАНеМо World</str«ng>j;
Рис, 13.5. Результат обращения к службе по протоколу HTTP POST
Атрибут [WebService]
Атрибут [WebService] может предшествовать объявлению класса веб-службы. Если он опущен, служба получает набор умалчиваемых значений свойств. Например, свойство Name space получает значение http : //tempuri. org. Объявление атрибута позволяет изменить умалчиваемые значения этого и других свойств. Например:
[WebService(
NameSpace= *http://MyFirm.ru/WebServices1
Name='Му First Web Service'
Description='This is My First Web Service with method HelloWorld' )]
WebServicel = class(System.Web.Services.WebService)
В этом примере изменяются пространство имен, название и описание службы.
В атрибуте помимо указанных свойств можно устанавливать имя класса службы, сборку, в которой он описан, и язык программирования. Если эти свойства не описаны, имя класса устанавливается таким же, как имя службы, а сборка (DLL- файл) размещается во вложенной папке /BIN в папке размещения службы. Для указания языка программирования разрешается использовать значения С#» VB или JS для языков С#, VisualBasic .NET или JScript .NET соответственно.
Атрибут [WebMethod]
Атрибут [WebMethod] должен предшествовать объявлению в классе службы любого ее метода. Свойства атрибута описаны в табл. 13.1.
Таблица 13.1. Свойства атрибута [WebMethod]
Свойство
Описаяие
property Buf f erResponse :
Boolean;
property CasheDuration;
Integer;
Если содержит True (по умолчанию), ответ буферизуется в памяти сервера полностью или до заполнения буфера, а затем передается клиенту. При значении False ответ передается порциями по 16 Кбайт1. Это значение имеет смысл устанавливать только тогда, когда заранее известно, что ответ будет дос* таточно большим и буферизация ответа не повысит производительность
Интервал времени в секундах, в течение которого ответ помещается в кэш сервера. Устанавливается, когда известно, что метод будет вызываться неоднократно с одним и тем же набором параметров. В этом случае кэширование ответа может повысить производительность
Этот размер определен в ныне действующей версии 1.1 среды .NET Framework. В следующих версиях он может быть изменен.
Свойство
Описание
property Description :
String;
Содержит описание метода
property EnableSession:
Если содержит True, метод может использовать
Boolean;
объект Session
property MessageName ;
Задает псевдоним имени. Широко используется
String;
для перегруженных методов, так как протокол SOAP не различает перегруженные методы и всегда обращается к первому из них
property Transact ionOption:
Это свойство позволяет методу работать подобно
Transactionoption;
транзакциям базы данных
Пример использования свойства MessageName:
[WebMethod(MessageName= *Addlnt'))
function Add(A, B: Integer): Integer; overload; [WebMethod(MessageName= *DoubleInt')]
function Add(A, B: Double): Double; overload;
Если бы свойство MessageName не применялось, всегда вызывался бы только первый метод Add, так как SOAP не анализирует типы параметров обращения и определяет метод только по его имени.
Использование веб-служб
Для использования веб-службы нужно выполнить перечисленью ниже действия:
Найти службу (то есть узнать ее URL-адрес).
Получить описание службы на языке WSDL.
Изучить описание и создать так называемый прокси-класс.
Обратиться к нужным методам службы с помощью средств прокси-класса. Напомню, что для получения описания веб-службы нужно с помощью браузера обратиться по URL-адресу службы, добавив в конце строки вызова символы 7WSDL. Это описание может быть довольно пространным (даже описание созданной в этой главе простейшей службы WSHelloWorld занимает более одной страницы). К счастью, среда Delphi способна аналюировать описание и автоматически создавать прокси-класс.
Создание прокси-класса
Прокси - классом называется специальный класс, создаваемый на основе описания веб-службы и играющий роль посредника1 между клиентской программой
Proxy в буквальном переводе с английского означает представитель, уполномоченный» заместитель.
444 Глава 13 • Веб-службы
и службой. В рамках этого класса для каждого метода веб-службы создаются по три метода — одноименный метод Method, а также методы BeginMethod и EndMethod. Первый используется для синхронного обращения к службе, два других — для асинхронного обращения. При синхронном вызове управление передается методу веб-службы, и работа клиентской программы 11 риостанавливается до завершения этого метода. При асинхронном вызове метод веб-службы стартует при вызове BeginMethod, но выполнение клиентской программы продолжается. Работа метода завершается вызовом EndMethod.
Как уже говорилось, анализ описания и ручное кодирование прокси-класса могут быть довольно трудоемким процессом, поэтому далее описываются соответствующие инструментальные средства Delphi.
К веб-службс можно обратиться из оиентской программы, реализованной в виде приложения ASP.NET или приложения WinForms. Для конкретности используем приложение WinForms:
Создайте новый проект WinForms (File ► New ► Windows Forms Application — Delphi for .NET). На пустой форме расположите кнопку и надпись. Сохраните проект на диске.
Выберите команду Project ► Add Web Reference. В результате появится диалоговое окно, показанное на рис. 13.6.
To add A web HferencB to the ./OH屯 wMQateto 电mb :E*bd»sa№n document Jn-. % Ьгмивг E(#c^M Add :Refer enc* button.To add A web HferencB to the ./OH屯 wMQateto 电mb :E*bd»sa№n document Jn-. % Ьгмивг E(#c^M Add :Refer enc* button.Borland UDOI universal directory tool searches for services and providers in the *J口DI services sitss with WS口L described services. Search by name or brow^ti thrciu/ available cateQonzatian schemas.Borland UDOI universal directory tool searches for services and providers in the *J口DI services sitss with WS口L described services. Search by name or brow^ti thrciu/ available cateQonzatian schemas.Рис. 13.6. Диалоговое окно UDDIРис. 13.6. Диалоговое окно UDDI
To add A web HferencB to the ./OH屯 wMQateto 电mb :E*bd»sa№n document Jn-. % Ьгмивг E(#c^M Add :Refer enc* button.
To add A web HferencB to the ./OH屯 wMQateto 电mb :E*bd»sa№n document Jn-. % Ьгмивг E(#c^M Add :Refer enc* button.
Borland UDOI universal directory tool searches for services and providers in the *J口DI services sitss with WS口L described services. Search by name or brow^ti thrciu/ available cateQonzatian schemas.
Borland UDOI universal directory tool searches for services and providers in the *J口DI services sitss with WS口L described services. Search by name or brow^ti thrciu/ available cateQonzatian schemas.
Рис. 13.6. Диалоговое окно UDDI
Рис. 13.6. Диалоговое окно UDDI
Испол ьзование веб-служб445
В верхней строке этого окна следует указать URL-адрес веб-службы или выбрать описание службы в одной из доступных папок UDDI (Universal Description, Discover and Integration — универсальное описание, обнаружение н интеграция). UDDI представляет собой открытый системный реестр, предназначенный для хранения информации о веб-службах.
Введите в верхней строке такой URL-адрес:
hr гр : / / localhosr./WSHel loWorld/WebServicel. asmx?WSDL
После щелчка на расположенной справа синей стрелке появится окно, показанное на рис. 13.7.
歩•夢,図.^ ^ [htto?//toc5host/*WeioW^^
<"sml ■versior-'l.Ci" ftr;cnding=;"utf-8" ?>-vbvcU:deh、i【iGc$'■r:::':^ ■■..•■;;jp-'h(tp://suh^nit'ts.xmisuop.urcj/^sdl/soap/"-:s~ "http://wwi4 3'j3-urg/2(]!3 ^ХМСКсИйта"'.;.:■■ :s-sd j^cIi -"http^/seb^rnns xmho^p.orq/so^p/encoiihi^/"•.h'4 / ;:i. -JhH.p://tfimpuri.nrg/*'.:.:;■ : ■ - 5】="htt# ://1н:сt fiscH j:ofn/^sdl/iuitt(e/lexl:M<it:chtny/*• ■' :■■■; ?: r<ii^4htlp://s.r:hetruis.i<t!dso*:<p j:trq/'.7sdi/miin(*/"t^^,c]el^Jьпlespice-,http://tompuri.org/',ziYh.: e :.・|::"hH p://&chem0s ,xmfsoap.ory/wsdl/4>-<wsdl. lype$>-・;,:£ch士rna e;emen*.Ftjrn:Defajj4-,'qualifled,'targe tN^r;E;41p3c:e-l,http://tempurl.org/,l><,f,<lernerit nari6~uHelioWorld"><s:cornpb5xType /:•</s: ei(?m:?r.t>■ < 5:el^-i^ent rran;c=l,HenoWorldResponse">-<s:complex Type>-?s: 3@不启旧己><b:eienienl rHinOccurs^'O" rria^Oce=jTS-"lhnar^e-"HelloWorldResult"lvpe=','s:string*, /〉<"sml ■versior-'l.Ci" ftr;cnding=;"utf-8" ?>-vbvcU:deh、i【iGc$'■r:::':^ ■■..•■;;jp-'h(tp://suh^nit'ts.xmisuop.urcj/^sdl/soap/"-:s~ "http://wwi4 3'j3-urg/2(]!3 ^ХМСКсИйта"'.;.:■■ :s-sd j^cIi -"http^/seb^rnns xmho^p.orq/so^p/encoiihi^/"•.h'4 / ;:i. -JhH.p://tfimpuri.nrg/*'.:.:;■ : ■ - 5】="htt# ://1н:сt fiscH j:ofn/^sdl/iuitt(e/lexl:M<it:chtny/*• ■' :■■■; ?: r<ii^4htlp://s.r:hetruis.i<t!dso*:<p j:trq/'.7sdi/miin(*/"t^^,c]el^Jьпlespice-,http://tompuri.org/',ziYh.: e :.・|::"hH p://&chem0s ,xmfsoap.ory/wsdl/4>-<wsdl. lype$>-・;,:£ch士rna e;emen*.Ftjrn:Defajj4-,'qualifled,'targe tN^r;E;41p3c:e-l,http://tempurl.org/,l><,f,<lernerit nari6~uHelioWorld"><s:cornpb5xType /:•</s: ei(?m:?r.t>■ < 5:el^-i^ent rran;c=l,HenoWorldResponse">-<s:complex Type>-?s: 3@不启旧己><b:eienienl rHinOccurs^'O" rria^Oce=jTS-"lhnar^e-"HelloWorldResult"lvpe=','s:string*, /〉svMce дмефиоп^ dwunent “Waxnglxmv.…二svMce дмефиоп^ dwunent “Waxnglxmv.…二“ ^^8p^1^0^8r jgy^:;“ ^^8p^1^0^8r jgy^:;Add8*fiK«nc«:Add8*fiK«nc«:
<"sml ■versior-'l.Ci" ftr;cnding=;"utf-8" ?>
-vbvcU:deh、i【iGc$
'■r:::':^ ■■..•■;;jp-'h(tp://suh^nit'ts.xmisuop.urcj/^sdl/soap/"
-:s~ "http://wwi4 3'j3-urg/2(]!3 ^ХМСКсИйта"
'.;.:■■ :s-sd j^cIi -"http^/seb^rnns xmho^p.orq/so^p/encoiihi^/"
•.h'4 / ;:i. -JhH.p://tfimpuri.nrg/*
'.:.:;■ : ■ - 5】="htt# ://1н:сt fiscH j:ofn/^sdl/iuitt(e/lexl:M<it:chtny/*
• ■' :■■■; ?: r<ii^4htlp://s.r:hetruis.i<t!dso*:<p j:trq/'.7sdi/miin(*/"
t^^,c]el^Jьпlespice-,http://tompuri.org/',
ziYh.: e :.・|::"hH p://&chem0s ,xmfsoap.ory/wsdl/4>
-<wsdl. lype$>
-・;,:£ch士rna e;emen*.Ftjrn:Defajj4-,'qualifled,'
targe tN^r;E;41p3c:e-l,http://tempurl.org/,l>
<,f,<lernerit nari6~uHelioWorld">
<s:cornpb5xType /:•
</s: ei(?m:?r.t>
■ < 5:el^-i^ent rran;c=l,HenoWorldResponse">
-<s:complex Type>
-?s: 3@不启旧己>
<b:eienienl rHinOccurs^'O" rria^Oce=jTS-"lh
nar^e-"HelloWorldResult"
lvpe=','s:string*, /〉
<"sml ■versior-'l.Ci" ftr;cnding=;"utf-8" ?>
-vbvcU:deh、i【iGc$
'■r:::':^ ■■..•■;;jp-'h(tp://suh^nit'ts.xmisuop.urcj/^sdl/soap/"
-:s~ "http://wwi4 3'j3-urg/2(]!3 ^ХМСКсИйта"
'.;.:■■ :s-sd j^cIi -"http^/seb^rnns xmho^p.orq/so^p/encoiihi^/"
•.h'4 / ;:i. -JhH.p://tfimpuri.nrg/*
'.:.:;■ : ■ - 5】="htt# ://1н:сt fiscH j:ofn/^sdl/iuitt(e/lexl:M<it:chtny/*
• ■' :■■■; ?: r<ii^4htlp://s.r:hetruis.i<t!dso*:<p j:trq/'.7sdi/miin(*/"
t^^,c]el^Jьпlespice-,http://tompuri.org/',
ziYh.: e :.・|::"hH p://&chem0s ,xmfsoap.ory/wsdl/4>
-<wsdl. lype$>
-・;,:£ch士rna e;emen*.Ftjrn:Defajj4-,'qualifled,'
targe tN^r;E;41p3c:e-l,http://tempurl.org/,l>
<,f,<lernerit nari6~uHelioWorld">
<s:cornpb5xType /:•
</s: ei(?m:?r.t>
■ < 5:el^-i^ent rran;c=l,HenoWorldResponse">
-<s:complex Type>
-?s: 3@不启旧己>
<b:eienienl rHinOccurs^'O" rria^Oce=jTS-"lh
nar^e-"HelloWorldResult"
lvpe=','s:string*, /〉
svMce дмефиоп^ dwunent “
Waxnglxmv.…二
svMce дмефиоп^ dwunent “
Waxnglxmv.…二
“ ^^8p^1^0^8r jgy^:;
“ ^^8p^1^0^8r jgy^:;
Add8*fiK«nc«:
Add8*fiK«nc«:
Рис. 13.7. Окно с описанием веб-службы
Щелкните на кнопке Add Reference, чтобы среда Delphi создала прокси-класс.
ПРИМЕЧАНИЕ
Если вы работаете с локш1изованной (русифицированной) версией Windows, щелчок на кнопке может вызвать сообщение об ошибке. Связано зто с тем, что в процессе создания прокси-класса среда Delphi создает временный файл в папке, указанной в переменной среды Тетр. Маршрут доступа к этому файлу но умолчанию включает имя пользователя и папку Мои документы, то есть содержит кириллицу. В результате среда tn* сможет создать временный файл и прокси-класс. В этом случае измените переменную Тетр, оызвав командой Пуск > Панель управления > Система окно Свойства системы и на вкладке Дополнительно этого окна щелкнув на кнопке Переменные среды. Для пере- мешкл! Тетр укажите чакон маршрут: С : \Temp.
Просматривая проект в окне менеджера проектов, можно увидеть, что среда создала и добавила к проекту несколько новых файлов:
WebServicel.map — справочная информация о веб-службе;
WebServicel.wsdl — описание службы на языке WSDL;
localhost.WebServicel.pas — код прокси-класса.
Эти файлы располагаются в папке Web References\localhost, вложенной в папку размещения проекта.
Использование прокси-класса
Использование прокси-класса не вызывает затруднений. Для этого в нужном месте программы объявляется переменная этого класса и создается соответствующий объект. После этого любой метод веб-службы доступен как метод этого объекта. Например (проект Chl3\UseWSHelloWorld\UseWS.dpr):
implement at i on
uses localhost.WebServisel;
procedure TWinForrn.Buttonl_Click(sender: System.Object;
e: System.EventArgs);
var
WS: TWebServicel;
begin
Self.Cursor :二 Cursors.WaitCursor;
WS := TWebServicel.Create; // Создаем объект прокси-класса
Label1.Text := WS.HelioWorld; // Вызываем веб-службу
Self.Cursor := Cursors.Default;
end;
Обратите внимание: среда не вставляет автоматически в файл WinForm.pas ссылку на модуль с прокси-классом. Эту ссылку нужно вставить вручную.
На рис. 13.8 показано окно программн примера использования веб-службы.
Рис. 13.8. Использование веб-службы
Создание пользовательских элементов
управления
В этой главе описывается процесс создания и использования пользовательских элементов управления. Пользовательский элемент управления — это страница ASP.NET, преобразованная в элемент управления. Основное назначение таких элементов — многократное использования их содержимого и логики на нескольких страницах. Например, в большинстве веб-узлов на страницах отображаются одинаковые верхние и нижние колонтитулы, левые и правые панели. Технология пользовательских элементов управления позволяет один раз создать такие колонтитулы и панели, а затем использовать их на любой странице узла.
Пример простого пользовательского элемента управления
В качестве примера создадим простой пользовательский элемент управления, помещающий на веб-страницу текстовую строку (проект Chl4\UserC6ntrol\UserControl.dpr):
Начните новое приложение ASP.NET и сохраните его на диске. Затем выберите команду File ► New ► Other и в открывшемся окне на странице, связанной с узлом New ASP.NET Fites, выберите значок ASP-NET User Control, как показано на рис. 14.1.
После щелчка на кнопке ОК среда Delphi создаст заготовку нового пользовательского элемента управления: в проекте появятся файл WebUserControl 1.ascx и связанный с ним файл WebUserControl 1.pas. Сохраните файл пользовательского элемента под именем SimpleUserCOntrol. Имена ascx- и pas-файлов соответствующим образом изменятся.
Для наполнения нового пользовательского элемента управления используются те же средства редактора форм, что и при создании обычной страницы ASP.NET: на нем можно размещать элементы категорий HTML Elements и Web Controls, а также редактировать саму страницу (ascx-файл).
Item C^tegor 1*5:Item C^tegor 1*5:ECOASP.NET Qobal.asax Web Web ServiceConftgurati...ECOASP.NET Qobal.asax Web Web ServiceConftgurati...ECO A5P.NET PageECO A5P.NET Page产? C# Projects■ f.'.j Crystal Reports;-;.:Delphi for .NET Projects口 Intrawebf : New ASP.NET Ffesf二 New ECO Flies■匕 New Files Ю二 Delphi Projects■产二 ActiveX胃…Business■ Г'": Delphi FilesC: Intraweb■二 WebBroker 产:WebServices-• WebSnap广;XMLDeploymentCJ Other Flies,「Unit Test产? C# Projects■ f.'.j Crystal Reports;-;.:Delphi for .NET Projects口 Intrawebf : New ASP.NET Ffesf二 New ECO Flies■匕 New Files Ю二 Delphi Projects■产二 ActiveX胃…Business■ Г'": Delphi FilesC: Intraweb■二 WebBroker 产:WebServices-• WebSnap广;XMLDeploymentCJ Other Flies,「Unit TestASP.NET PageASP.NET PageA5P.NET WebServiceA5P.NET WebService題題
Item C^tegor 1*5:
Item C^tegor 1*5:
ECOASP.NET Qobal.asax Web Web ServiceConftgurati...
ECOASP.NET Qobal.asax Web Web ServiceConftgurati...
ECO A5P.NET Page
ECO A5P.NET Page
产? C# Projects
■ f.'.j Crystal Reports
;-;.:Delphi for .NET Projects
口 Intraweb
f : New ASP.NET Ffes
f二 New ECO Flies
■匕 New Files Ю二 Delphi Projects
■产二 ActiveX
胃…Business
■ Г'": Delphi Files
C: Intraweb
■二 WebBroker 产:WebServices
-• WebSnap
广;XML
Deployment
CJ Other Flies
,「Unit Test
产? C# Projects
■ f.'.j Crystal Reports
;-;.:Delphi for .NET Projects
口 Intraweb
f : New ASP.NET Ffes
f二 New ECO Flies
■匕 New Files Ю二 Delphi Projects
■产二 ActiveX
胃…Business
■ Г'": Delphi Files
C: Intraweb
■二 WebBroker 产:WebServices
-• WebSnap
广;XML
Deployment
CJ Other Flies
,「Unit Test
ASP.NET Page
ASP.NET Page
A5P.NET WebService
A5P.NET WebService
題
題
Рис. 14.1. Активизация эксперта создания пользовательского элемента
Добавим в наш элемент текст: щелкните в окне редактора форм и прямо на поверхности -элемента введите строку
Это - пример простого пользовательского элемента управления.
Теперь вернитесь к странице WebForml и добавьте такую строку:
Эта страница демонстрирует простой пользовательский элемент управления.
Завершите ввод нажатием клавиши Enter (для большей наглядности можно нажать эту клавишу дважды) и выберите команду Insert ► Insert User Control. Появится окно, показанное на рис. 14.2.
Рис. 14.2. Диалоговое окно выбора п о л ьзовательского элемента управленияРис. 14.2. Диалоговое окно выбора п о л ьзовательского элемента управления
Рис. 14.2. Диалоговое окно выбора п о л ьзовательского элемента управления
Рис. 14.2. Диалоговое окно выбора п о л ьзовательского элемента управления
Убедитесь, что в поле ввода содержится ссылка на файл SimpleUserControl.asoc, и щелкните на кнопке ОК. В результате редактор формы должен выглядеть так, как показано на рис. 14.3.
Рис. 14.3. Окно редактора форм с пользовательским элементом управленияРис. 14.3. Окно редактора форм с пользовательским элементом управленияПосле запуска приложения появится окно, показанное на рис. 14.4.После запуска приложения появится окно, показанное на рис. 14.4.£айп Правка Бид йзбра«юе Сераке правка«0 W £ Z 心 /С Поиск • >;;.•■ Убранное厶на”;阁 http://locrfx>sl/UserControl/WebForm 1,aspx£айп Правка Бид йзбра«юе Сераке правка«0 W £ Z 心 /С Поиск • >;;.•■ Убранное厶на”;阁 http://locrfx>sl/UserControl/WebForm 1,aspx霞金m♦&百觀摻:霞金m♦&百觀摻:Эта страница демонстрирует простой пользовательский элемент управленияЭта страница демонстрирует простой пользовательский элемент управленияЭто - пример простого пользовательского элемента управленияЭто - пример простого пользовательского элемента управления+淞汨铢七+淞汨铢七,9.丝竺階蹙三三:決上三二至』,9.丝竺階蹙三三:決上三二至』
Рис. 14.3. Окно редактора форм с пользовательским элементом управления
Рис. 14.3. Окно редактора форм с пользовательским элементом управления
После запуска приложения появится окно, показанное на рис. 14.4.
После запуска приложения появится окно, показанное на рис. 14.4.
£айп Правка Бид йзбра«юе Сераке правка
«0 W £ Z 心 /С Поиск • >;;.•■ Убранное
厶на”;阁 http://locrfx>sl/UserControl/WebForm 1,aspx
£айп Правка Бид йзбра«юе Сераке правка
«0 W £ Z 心 /С Поиск • >;;.•■ Убранное
厶на”;阁 http://locrfx>sl/UserControl/WebForm 1,aspx
霞
金m♦&百觀摻:
霞
金m♦&百觀摻:
Эта страница демонстрирует простой пользовательский элемент управления
Эта страница демонстрирует простой пользовательский элемент управления
Это - пример простого пользовательского элемента управления
Это - пример простого пользовательского элемента управления
+淞汨铢七
+淞汨铢七
,9.丝竺階蹙三三:決上三二至』
,9.丝竺階蹙三三:決上三二至』
Рис. 14.4. Пользовательский элемент управления на странице в окне браузера
1S 3妆 449
Исследование простого элемента управления
Прежде всего активизируйте окно с кодом файла SimpleUserControl.pas. В нем объявляется следующий класс:
type
TWebUserControll = class(System.Web.UI.UserControl)
strict private
procedure InitializeComponent;
strict private
procedure Page_Load(sender: System.Object; e: System.EventArgs); strict protected
procedure Onlnit(e: System.EventArgs); override;
private
f Private Declarations 丿
public
f Public Declarations 丿 end;
Класс TWebUserControll порожден от класса System.Web.UI.UserControl. Этот класс является базовым для всех пользовательских элементов управления. В нем объявлен обработчик события Page_Load, который можно применять для программной инициализации пользовательского элемента управления.
Файл SimpleUserG)ntrol.ascx содержит такие строки:
<%@ Control Language-*c#" AutoEventWireup="false"
CodeBehind=°SimpleUserControl.pas"
Inherits=,*SimpleUserControl.TWebUserControll,*%>
Это - пример простого пользовательского элемента управления.
В первой строке (в книге эта строка разбита на три) содержится стандартный для ASP.NET дескриптор Control. Атрибуты дескриптора описаны в табл. 14.1.
Таблица 14.1. Атрибуты дескриптора Control
Атрибут
Описание
Language
Определяет язык сценариев, используемый на данной странице. Поскольку сервер MS IIS не имеет компилятора Delphi, здесь по умолчанию используется значение C#
AutoEventWireup
Указывает, будут ли обработчики событий в сценариях автоматически связываться с соответствующими событиями. Так как обычно в Delphi события обрабатываются в pas-файле, значением по умолчанию этого атрибута является False
CodeBehind
Имя pas-файла
Inherits
Имя класса пользовательского элемента управления
В файле WebForml.aspx имеются такие строки:
<%@ Раде Ьапдиаде=ис#и Debug=°truen Codebehind="WebForml.pas AutoEventWireup=,*false'* Inherits= "WebForml.TWebForml*%>
<%@ Register tagprefix="ucl" tagname=иSimpleUserControl"
Src=* Sin^leUserControl.ascxn%>
<!DOCTYPE HTML PUBLIC --//W3C//DTD HTML 4.01 Transitional//ENH>
<html>
<head>
<titlex/title>
</head>
<body bgcolor=,,#ffffff" msepositioning=nGridLayout ">
vform runat=H server * >
<р>Эта страница демонстрирует простой пользовательский элемент управления.</р>
<Р>
<ucls SimDleUsexControl id="UserControll" runat="server * >
</ucl:SimpleUserControl>
</p>
</foxn>
</body>
</html>
В его начале располагается дескриптор Register, с помощью которого осуществляется регистрация пользовательского элемента управления. Атрибуты дескриптора описаны в табл. 14.2.
Таблица 142 Атрибуты дескриптора Register
Атрибут
Описание
TagPrefix
Определяет префикс, предназначенный для маркировки десжрипторов, описывающих пользовательский элемент
TagName
Задает имя пользовательского элемента
Src
Указывает файл с кодом пользовательского элемента
Сам пользовательский элемент управления добавляется на веб-страницу следующим образом:
<ucl:SimpleUserControl id=-UserControlln runat="server">
</ucl: S impleUserCont rol >
Этот дескриптор начинается значением атрибута TagPrefix (в нашем случае - ucl), затем следует имя элемента (siivleUeerControl).
Элемент управления для регистрации пользователя
В этом разделе описывается относительно сложный элемент, содержащий встроенные элементы и логику (проект Chl4\UCLogin\UCLogin.dpr). Он предназначен для регистрации пользователя и, таким образом, затрагивает проблему безопасности приложений ASP.NET. В главе 15 эта проблема рассматривается более подробно. Страница, на которой используется этот элемент, показана на рис. 14.5.
Рис. 14.5. Использование элемента UserControlLogin
Начните новое приложение ASP.NET и сохраните его на диске под именем UCLogin.
С помощью окна, открываемого команаоЛ File ► New ► Other, запустите эксперт создания пользовательских компонентов (значок ASP.NET User Control). Сохраните файл элемента под именем UserControlLogin.ascx.
Поместите на поверхность элемента панель Panel (категория Web Controls). Панель послужит контейнером для вставляемых в наш элемент другах элементов. В свойстве ID панели укажите значение LoginPanel.
На панель поместите две надписи Label, два поля TextBox, два элемента RequiredFieldValidator и кнопку Button так, как показано на рис. 14.6 (все элементы из категории Web Controls).
Измените умалчиваемые значения свойств элементов следующим образом:
Label 1 «Text = User Name;
Label2.Text = Password;
о TextBoxl.ID = tbUserName;
о TextBox2.ID = tbPassword;
o RequiredFielValidatorl.ControlToValidate = tbUserName;
о RequiredFielValidator2.ControlToValidate = tbPassword;
о RequiredFielValidatorl. ErrorMassage = Поле User Name не может быть пустым!;
о RequiredFielValidator2.ErrorMessage 二 Поле Password не может быть пустым!;
о Buttonl.ID = LoginButon;
о Buttonl.Text 二 Login.
Рис. 14.6. Вид элемента в окне редактора форм
Для кнопки LoginButton напишите такой обработчик:
procedure TWebUserControll.LoginButton_Click(sender: System.Object; e: System.EventArgs);
begin
DoLogin ( dbUserName. Text, tbPassvJord. Text); end;
Процедура DoLogin определена следующим образом:
procedure TWebUserControll.DoLogin(UserName, Password: String); begin
If (System.String.Compare(^serName, 'Username', True) 二 0) and
(System. String. Compare? (Password, * Password' , True) = 0) then Response.Redirect('Welcom.aspx') else Response.Redirect(1ErrorPage.aspx');
end;
В процедуре DoLogin используется метод Compare класса System. String. Он принимает две сравниваемые строки и логический признак, разрешающий игнорировать разницу в регистре букв сравниваемых строк. Метод возвращает 0, если строки совпадают*
Если пользователь введет правильные данные, он методом Response. Redirect () будет перенаправлен на страницу Wei com. aspx, в противном случае — на страницу ErrorPage. aspx. Первая страница содержит приветствие (рис. 14.7), а вот вторая —сообщение об ошибке н новый экземпляр элемента UserConcrolLogin. asex (рис. 14.8).
Рис. 14.7. Реакция на ввод пользователя — страница Welcom.aspx
файл Правка 恥 Избранное Сдзеис £пР^§亡三摩
0Намд 0 面图心,/)По«к ☆哂анное 砂 *
Адре»:; [^ http://locdhost/UQogln/ErrorPag^^] 0 Переход ;5^^ ^
Ошибка! Повторите ввод: |
User Name;腔
Password :j
跑匹^二二二二二二入…宀專^
Рис. 14.8. Реакция на ввод пользователя — страница ErrorPage.aspx
Обе страницы должны быть добавлены в проект с помощью команды File ► New > Other ► ASP.NET Page.
приложенийASP.NETприложенийASP.NET
приложений
ASP.NET
приложений
ASP.NET
Защита
Безопасность веб-приложений является их важнейшим аспектом. Незащищенные веб-приложения уязвимы для сетевых атак, могущих привести к необратимым нарушениям целостности данных. В этой главе обсуждается проблема защиты приложений ASP.NET от несанкционированного доступа.
Способы защиты приложений ASP.NET
Существует несколько способов защиты приложений ASP.NET, но все они в той или иной форме основаны на аутентификации пользователя и его авторизации. Под аутентификацией понимают процесс идентификации пользователя и проверки его роли. Определить роль пользователя — означает отнести его к той или иной группе пользователей и наделить его правами, присущими этой группе. Например, в бизнес-приложениях клерки имеют ограниченные права относительно размеров заключаемых сделок, руководители отделов имеют права проведения крупных сделок, а высшее руководство компании — неограниченные права.
Результат аутентификации пользователя позволяет выяснить его идентификатор, иногда называемый учетной записью пользователя^ и его роль. Результат авторизации позволяет на основе идентификатора пользователя и его роли определить, к каким ресурсам и на каком уровне он имеет право доступа.
В ASP.NET существует три формы аутентификации: аутентификация Windows, аутентификация на основе форм и аутентификация по паспорту. Вид аутентификации определяется дескриптором authent i с at i on и его параметром mode, который может принимать значения Windows, Forms, Passport и None. Этот
456 Глава 15 • Защита приложений ASP.NET
дескриптор помещается в фаЛл Web.config, которым снабжается каждое приложение ASP.NET.
Далее рассматриваются указанные формы аутентификации.
Аутентификация Windows
Аутентификация Windows может использоваться только при работе машины пользователя под управлением этой операционно!! системы, а приложения — под управлением MS IIS.
ПРИМЕЧАНИЕ
По умолчанию каждое приложение ASP.NET в(|)aiijie Web.config имеет дескриптор вида <authentication mode= ° Windows" / >. Этот дескриптор устанавливает аутентификацию Windows, но нс защищает приложение ASP.NET.
Для использования аутентификации Windows нужно запустить утилиту Internet Information Services (Пуск > Панель управления ► Администрирование), раскрыть узел с именем машины, затем узел Веб-узлы и узел Веб-узлы по умолчанию, разыскать папку с защищаемым веб-приложеиием и в ее локальном меню выбрать команду Свойства. В новом окне на вкладке Безопасность каталога щелкните на кнопке Изменить. В результате появится окно Методы проверки подлинности (рис. 15.1).
戸门丽诵森啮壘^正 -■ ■ - ■ ■ ■■ -— ■;■ :■:■ ■也я досг9n9 к хинному ресурсу w требуется имя и пароль.. j§ У чета запись аля анонимного доступа:Нмяпользоеотля/ к. j, 匚05> П^Ф0£|Ь:'л«««<й^»*«д»■不:戸门丽诵森啮壘^正 -■ ■ - ■ ■ ■■ -— ■;■ :■:■ ■也я досг9n9 к хинному ресурсу w требуется имя и пароль.. j§ У чета запись аля анонимного доступа:Нмяпользоеотля/ к. j, 匚05> П^Ф0£|Ь:'л«««<й^»*«д»■不:
戸门丽诵森啮壘^正 -■ ■ - ■ ■ ■■ -— ■;
■ :■:■ ■也я досг9n9 к хинному ресурсу w требуется имя и пароль.. j
§ У чета запись аля анонимного доступа:
Нмяпользоеотля/ к. j, 匚05
> П^Ф0£|Ь:'л«««<й^»*«д»■不:
戸门丽诵森啮壘^正 -■ ■ - ■ ■ ■■ -— ■;
■ :■:■ ■也я досг9n9 к хинному ресурсу w требуется имя и пароль.. j
§ У чета запись аля анонимного доступа:
Нмяпользоеотля/ к. j, 匚05
> П^Ф0£|Ь:'л«««<й^»*«д»■不:
皿婚仲 смоесфкМмдяижйсгх-::
Дляэтмк мега 碑 проверки псалм^ности^ЯгИ пароль пельзевете ля требуются в олядУйзи^ W л^як * ?
■ анонимный аозпЕ уключен;
• доступ ограничен Габлицаьш управления доступом NTFS.
0 Обычная {пароль отправляется в текстовом Формате)
Д(%$ОН ПО ^МОЛН»«*Х
Облвст^
О Вбгроенмва проверка ащнюсти Wirxlo倣
6k :〕「Ьтй^аГ] С^^З ^
Рис. 15.1. Диалоговое окно Методы проверки подлинности
В этом окне следует сбросить флажок Анонимный доступ и установить флажок Обычная (пароль отправляется в текстовом формате). После этого при попытке обращения к защищенному ресурсу появится окно, показанное на рис. 152
Аутентификация Windows применяется только в лок^1ьных сетях, построенных по технологии интранет, так как предъявляет жесткие требования к клиентским машинам (они должны работать под управлением Windows и использовать браузер Internet Explorer). При создании интернет-сайта следует помнить, что дале-
focahostПользователь;Пароль!focahostПользователь;Пароль!Пс^фжитьлврольПс^фжитьлврольРис. 15>2. Диалоговое окно для регистрации пользователяРис. 15>2. Диалоговое окно для регистрации пользователяко не все клиенты могут удовлетво
focahost
Пользователь;
Пароль!
focahost
Пользователь;
Пароль!
Пс^фжитьлвроль
Пс^фжитьлвроль
Рис. 15>2. Диалоговое окно для регистрации пользователя
Рис. 15>2. Диалоговое окно для регистрации пользователя
рять этим требованиям. Кроме того, аутентификация пользователя на основе учетной записи Windows не всегда приемлема с точки зрения безопасности.
Аутентификация на основе форм
Аутентификация на основе форм не предъявляет никаких требований к клиентам и позволяет разработчику приложения ASP.NET использовать любой механизм для хранения имен пользователей и их паролей, будь то XML-файл (в том числе файл Web.config), таблица базы данных, реестр Windows и т. д.
Для реализации этого вида аутентификации разработчик приложения ASP.NET должен создать страницу для регистрации пользователя и предъявлять ее пользователю при первом обращении к сайту. Если регистрация прошла успешно, браузеру пользователя отсылается так называемый «регистрационный билет» в виде файла cookie^ При обращении к любой другой странице сайта сервер получает из этого файла регистрационный билет пользователя и блокирует его повторную регистрацию. Для использования аутентификации на основе форм необходимо проделать следующее:
Внести изменения в раздел <authentication> конфигурационного файла Web.config.
Создать в проекте страницу для регистрации пользователя.
Защитить остальные страницы приложения от несанкционированного доступа.
Cookie (читается куки) в буквальном переводе с английского означает «печенье». В терминологии Интернета этим термином обозначается некоторая информация, предназначенная для временного размещения на машине пользователя.
Изменения в файле Web.config
Как уже говорилось, каждое приложение ASP.NET имеет индивидуальный конфигурационный файл Web.8nfig$ расположенный в папке размещения приложения. Для включения механизма аутентификации на основе форм в него нужно внести такие изменения:
<authentication mode=eForms">
<forms
name=•logincookie"
1од1пиг1=нЬод1пРопп.аархи
timeout-"30й>
</form8>
</authentlcation>
В дескрипторе <forms> используется ряд атрибутов, описание которых приведено в табл, 15.1.
Таблица 15.1. Атрибуты дескриптора <forms>
Атрибут
Описание
name
Имя используемого файла cookie. По умолчанию принимается значение aspxauth
loginUrl
URL-адрес страницы, на которую переадресуется запрос, если файл cookie не найден
timeout
Период времени в минутах, по истечении которого файл cookie удаляется
protection
Тип пшфрования файла cookie. Допустимые значения: All (все); None (отсутствует); Encryption (шифрование); Validation (проверка)
path
Маршрут доступа к файлу cookie
requireSSL
Если содержит True, для передачи cookie используется протокол повышенной секретности SSL (Socket Security Layer — секретный слой сокета)
slidingExpiration
Если содержит True, атрибут timeout обновляется после каждого запроса
Индивидуальная защита страниц
Обычно сайт сод^жит множество страниц, каждая из которых имеет свой URL-адрес. Ничто не мешает злоумышленнику обратиться непосредственно к нужной странице, не проходя процедуру регистрации. Чтобы исключить возможность доступа к странице клиента» который не прошел процедуру регистрации» можно написать такой обработчик события Page_Load:
procedure TWebForm.Page_load(Sender: Object;
e: System.EventArgs);
begin
if not User.Identity.IsAuthenticated then // Клиент
// а а регистрирован ?
Response.Redirect('LoginForm.aspx');//-Нет.
/ / Регистрируем его end;
Подобный обработчик следует написать для каждой защищаемой страницы сайта. Если защищаются все страницы, вместо указанных обработчиков можно дополнить конфигурационный файл следующим дескриптором:
<authorization>
<deny users;"?* />
</authorizations
В этом случае знак ? указывает, что страницы защищаются от любых незарегистрированных клиентов. Заметьте, что при такой защите в составе вашего веб-узла должна быть регистрационная страница в файле, определяемом атрибутом LoginUrl дескриптора <forxns>t а если этот атрибут не задан — в файле Login.aspx.
В обработчике используется свойство User объекта Раде, содержащее объект, реализующий интерфейс IPrincipal. Подсвойство Identity этого свойства исполняет интерфейс I Identity, с помощью которого программа может определить не только факт регистрации пользователя (свойство IsAutheticated), но и некоторые другие параметры — его имя, регистрационное удостоверение и т. п.
Создание страницы регистрации
На странице регистрации пользователя необходимо предусмотреть элементы управления для ввода необходимой регистрационной информации. Чаще всего пользователь должен указать свое регистрационное имя и пароль, поэтому непременными атрибутами окон регистрации являются два текстовых поля. Кроме того, в некоторых случаях на страницу помещается флажок, с помощью которого пользователь может указать на необходимость создания постоянного файла cookie. Постоянный файл не уничтожается браузером и позволяет получить доступ к защищаемым ресурсам без повторной регистрации. Таким образом, типичная страница регистрации обычно выглядит так, как показано на рис. 15.3.
Создание регистрационного удостоверения пользователя
После щелчка на кнопке на странице регистрации осуществляется аутентификация пользователя и, если она проходит успешно, создается регистрационное удостоверение пользователя. В регистрационное удостоверение переносятся вся регистрационная информация и другие сведения, необходимые для регистрации. Регистрационное удостоверение размещается на браузере клиента в виде файла cookie. Оставив пока в стороне процедуру аутентификации (далее рассматриваются ее различные реализации), рассмотрим создание регистрационного удостоверения и его размещение в файле cookie.
8йл Правка @ид ©бранное Сервис Справка
87^
^^‘初ppgXOA @纱碼济秽^^‘初ppgXOA @纱碼济秽Адрес;陶 http://locdho5t/FormjAuthlnfo/Logln.aspx
^^‘初ppgXOA @纱碼济秽
^^‘初ppgXOA @纱碼济秽
Пример страницы регистрации
Введите имя Psumamu" и пароль "Password"
User Name:;
Password
□ Запомнить параметры регистрации
Рис. 15.3. Пример страницы для регистрации пользователя
Эти действия реализуются в такой процедуре:
class procedure Redii'ectFromLoginPage (UserName: String;
PersistentCookie: Boolean); overload;
Эта процедура объявлена в классе FormsAuthentication как статическая, то есть к ней можно обращаться без создания экземпляра класса. При обращении к ней передаются регистрационное имя пользователя и лошчсский признак, указывающий на необходимость создания постоянного файла cookie. В перегруженном варианте процедуре в качестве третьего параметра передается строковое выражение, указывающее маршрут размещения файла cookie. Процедура создает стандартный файл cookie и возвращает его браузеру пользователя.
Вот типичный пример использования процедуры:
procedure TLoginForm.btnLogin_C1ick(Sender: &Object;
e: EventArgs);
begin
if Userboginvalid then // Регистрационные параметры верные?
FormsAuthentication.RedirectFromLoginPage( // -Да tbUsername.Text, cbRemember.Checked); end;
Предполагается, что в лошческой функции UserLoginValid осуществляется проверка правильности введенной регистрационной информации, поле tbUsername содержит регистрационное имя пользователя, а флажок cbRemember управляет созданием постоянного файла cookie.
После успешного выполнения метода RedirectFromLoginPage управление передается на страницу с именем defaultaspx. Обработчик ее события Page_Load имеет такой вид (проект Chl5\FormsAuthInfo.dpr):
procedure TWebForml, Page_Load (sender : Sy stem. Object; e: System.EventArgs);
var
Formsld: Formsldentity;
begin
If not User.Identity.IsAuthenticated then // Нужна регистрация? Response.Redirect('Login.aspx') // -Да. На странице регистрации else // -Нет. Выводим информацию о пользователе:
begin
Re spouse .Write ( ' <Ы>Параметры клиента: </hl> * );
Response.Write(*Имя пользователя = ' +
User.Identity.Name + '<br>');
Response.Write('Тип аутентификации 二'+
User.Identity.AuthenticationType + '<br>1);
Formsld := Formsldentity(User.Identity);
Response.Write(* Маршрут файла Cookie = ' + Formsld.Ticket.CookiePath + '<br>');
Response.Write(* Время уничтожения Cookie = ' +
Convert.ToString(Formsld.Ticket.Expiration) + 'vbr>');
end;
end;
После регастрации пользователь возвращается на страницу defaultaspx, на которой выводится некоторая информация о нем (рис. 15.4).
В классе Forms Au t hent i cat ion определена следующая функция:
class function GetRedirectURL (UserName: String;
IsPersistentCookie: Boolean): String;
Как сказано в документации, эта функция создает стандартный файл cookie и возвращает URL страницы, которая перенаправила запрос на страницу регистрации. Она используется так:
Response-Redirect(GetRedirectURL{'UserName', False));
Однако мне не удалось добиться от нее возврата на страницу запроса, если эта страница содержится в произвольном файле (не в файле default.aspx).
Возврат на страницу запроса можно реализовать при программном создании файла cookie. Например (проект Chl5\FbrmsAuthCreateGx>kie.dpr):
iins>l ement at 土 on
uses System.Web.Security;
procedure TWebForml.Buttonl_Click(sender: System.Object; e: System.EventArgs);
var
Ticket: FormsAuthenticationTicket;
encTicket: String;
HTTPCook: HTTPCookie;
RetUrl: String;
begin
〃 Создаем регистрационное удостоверение :
// Номер версии〃 Решстрацлонное имя〃 Текущее время// Время действия〃 cookie// Номер версии〃 Решстрацлонное имя〃 Текущее время// Время действия〃 cookieTicket := FormsAuthenticationTicket-Create(
// Номер версии
〃 Решстрацлонное имя
〃 Текущее время
// Время действия
〃 cookie
// Номер версии
〃 Решстрацлонное имя
〃 Текущее время
// Время действия
〃 cookie
'user',
System.DateTime.Now,
System.DateTime.Now.AddMinutes (30 >,
false,//Не постоянный cookie
*nr/mail@mail.ru1,// UserData
FormsAuthentication.FormsCookiePath); // Маршрут доступа // Шифруем удостоверение;
encTicket := FormsAuthentication.Encrypt(Ticket};
// Создаем cookie:
HTTPCookHTTPCookie.Create(
FormsAuthentication.FormsCookieName, encTicket); // Помещаем его в коллекцию cookies:
Response.Cookies.Add(HttpCook);
〃 Получаем URL страницы запроса;
RetUrl : = Re<juest. Params [' ReturnUrl'];
// Переадресуем на страницу запроса или на Welcome.aspx: if RetURL о 一 then
Response.Redirect(RetUrl) else
Response.Redirect('Welcome.aspx'); end;
При программном создании в cookie можно поместить произвольные данные (параметр UserData). Эти данные будут доступны на любой странице. Например (файл Welsome.aspx):
1пф1етепЪаЪ±оп
uses System.Web,Security;
procedure TWebForml.Page_Load(sender: System.Object;
e: System,EventArgs); var
FormsId; Formsldentity;
begin
// Получаем регистрационное удостоверение:
Formsld := User,Identity as FormsIdentity;
Регистрационное имя:
IbName.Text := Formsld.Name;
// EMail-адрес:
IbUserData.Text := Formsld.Ticket.UserData; end;
Свойство Page.User.Identity определено как объект, исполняющий интерфейс Ildentity. Класс Formsldentity также исполняет этот интерфейс, но в нем определено свойство Ticket, открывающее доступ к полям регистрационной записи. В первом операторе осуществляется явное приведение объекта User. Identity к классу FormsIdentity.
Обратите внимание: в приведенном обработчике события Page_Load нет переадресации на страницу регистрации. Тем не менее такая переадресация осуществляется автоматически, так как в файл Web.config вставлены следующие дескрипторы:
<authenticatioxi mode=*Forms" />
<authorization>
<deny users=**?^' />
< / authorization
Хранение аутентификационной информации
в файле Web.config
До сих пор мы фактически не рассматривали процесс аутентификации пользователя. В этом и двух следующих разделах этот процесс рассматривается применительно к месту хранения аутентификационной информации.
Аутентификационную информацию можно хранить в конфигурационном файле Web.config. Для этого предусмотрены специальные дескрипторы <creditionals> и <user>. Например:
<authentication mode3"Forms*>
<fonns
name= "AuthCred" loginUr 1=nLoginPage.aspx* timeout=,*3 0,,>
<cx,edltionalB passwordFormat= "Clear" >
vues name="Sasha" password3nSecretM/>
<user name=(,01gaH password=н secretп / >
</creditionals>
“forms〉
</authentlcatlon>
Хранение паролей в незашифрованном виде опасно, так как файл Web.config может быть доступен любому, кто работает с веб-сервером. Для шифрования паролей используется метод HashPasswordForStoringlnConf igFile класса FornisAuthetication, который принимает два строковых параметра (пароль и название алгоритма шифрования) и возвращает хеш-код пароля.
ПРИМЕЧАНИЕ
Хеш-кодом называется последовательность шестнадцатеричных цифр, которая однозначно определяет зашифрованный текст, но не позволяет узнать этот текст.
Существует несколько алгоритмов получения хеш-кода. Наиболее устойчивыми к дешифрированию считаются алгоритмы MD5 н SHA1, Именно эти алгоритмы можно указывать при обращении к методу HashPasswordForStoringlnConf igFile и в атрибуте passwordFormat дескриптора <creditionals>. Вот как выглядит файл Web.config при шифровании паролей алгоритмом MD5:
<credltlonale passwordFormat="MD5н>
<ueer паше=иSasha"
password="lE6947AC7FB3A9529A9726EB692C8CC5"/>
<user name= "Olga1'
раззмогй=м5ЕВЕ2294ЕСО0Е0Е08ЕАВ7690О2АбЕЕб9и/> </credltlonals>
Обратите внимание на любопытную особенность хеширования: в данном случае пароли обоих пользователей различаются лишь регистром первой буквы» тем не менее они порождают совершенно разные хеш-коды.
Оба алгоритма дают код одной и той же длины, независимо от длины кодируемого пароля: 20 байт для SHA1 и 16 байт для MD5. С помощью проекта Chl5\Hash.dpr вы сможете получить хеш*код для любых пароля и алгоритма хеширования. После создания списка пользователей и их паролей в файле Web.config их аутентификация сводится к вызову логической функции Authenticate класса FormsAuthentication, которая принимает в качестве двух строковых параметров регистрационное имя пользователя и его пароль н возвращает True, если данные пользователя обнаружены в файле Web.config (проект Qjl5\F^rmsAuth\AuthCredit.dpr). Несмотря на простоту реализации, размещение регистрационной информации в файле Web.config в серьезных проектах практически не используется. Связано это с двумя обстоятельствами. С одной стороны, файл Web.config не защищен от несанкционированного доступа и может быть случайно или намеренно поврежден. Вторая и главная причина — трудности администрирования: администратор должен вручную изменять файл при добавлении очередного пользователя или его удалении.
Хранение регистрационной информации в XML-файле
Размещение регистрационной информации в XML-файле сопряжено с теми же недостатками, что и ее хранение в файле Web.config. Тем не менее далее кратко описываются методика создания XML-файла и его использование для аутентификации.
Для создания и редактирования XML-файла подойдет любой текстовый редактор, например Блокнот Windows или текстовый редактор среды Delphi. Сотдайте с его помощью такой файл:
<users>
<user>
<name>Sasha</name>
<password>Secret</password>
</ивег>
<user>
<name>Olga</xiame>
<paBBword>secret</password>
</user>
</users>
В отличие от файла Web.csnfig, хранить такой файл можно в любой папке. В следующем примере (проект Chl5\f=ormsAuthXML.dpr) показано использование файла: implement at ion uses System.Web.Security, System.IO;
procedure TWebForm2.Buttonl_Click(sender: System.Object; e: System.EventArgs);
var dsusers: DataSet; fsUsers: FileStream; srUsers: StreamReader; drArray: array of DataRow; S: String;
begin
// Проверяем заполнение полей:
if (tbUserName.Text <> * *) and
(tbPassword.Text <> '') then begin
// Создаем поток ввода ;
fsUsers := FileStream.Create(Server.Mappath(
* users.xml•)# FileMode.Open, FileAccess.Read); try
〃 Создаем набор данных: dsUsers := DataSet.Create; / / Создаем объект Streajn^eader: srUsers := StreamReader.Create(fsUsers)7 // Читаем файл в набор данных; dsUsers.ReadXML(srUsers);
// Выбираем нужную запись:
drArray := dsUsers.Tables[0].Select(
System.&String.Format('name=,'{0}*'1,
tbUsername.Text));
finally
fsusers.Close;
end;
// Сравниваем пароли:
if System.&Array(drArray).Length > 0 then
begin
S := String(drArray[0][* password1]);
if S = tbPassword.Text then
FormsAuthentication.RedirectFromLoginPage(
CbUserName.Text, false);
end;
end;
end;
Даже беглый анализ показывает, что более сложная, чем в предыдущем случае, аутентификация не дает никаких преимуществ.
Хранение регистрационной информации в БД
Наиболее часто регистрационная информация хранится в таблицах серверной базы данных. Главными достоинствами такого подхода являются высокая защищенность конфиденциальной информации и довольно простое ее администрирование. Например, не составляет особых проблем создание страниц для регистрации новых пользователей и автоматического занесения новой регистрационной информации в БД.
В следующем примере (проект Chl5\FormsAuthBD.dpr) для хранения регистрационной информации используется небольшая таблица users БД IB.BIBLgdb. В этой таблице определены два строковых поля — user_name и passwrd (слово password является зарезервированным для сервера InterBase и не может использоваться для именования полей). К проекту присоединены компонент BdpCormect ionl, настроенный на связь с БД, компонент BdpCommandl, ссылающийся в своем свойстве Connection на компонент BdpConnectionl, и компонент DataSetl. Работа с регистрационной информацией осуществляется следующим образом:
procedure TWebForml.Buttonl_Click(sender: System.Object;
e: System.EventArgs);
var
S: String;
begin
BdpCormectionl.Close; // Закрываем соединение
// Формируем команду выборки нужного имени:
BdpCommandl.CommandText :=
* select passwrd from users where user_name= * *' +
tbUserName.Text + ' * '';
BdpCormectionl.Open;
// Выполняем команду:
S := System.&String(BdpCoinmandl.ExecuteScalar);
BdpConnectionl.Close;
〃 Сравниваем пароли:
If S = tbPassword.Text then
FormsAuthentication.RedirectFromLoginPage{
tbUserName.Text, false); end;
Аутентификация по паспорту
Аутентификация по паспорту представляет собой централизованную услугу аутентификации в Веб, предоставляемую некоторыми крупными производителями всем желающим на бесплатной основе. Наибольшую известность получила служба Microsoft Passport (далее — просто Passport), которой на сегодня пользуются уже около 200 млн пользователей во всем мире.
ПРИМЕЧАНИЕ
Чтобы создать веб-узел, поддерживающий аутентификацию по паспорту, надо стать сертифицированным партнером Microsoft и получить пакет Passport SDK. Годовая стоимость участия в программе Microsoft Certified Partner едина для всех компаний, не подлежит дополнительным скидкам или согласованиям и составляет для российских компаний 1610 долларов США (без учета НДС). Дополнительную информацию можно получить в ЗАО <Экоинвент» по тел. (095) 916-71-14,
Безусловным достоинством аутентификации по паспорту является возможность свободного перемещения между иеб-узлами без повторной регистрации (если, разумеется» узлы поддерживают технологию Passport). Платформа КЕТ обеспечивает полную подцержку паспортов при помощи модуля PassportAutenticationModule. Чтобы разрешить аутентификацию по паспорту, в файл Web.config необходимо поместить следующую информацию:
<authentication mode="Passportn >
<passport redireetUrl="Login.aspx" />
< /authent lcatioxi>
Программирование 屮 приложении “您寸
ASP.NET宀
В этой главе обсуждаются некоторые общие вопросы создания приложений ASP.NET. В частности, рассматриваются популярные объекты и классы» а также механизм управления состоянием вида приложения.
Объекты и классы приложений ASP.NET
Далее в этом разделе рассматриваются наиболее важные для программиста классы и их свойства.
Класс Раде
Одним из важнейших объектов приложения ASP.NET является объект Page, представляющий собой экземпляр класса TWebForm, объявленного в pas-файле. Этот класс является наследником класса System. Web. UI. Page и инкапсулирует все особенности конкретной веб-формы.
Свойства класса System.Web.UI. Page представлены и табл. 16.1.
Таблица 16.1. Свойства класса System.Web. Ul.Page
Свойство
Описание
property Application:
HttpApplicationScate;
Содержит объ(?кт-пр騎力сжсннс Application
property Cache: Cache;
Содержит объекп Cache приложения
property ClientTarge: String;
Указывает условное имя браузера клиента
property EnableViewState:
Возвращает True, если страница сохраняет
Boolean;
свое состояние вида
Объекты и классы приложен加 ASP.NET 469
Свойство
Описание
property ErrorPage: Strting;
Содержит имя страницы, которую будет использовать браузер для отображения ошибок
property IsPostBack: Boolean;
Содержит False, если страница загружена впервые
property IsValid: Boolean;
Содержит True, если все компоненты коллекции Validators успешно завершили свою работу
property Request: HttpRequest;
Содержит запрос клиента
property Response: HttpResponse; Содержит ответ на запрос клиента
property Server:
HttpServerUtility;
Содержит объект Server
property Session: HttpSessionState;
Содержит объект Session
property SmartNavigation:
Разрешает/запрещает «умную* навигацию
Boolean;
между страницами (см. далее)
property Trace: TraceContext;
Содержит объект TraceContexct с помощью которого можно прослеживать процесс создания страницы ответа
property User:IPrincipal;
Содержит информацию о пользователе, запросившем данную страницу
property Validators:
Содержит ссылку на коллекцию контроли-
ValidatorCollection;
рующих элементов, расположенных иа данной странице
property Viev?StateUserKey :
Усганавливает ID пользователя в перемен-
String;
ную состояния вида, чтобы блокировать попытку однократного щелчка для доступа к ресурсу
Как видно из таблицы» многие свойства класса являются объектами других классов, что требует пояснения.
Свойство Application объединяет совокупность файлов, сеансов, запросов, обработчиков и модулей в виртуальном каталоге приложения и всех его подкаталогов. Этот объект создается в ответ на каждый запрос конкретного URL-адреса в данном виртуальном каталоге и не разделяется с возможными другими запросами. Свойство Cache содержит буферную память (кэш) объекта Application. Размещение страниц или их частей в буферной памяти в ряде случаев помогает сэкономить время ответа на запрос пользователя.
Свойство ClientTarge может содержать одно из следующих значений:
ie5 — страницу можно обрабатывать браузером Internet Explorer 5.5 и выше;
ie4 — страницу можно обрабатывать браузером Internet Explorer 4.0;
uplevel — страницу можно обрабатывать браузером Internet Explorer 4.0 и более ранним;
downlevel — страницу можно обрабатывать браузером более ранним, чем Internet Explorer 4.0.
Кроме того, в свойство можно помещать значение, описанное в файле Web.config. Например:
<configuration>
<8yetem.wab>
<clientTarget>
<add alias="ie302" useragent="Mozilla/2.0
(compatible; MS工E 3.02; Windows NT 3.5)" />
</alientTarget>
</system. web>
</configuration>
В этом фрагменте описывается Internet Explorer 3.02.
Свойства Request, Response, Session очень часто используются в программном коде и поэтому описываются в этой главе отдельно (см., соответственно, разделы «Класс HttpRequest>, <Класс HttpResponse» и «Управление состоянием на уровне сеансам).
Свойство Server класса Раде определено как объект класса HttpServerUtility. Этот класс содержит два свойства и несколько методов, которые дают вспомогательные средства для обработки запроса пользователя.
Если в свойство SmartNavigation поместить значение True» навигация по страницам будет происходить со следующими особенностями:
устраняется излишнее мелькание изображения;
поддерживается постоянство позиции прокрутки при возвращении к ранее покинутой странице;
поддерживается постоянство фокуса ввода при возвращении к ранее покинутой страшще;
в списке посещенных страниц окна просмотра сохраняется только URL-адрес последней страницы.
Свойство Trace облегчает отладку приложения. Если Trace • IsEnabled имеет значение True, программист может использовать метод Trace.Write, чтобы вывести в окне трассировки информацию о текущем состоянии приложения, как показано на рис. 16.1 (проект Chl6\Trace\Trace.dpr).
Это окно создано таким обработчиком:
procedure TWebForml.Page_Load(sender: System.Object; e: System.EventArgs);
begin
Trace.IsEnabled := True;
Trace.Write(bellow*); end;
QkHntfi fiJTF-8JQkHntfi fiJTF-8J(ri d'H и ICC <■(ri d'H и ICC <■упЬаЗ! vk20vH»55<]D4dsk«S 09,08,2005 14:39:50 Юнм^од (UTF-е)упЬаЗ! vk20vH»55<]D4dsk«S 09,08,2005 14:39:50 Юнм^од (UTF-е)Идентификатор сеанса: время запроса: Кадированив запроса:Идентификатор сеанса: время запроса: Кадированив запроса:■■*1**. 4^httpJ/bc4hostnrace/w«№ormi.ая«■■*1**. 4^httpJ/bc4hostnrace/w«№ormi.ая«■;■■ >;:;;》<ййа#入;% …£'■;■■ >;:;;》<ййа#入;% …£'.Ига*,Connection.Ига*,Connection
QkHntfi fiJTF-8J
QkHntfi fiJTF-8J
(ri d'H и ICC <■
(ri d'H и ICC <■
упЬаЗ! vk20vH»55<]D4dsk«S 09,08,2005 14:39:50 Юнм^од (UTF-е)
упЬаЗ! vk20vH»55<]D4dsk«S 09,08,2005 14:39:50 Юнм^од (UTF-е)
Идентификатор сеанса: время запроса: Кадированив запроса:
Идентификатор сеанса: время запроса: Кадированив запроса:
■■*1**. 4^httpJ/bc4hostnrace/w«№ormi.ая«
■■*1**. 4^httpJ/bc4hostnrace/w«№ormi.ая«
■;■■ >;:;;》<ййа#入;% …£'
■;■■ >;:;;》<ййа#入;% …£'
.Ига*,
Connection
.Ига*,
Connection
Тип запроса:
Код СОС1ОЯНИЯ;
Кадирооаниа ответа:
l/il <<|l<J|;'1i 11 l.-1>1 1р.н < . '[leu iig-
№*OX2遂;心馋臓死/садрЙ3Й畤綬,*工《范鬲[笃曲〈、、"3NR.粛騎濮擁解响(窜»:学;*.:;・:・『,:7泌油鹤!询解脓敝飞:"*::脸袋密1”咨,
aspx’peq*Begin PrtRender0,0001640,000164
aspx pageEnd PrePenderO.ODOJtOOQUUC%
•$fix.pai}»Begtn SaveViewStet*0,000791U.G0OS31
aspx.pa銀End SavO^rewState0,0027290,001937
arpx.p*ge8・gin Render0,0028650,000137
asp> pageEM Render0,3 765496 3736 8 3
Ж®^ К 二式二:二吕9М
Я^й^.йййи@4й>ёгйм»|к < х>;&6^^йвни»п$в1Кт&*《б«,:1М>ч1фмих
■■■ ов^йж血)
PAGE
ASP.WebForrnl 9 5A
372
20
Ctll
Systim.web.Ul.Liter «icontrot
164
_CtlD
System Weti.VI.wtmlConirolf,H:n*IFan*i
】84
0
_ctt2
Svsteni.Web.ui.uttraicontroi
7
0
_ctl.3
System.Web.ul utvraKontrol
24
0
lyi<-pfHu yi Ip.-tltflfth'M
'Ии*'■….м…….“<「"「4***:,:“「£…,7、ЕашА'йхй
ASP NET_Ses«onIdvng3lvk20vlle5sqp4“ks3
Kl,r“1CKl|/" I.» (>ЛПНК(Я<
.^^nwft<«rrp«csn>
Рис. 16.1. Окно трассировки
Заметьте: по умилчамию трассировка отключена, поэтому первый оператор включает ее. Если этого не сделать, окно останется пустым.
Свойство User описано как объект, исполняющий интерфе1(с IPrincipal. В интерфейс входит метод IsInRole, который возвращает True, если для пользователя определена указанная роль. Кроме того, интерфейс имеег свойство Identity, которое представляет собой регистрационный билет пользователя (особенности использования свойства User описаны в главе 15).
Класс HttpRequest
Свойство Request объекта Раде относится к классу HttpP.equesu. Этот класс предназначен для описания параметров запроса. Его свойства представлены в табл. 16.2.
Таблица 16.2. Свойства класса HttpRequest
Свойство
Описание
property AcceptTypes : array of
Определяет, какого гл па сообщения может
Strng;
принимать клиент
property AppI LcarionPath:
String;
Содержит виртуальныii катхчог приложения
Таблица 16.2 (продолжение)
Свойстао
Описание
property Browser:
HttpBrowserCapabilites;
Содержит объект, описывающий возможности клиентского браузера
property Clientcertificate: HttpClientCertificate;
Содержит объект, описывающий сертификат безопасности клиента
property Cookies:
HttpCookieCollection;
Открывает доступ к объектам Cookie клиента
property
CurrentExecutionFilePath:
String;
Содержит имя виртуального каталога и имя исполняемого файла
property FilePath: String;
Содержит имя виртуального каталога и имя исполняемого файла
property Files:
HttpFileCollection;
Содержит присоединенную к запросу коллекцию файлов
property Filter: Stream;
Содержит фильтр для чтения входного потока
property Headers:
NameValueCollection;
Содержит коллекцию НТТР-заголовков
property HTTPMethod: String;
Содержит HTTP-метод запроса
property InputStream: Stream;
Поток, содержащий тело запроса
property IsAuthenticated:
Boolean;
Содержит True, если клиент прошел аутентификацию
property IsSecureConnection: Boolean;
Содержит True, если клиент использует протокол повышенной секретности
property Item: String;
Возвращает указанный объект в коллекциях Cookies, Form, Querystring, Servervariables
property Params:
NameValueCollection;
Содержит все члены коллекций Cookies, Form, QueryString, Servervariables
property Path: String;
Содержит виртуальный каталог и исполняемый файл
property
PhisicalApplicationPath: String;
Содержит полный путь к исполняемому файлу
property PhisicalPath: String;
Содержит полный путь к запросу
property QueryString:
NameValueCollection;
Возвращает коллекцию переменных запроса
property RawURL: String;
Возвращает виртуальный каталог и исполняемый файл запроса
property RequestType: String;
Возвращает тип запроса
Свойство
Описание
property Servervariables:
NameValueCollection;
Возвращает все серверные переменные запроса
property To匸alBy匸巳s: Integer;
property URL: Uri;
O6uiee количество байтов в запросе
Возвращает информацию о текущем URL- адресе
property URLP.eferrer: Uri;
Возвращает ин(|юрмацию об URL-адресс. с которого клиент перешел »а текущий URL-адрсс
property UserAgent: String;
Возвращает информацию об агенте браузера
property UserHostAddress:
String;
property UserHostName: Strimg;
Возвратает IP-адрес клие1гга
Возвращает DNS-имя клиента
property UserLanguages: array
o£ String;
Возвращает отсортированиый набор строк с указанием предпочитаемых языков
Обработчик, представленный в листштге 16.1 (проект Chl6\RequestPropDemo\Request-
PropDemo.dpr), иллюстрирует некоторые свойства объекта Request (рис. 16.2).
0 ”,L ©时阑心;?,5
*<f 彌 g/Aoc4»estJH*quMtfrgf£*n«AV灯"I"»
Арр1leat LonPatb1 /RequeatPropDeeo
CueEcatZxeturiouTiliPa^hi / ЯаquestPeofDkrq/SebFoml .«ирк Fll*Patb> УПациевьРгорВсво/Vetarorml.aapx Pathlatot
Pachi /Re<rue3tPcopDc*o/VebF<icnl.Mpx
Phy・ic・lPazht ei、inetpub\ vv*r«)c\KecnJcacPcopI»sinO\ Vcbroml .*3px PbyjticalAppllcatiQnPech: u:\ ln«cpub\ ・*Yroot\ RequestРсорРево^ UserBosvAddreaa: 12*7.0.0.1 UBecSostMon*: 111.0.0.1
ШКФиЦИЯ。ЗАПРОСЕ: QuvryScrla0> Uuetrflcring 'Nue': Qu«cyScring 'Stace1i BTTPaethod: GET Hee4etBi Canaeccian : Kicp-AXlv« Accept : •/• Acc«pt-E&coditm i defl・c・ Accepc-L*&9U*9< t ru №»t i LocMlhnst
UMC-lgeet : HoclXla/4.0 (canpatiblc; H3IZ в.О; UUuiovs KT 5.1; SV1; .ИТ CLR 3.1.4Э22)
ASF.NtT^ScSBlonld i
uKjmjATK :apl,hVsical_patm I▲E二EE 1 "▲E~uaR :uKjmjATK :apl,hVsical_patm I▲E二EE 1 "▲E~uaR :AE PA3SVOHS 1LOGCS_US£R :REBOlijJSER :AE PA3SVOHS 1LOGCS_US£R :REBOlijJSER :Рис. 16.2. Некоторые свойства объекта RequestРис. 16.2. Некоторые свойства объекта Request
uKjmjATK :
apl,hVsical_patm I
▲E二EE 1 "
▲E~uaR :
uKjmjATK :
apl,hVsical_patm I
▲E二EE 1 "
▲E~uaR :
AE PA3SVOHS 1
LOGCS_US£R :
REBOlijJSER :
AE PA3SVOHS 1
LOGCS_US£R :
REBOlijJSER :
Рис. 16.2. Некоторые свойства объекта Request
Рис. 16.2. Некоторые свойства объекта Request
Листинг 16.1. Отображение некоторых свойств объекта Request
procedure TWebForml.Page„Load(sender: System.Object; e: System.EventArgs);
var NaineValCol: NameValueCollection; StrArray: array o£ String; i: integer; begin Response.Write('<code>*);
// Клиент может запросить информацию о сервере; Response.Write(•ИНФОРМАЦИЯ О СЕРВЕРЕ: <br>*); Response.Write(System.String.Format(
'Applicationpath: {0} <br>•, [Request.Applicationpath]));
Response,Write(System,String.Format( 1CurrentExetutionFilePath: {0} <br>1, [Request.CurrentExecutionFilePath]));
Response.Write(System.String.Format(1FilePath: {0} <br>1, [Request.Filepath])};
Response.Write(System.String.Format('Pathinfo: {0} <br>', [Request.Pathinfo]));
Response.Write(System.String.Format(1 Path: {0} <br>1, [Request.Path]));
Response.Wr i t e(System.S tring.Format(
* PhysicalPath: {0} <br>*, [Request.PhysicalPath])};
Response.Write(System.String.Format( 'PhysicalApplicationPath: {0} <br>*, [Request.PhysicalApplicationPath]));
Response.Write(System.String.Format(
*UserHostAddress: {0} <br>*, [Request.UserHostAddress]));
Response.Write<System.String.Format(
*UserHostName: {0} <br>*, [Request.UserHostName]));
// Информация о запросе:
Response.Write('<br>*);
Response.Write(* ИНФОРМАЦИЯ О ЗАПРОСЕ: <br>*);
Response.Write(System.String.Fonnat('Querystring: {0}<br>* f [Request.Querystring]));
Response.Write(System.String.Format(
* Querystring —Name' * : {0}<br>', [Request.Querystring[*Ыате*]]));
Response.Write(System.String.Format( 'Querystring '* State'': {0}<br>', [Request.Querystring{'State']]));
Response.Write(System.String.Format(*HTTPMethod: {0} <br>', [Request.HTTPMethod]));
Response.Write(•Headers:<br>'};
NameValCol := Request.Headers;
StrArray := NameVaICol.Al1Keys;
for i := Low(StrArray) to High(StrArray) do
Response.Write(System.String.Format(1{0) : {1} vbr>',
[StrArray[i], Request.Headers.Item[StrArray[i]]]));
Response.Write(* <br>1);
Response.Write('Params:<br>');
NameValCol := Request.Params;
StrArray := NameValCol.AllKeys;
for i := Low(StrArray) to High(StrArray) do
Response.Write(System.String.Format('{0} : {1} <br>1,
[StrArray[i], Request.Headers.Item(StrArray[i]]]));
// Информация о браузере клиента;
Response.Write((<br>*);
Response.Write(•ИНФОРМАЦИЯ О БРАУЗЕРЕ:<br>*);
Response.Write(System.String.Format(*Typet {0}<br>1y
[Request.Browser.&Type.ToString]));
Response.Write(System.String.Format('Version: {0}<br>', [Request.Browser.Version]));
Response•Write(System.String.Format('ClrVersion: {0}<br>*, [Request * Browser.ClrVersion.ToString]));
Response.Write(System.String.Format('Platform: {0}<br>*, [Request.Browser.Platform]));
Response.Write(System.String.Format(* Frames: (0}<br>1, [Request.Browser.Frames.ToString]));
Response. Write ( 1 </cocle>,);
end;
Класс HttpResponse
Свойство Response объекта Page относится к классу HttpResponse. Этот класс предназначен для описания параметров ответа на запрос пользователя. Его свойства представлены в табл. 16.3.
Таблица 16.3. Свойства класса HttpResponse
Свойство
Описание
property Buffer : Boolean;
Содержит True, если ответ кэшируется
property Cache : HttpCachePo 1 isy;
Содержит объект HttpCachePolisy с информацией о кэшированной^ части ответа
property CacheControl: String;
Определяет способ использования кэша и может 1финимать значение Public или Private
property Charset: String ;
Содержит название набора символов ответа
property ContentEncodind: Encoding;
Содержит объект Encoding с информацией о на&ре символов ответа
Таблица 16.3 (продолжение)
Свойство
Описание
property ContentType : String ;
Содержит niii OTBeia По умолчанию — *'Text/
HTML"
property Cookies:
Содержит связанную с ответом коллекцию
Ht tpCookieCollection;
объектов HttpCookie
property Expires:Integer;
Содержит время хранения ответа в буфере в минутах
property ExpiresAbsolute:
Содержит время и дату удаления из кэша кэ-
DateTime;
тированной информации ответа
property Filter: Stream;
Содержнт поток для фильтрации ответа
property IsClientConnected:
Содержит True, если клиент соединен с сер-
Boolean;
вером
property Output: Textwriter;
Содержит объект Textwriter с ответом кли* енту
property OutputStream: Stream;
Содержит ссылку на поток с ответом клиенту
property RedirectLocation:
Содержит URL-адрес, передаваемый клиенту
String;
в строке заголовка
property Status: String;
Содержит строку статуса, возвращаемую в ответ на запрос клиента. По умолчанию - "200ОК"
property StatusCode: Integer;
Содержит код статуса, возвращаемый в ответ на запрос клиента. По умолчанию — 200 ("ОК")
property StatusDescription:
Содержит строку статуса, возвращаемую в от-
String;
вст на запрос клиента. По умолчанию — ИОК"
property SuppressContent:
Содержит True, если ответ будет посылаться
Boolean;
клиенту
Свойство Response объекта Раде используется в основном в трех случаях: для программной передачи HTML-информации пользователю, для фильтрации ответа и для его переадресаоди.
Для передачи HTML-информации используется метод Wri t е класса Ht tpResponse. Рассмотренный ранее пример отображения некоторых свойств объекта Request наглядно демонстрирует эту возможность (см. листинг 16.1).
Фильтрация данных в общем случае затруднена» так как символьный тип Char хранит символ Unicode и не может преобразовываться в целочисленные типы1. Фильтрация же обычно сводится к некоторым манипуляциям над символами, требующими преобразования символьного типа в число и наоборот. Для строк» содержащих только символы с кодами от Одо 127 включительно, символ Unicode
В языке Visual Basic .NET определена функция AscW, которая преобразует символ Unicode в значение типа Word, но в общей системе типов (и Delphi) такой функцин нет.
совпадает с однобайтным символом ASCII, который может преобразовываться в значение типа Byte функцией Delphi ord.
В листинге 16.2 (проект Chl6\ResponseFilter\ResponseRlter.dpr) все символы текста ответа преобразуются в прописные.
Листинг 16.2. Преобразование в верхний регистр всех символов текста ответа unit WebForml ; interface uses
System.Collections, System.ComponentModel, System.Dana, System.Drawing, System.Web, System.Web.Sessionstate, System.Web.UI, System.Web.UI.WebControls, System.Web.UI.Htmlcontrols, System.Ю; // В этом пространстве имен объявлен класс Stream
type
TWebForml = class(System.Web.UI.Page) strict private procedure Page_Load(sender: System.Object; e: System.EventArgs); strict protected procedure Onlnit(e: EventArgs); override;
private f Private Declarations 丿 public { Public Declarations 丿 end;
TFilter = class (MemoryStream) / / Класс для фильтрации private MemStream: Stream; public constructor Create(aStream: Stream); override; procedure Write(Bfr: array of Byte;
Offset, Count: Integer); override; end;
implementation
procedure TWebForml.InitializeComponent; begin Include(Self.Load, Self.Page_Load);
exid;
procedure TWebForml.Onlriit (e: EventArgs); begin
InitializeComponent;
Листинг 16.2 (продолжение)
inherited Onlnit(е); end;
procedure TWebForml.Page.Load(sender: System.Object;
e: System.EventArgs); begin
// Заменяем свойство Filter новым потоком:
Response.Filter := TFilter.Create(Response.Filter);
// Выводим строку ответа fтолько латиница.!) г
Response.Write(1Delphi 2005 for .NET Framework<br>*); end;
{ TFilter ,
procedure TFilter.Write(Bfr: array of Byte;
Offset, Count: Integer); // Используемое в процедуре преобразование регистров // возможно только для латиницы! var Data: array of Byte; k: Integer;
Delta.: Integer; begin
inherited;
Borland.Delphi.System.SetLength(Data, Count);
Buffer.BlockCopy(Bfr, Offset, Data, 0( Count);
Delta := ord (*A') - ord(1 a *);
for k := 0 to Count - 1 do
if (Data[k] >= ord(* a')) and (Data[k] <= ord(* z *)) then
Data[k] Data[k] + Delta;;
MemStream.Write(Data, 0, Count); end;
constructor TFiIter.Create(aStream: Stream); begin
inherited Create;
MemStream := aStream; end;
end.
Для переадресации запроса используется метод Redirect. Например:
Response.Redirect('http:7/DelphiKingdom.com1);
Состояние вида
Состояние вида (view state) — это механизм ASP.NET, с помощью которого отслеживаются текущие значения свойств серверных элементов управления. Благодаря
этому механизму можно восстановить вид страницы, которая уже посещалась ранее, причем не обязательно в том же сеансе связи с сервером. Обычно для сохранения информации состояния вида используется скрытое поле _ViewState, которое автоматически создается сервером и размещается в странице ответа на запрос пользователя. Но состояние вида можно также сохранять в наборе состояний страницы или отдельного элемента, в объектах Session и Application, на специальном сервере состояний и даже на SQL-сервере. В этом разделе обсуждаются различные способы хранения состояния вида.
Поле _ViewState
Стандартная веб-страница» создаваемая в Delphi 2005, включает директиву Раде следующего вида:
<%@ Page language="c#" Debug-"true* Codebehind="WebForml.pas" AutoEventWireup= * false" Inherits-"WebForml.TWebForml" %>
В этой директиве отсутствует атрибут EnableViewState, который, таким образом, получает умалчиваемое значение True. В результате стандартная веб-страница автоматически настраивается на создание и использование поля _ViewState.
Поле _ViewState работает следующим образом. Данные, введенные пользователем в веб-форму, передаются на сервер как часть команды POST или GET протокола HTTP. Сервер упаковывает эту информацию в скрытое поле _ViewState и возвращает браузеру как часть ответа. Например:
<input type=nhidden" name= ”VIEWSTATE"
value= ndDw2MDM5MTc5OTA7Oz76vVjs6ZlVGNd8+CxSPPVuouWK5A= = w />
ПРИМЕЧАНИЕ
Чтобы увидеть скрытое поле, нужно в браузере выбрать команду Вид ► Просмотр HTML- кода.
Клиентский браузер игнорирует эту информацию, но отсылает ее серверу при последующих запросах.
Поле _viewState может хранить довольно большой объем информации, в особенности для сложных страниц, насыщенных серверными элементами управления. Чтобы уменьшить объем информации, которой обмениваются браузер клиента и сервер, это поле можно отключить. Для этого в директиву Раде следует добавить такой атрибут:
EnableViewState="False"
Эта директива отменяет необходимость хранить состояние вида для страницы в целом. Но можно отключать этот механизм и для отдельного элемента управления. Для этого в окне инспектора объектов нужно свойству Enab 1 еVi еwSt at е элемента присвоить значение False.
Управление состоянием на уровне сеанса
Управление состоянием на уровне сеанса начинается при входе пользователя на сайт и завершается при его выходе.
Когда пользователь посещает сайт, ASP.NET создает для него специальный объект Session (сеанс) класса HttpSessionState. Кроме того, пользователю присваивается уникальный идентификатор, который передается его браузеру и возвращается серверу при каждом запросе в течение сеанса* По умолчанию для этого используется механизм cookie.
Сеанс остается в памяти до тех пор, пока пользователь не покинет сайт или пока не закончится отведенное для него время (по умолчанию — 20 минут).
Информацию сеанса поддерживает так называемый провайдер состояний, который может работать в одном из след)гющих режимов:
InProc — данные сеанса хранятся в том же самом домене, что и приложение ASP.NET, то есть внутри контекста процесса aspnet_wp.exe (этот режим принят по умолчанию);
stateserver — данные сеанса хранятся в контексте службы aspnet_state.exe Windows» которая может выполняться на Toit же машине, что и сервер, или в ее сетевом окружении;
SQLServer — данные сохраняются в таблице базы данных;
Off — данные сеанса не хранятся.
Для добавления данных в объект Session используется его метод Add:
Session.Add(^serName', TextBoxl.Text);
Чтобы получить данные, нужно обратиться к ним по имени, например:
Response.Write('Welcom 1 + Session!'UserName*].ToString);
Или:
TextBoxl.Text := Session['UserName'].ToString;
В объекте Session можно хранить данные любого типа:
Session.Add('MyDataset', DataSetl);
Для удаления данных используется метод Remove:
Session.Remove('MyDataSet');
Изменение умалчиваемого времени сеанса
По умолчанию на сеанс отводится 20 минут, после чего объект Session (и вся хранимая в нем информация) уничтожается. С помощью дескриптора < see в ionSt ate> конфигурационного файла Web.config можно изменить это время:
<con£iguration>
system.web>
<8esslonSt&te timeout=*'60,,/>
/ system. web>
< / egf igurat lg>
Сеансы без cookie
Как правило, идентификатор сеанса сохраняется в файле cookie браузера клиента. Однако пользователь может запретить использование cookie (для браузера IE с помощью команды Сервис ► Свойства обозревателя нужно открыть окно свойств и на вкладке Конфиденциальнсхлъ передвинуть ползунок доступности cookie в крайнее верхнее положение). В этом случае идентификатор сеанса можно передавать в составе URL. Для этого в файл Web.config вставляются такие строки:
<configuration>
<syetem.web>
<seseionSt&te cookieless="true"/>
</system.web>
</conf1ffur&tlon>
Хранение данных сеанса на сервере MS SQL Server
В ASP.NET имеется возможность хранить данные сеанса на сервере MS SQL Server. Этот вариант — наименее производительный, но и наиболее отказоустойчивый. Для организации хранения информации о состоянии на сервере MS SQL Server нужно, во-первых, создать на сервере базу данных с нужными таблицами, во-вторых, настроить конфигурационный файл Web.config.
Для создания БД следует использовать один из следующих файлов сценариев: • InstallSqlState.sql — создает базы данных ASPState и TempDB, информация о состоянии сохраняется в таблицах БД TempDB и теряется при отключении сервера;
• InstallPersistSqlState.sql — создает и использует БД ASPState, информация в этой БД не теряется при отключении сервера.
Оба файла располагаются в папке Windows\Microsoft.NET\Framework\vl. 1.4322. В этой же папке расположены и файлы UninstalISqIState.sql и UninstallPersistSqIState.sql, служащие для отмены регистрации баз данных.
Для использования файлов сценариев запустите утилиту SQL Server Enterprise Manager и выберите команду Tools ► SQL Query Analyzer, В новом окне загрузите нужный файл и нажмите клавший CW+F5 или выберите команду Query ► Parse (рис. 16.3).
После создания БД нужно в файл Web.config поместить такие строки:
<configurat1оп>
<system.web>
<sessionState mode=n SQLServer•
sqlConnectionString="data source=localhost; user id=sa; pwd=passwordи/>
< / system. web>
</configuration>
16 3a工 449
+®”0.q ©• ДЬ|кА$к>мш: <.
『尹面血麻精血0运]
可而IONOV
4: 口
7
bebQed
画.,.!" :. m ;黨:.《u不二
■ 1т“ Mie 5、?;”:с м,、г*и> ”"ch).eu */
(1 сон Is) affected)
(1 rov (s) allectecll
口", GO
三gpwwt j
Рис. 16.3. Выполнение файла сценария
削彎喲I吟鮭曲
」Common ОЬцесИ it; 口J Cshguuten FsBr 4 Cj CuriOf FinClKXV
1 ; : ] Date E T e Ftrctu
♦」Xa^wnvcK Ftmtar
.口 Aggtvgate Fwdcru\ :_j McUdoU Func bcm
.帛 口 &ec*rty FunctaH
■中 ^_J Stmg Finelkom
:+ ^J Syttflfn Fundxjm .♦.二J S^tw Siatnbcd fun 十 ^_] Тей and Image Furct
+ ;_J Syite/п Dale Type»
ЛУОЙ&^^^К成
d&ya,c?国
,* ,;;,•?< U.r.Anf.'.*;, I - cctd 件彳、:% l\・ 1> 入< e.y*、:ll.Y tic K7Y 34 'u>l+At« L :, *qh "' USE master
/ • Crop 匕:ie database c©A:a,:;Li.g cur е*го:з "/
ХУ [■:; НГ,,”:еу」IS 沙::Х'7;. liEGJM
PPQF ?ЛТХ£±ЗЕ ASPStBCe
The CREATE DATABASE process la allocating 0.75 MB on diak 'iSPState*.
Th, CREATE СЛГЛВЛВЕ ргосевя le ellocaClng 0.99 SB on disk •13P3c«ce_loff>.
Управление состоянием на уровне приложения
Управление состоянием на уровне приложения во всем подобно управлению на уровне сеанса, за исключением того, что данные о состоянии оказываются доступны всем клиентам. Связано это с тем, что хранение состояния на уровне приложения реализуется экземпляром класса HttpAppli cat ionstate, который создается при первом обращении к приложению (сеанс создается при обращении к приложению каждого нового клиента).
Приложения
Сервер InterBase
Назначение и возможности
SQL-сервер InterBase предназначен для хранения и обработки больших объемов информации в условиях одновременной работы с БД множества клиентских приложений. Масштаб информационной системы при этом произволен — от уровня рабочей группы (под управлением Novell Netware, Linux или 32-разрядной версии Windows на базе IBM-совместимых персональных компьютеров) до уровня большого предприятия (на базе компьютеров IBM, Hewlett-Packard, SUN).
В этом приложении рассматриваются те технолоши InterBase, использование которых обеспечивает максимальную вычислительную разгрузку клиентского приложения и гарантирует высокую степень безопасности и целостность информации. Перечислим эти технологии:
Первичные и внешние ключи. Отношения подчиненности между таблицами БД определяются с помощью первичных ключей у родительских и внешних ключей —у дочерних таблиц.
Ограничения на значения отдельных столбцов. Условия ограничений могут быть разнообразными — от требования, чтобы вводимые значения не выходили из определенного диапазона или соответствовали некоторой маске, до требуемого отношения с одной или несколькими записями из другой таблицы (или мноптх таблиц) БД.
Триггеры. Триггеры — это подпрограммы, автоматически выполняемые сервером до или/и после события изменения записи в таблице БД.
Генераторы. Генераторы служат для создания и использования уникальных значений нужных полей (только для InterBase).
Хранимые процедуры, Для ускорения работы клиентских приложений с удаленной БД могут быть определены хранимые процедуры, которые представ-
ляют собой подпрограммы, принимающие и возвращающие параметры и способные выполнять запросы к БД, условные ветвления и циклическую обработку. Хранимые процедуры пишутся на специальном алгоритмическом языке. В них программируются часто повторяющиеся последовательности запросов к БД. Текст процедур хранится на сервере в откомпилированном виде.
BLOB-поля и BLОВ-фильтры. В составе записи БД могут определяться BLOB- поля (Binary Large OBject — большой двоичный объект), предназначенные для хранения больших объемов данных в виде последовательности байтов. Таким образом могут храниться текстовые н графические документы, файлы мультимедиа, звуковые файлы и т. д. Интерпретация BLOB-поля выполняется в приложении, однако разработчик может определить так называемые BLOB- фильтры, предназначенные для автоматического преобразования содержимого BLOB-поля к другому виду.
Пользовательские функции. InterBase дает возможность создавать пользовательские функции (User Defined Function, UDF)( в которых может реализовываться функциональность, отсутствующая в стандартных встроенных функциях InterBase (стандартные функции применяются для вычисления максимума, минимума, среднего значения, преобразования типов и смены регистра букв). Например, в UDF можно реализовать извлечение из значения даты номера дня, года, определение длины символьного значения, усечение пробелов, разные математические алгоритмы и т. п. Функция пишется на любом алгоритмическом языке, позволяющем разрабатывать библиотеки динамической компоновки (DLL), например на языке Delphi.
Уведомления. InterBase может посылать уведомления клиентским приложениям о наступлении какого-либо события. Одновременно работающие приложения могут обмениваться сообщениями через сервер БД, вызывая хранимые процедуры, инициирующие нужные события.
Виртуальные таблицы, или представления. Чтобы ускорить выполнение запросов и освободить клиентское приложение от необходимости такие запросы выдавать, в БД можно определить виртуальные таблицы, или представления (views), в которых объединяются записи из одной или более таблиц, соответствующих некоторому условию. Работа с представлением из клиентского приложения ничем не отличается от работы с обычной таблицей. Поддерживает представления сервер, реагируя на изменение данных в БД. Представления могут быть изменяемыми или не изменяемыми (не допускающими внесения в них изменений).
Некоторые технические характеристики
Сервер InterBase был разработан в начале 80-х годов в американской корпорации DEC. В дальнейшем разработка сервера велась независимой компанией InterBase Software и впоследствии слившейся с ней компанией Ashton-Tate. Корпорация Borland приобрела права на InterBase у компании Ashton-Tate после слияния с нею.
Сервер InterBase активно используется в государственном и военном секторах США, что, видимо, и стало преградой для его продвижения в Россию. Интерес к это* му серверу возрос только в последнее время в связи с включением его локальной (а начиная с Delphi 3 — и пользовательской) версии в состав Delphi Client/Server Suite и Delphi Enterprise. Внимание разработчиков БД сервер InterBase привлек, во-первых, потому, что это сродной» продукт Borland (а средства разработки приложений этой компании давно зарекомендовали себя с положительной стороны), во-вторых, потому, что сервер InterBase весьма прост в установке, настройке и администрировании по сравнению с другими SQL-серверами, и, в-третьих, потому, что он обладает прекрасными функциональными возможностями.
В табл. АЛ приводятся некоторые технические характеристики сервера.
Таблица А.1. Технические характеристики сервера InterBase
Характеристика
Значение
Максимальный размер одной БД
Рекомендуется не выше 10 Гбайт, однако известны случаи объема одной БД в 10-20 Гбайт
Максимальное количество таблиц в одной БД
65 536
Максимальное количество палей (столбцов) в одной таблице
1000
Максимальное количество записей (строк) в одной таблице
Не ограничено
Максимальная длина записи
64 Кбайт (кроме BLOB-полей)
Максимальная длина поля
32 Кбайт (кроме BLOB-полей)
Максимальная длина BLOB-поля
Не ограничена
Максимальное количество индексов в БД
65 536
Максимальное количество полей в индексе
16
Максимальный уровень вложенности SQL-запроса
16
Максимальный размер хранимой процедуры или триггера
48 Кбайт
Максимальное количество пользовательских
Длина имени UDF — не более 31 сим-
функций (UDF) в базе данных
вола, каждая пользовательская функция должна иметь уникальное имя, поэтому максимальное количество UDF ограничивается только требованием уникальности имен
Физическая организация базы данных InterBase
База данных InterBase состоит из последовательно, начиная с 0, пронумерованных страниц. Нулевая страница является служебной и содержит ин&рмацию,
необходимую для соединения с БД. Размер страницы — 1 (по умолчанию), 2, 4 или 8 Кбайт. Размер страницы задается при создании БД, но может быть изменен при сохранении и восстановлении базы. Одна страница читается сервером за один логический доступ к БД.
Объем буфера ввода-вывода для операций чтения-записи определяется в количестве страниц (по умолчанию — 75). Если БД будет чаще читаться, объем буфера следует увеличить. Если в нее будет чаще осуществляться запись, размер буфера можно уменьшить.
В InterBase для записей поддерживается режим множества версий. При изменении записи какой-либо транзакцией создается новая версия записи, куда помимо данных записываются номер транзакции и указатель на предыдущую версию записи. Старая версия помечается как измененная, а ее указатель на следующую версию записи содержит ссылку на вновь созданную версию. Каждая стартующая транзакция работает с последней версией записи, изменения для которой подтверждены. Таким образом, параллельно работающие с БД транзакции всегда используют разные версии записей, что позволяет снимать блокировки для клиентских приложений, одновременно работающих с одними н теми же данными в БД. При удалении записи она физически не удаляется с диска, а помечается как удаленная до тех пор, пока не завершатся все активные транзакции, использующие эту запись.
InterBase размещает на одной своей странице все версии одной записи таблицы БД. После удаления записей на странице образуются «дырки». При добавлении новой записи анализируется размер максимальной «дырки» и, если он меньше длины добавляемой записи, происходит сжатие страницы, в процессе которого «дырки» объединяются. Если освободившегося пространства не хватает для размещения новой записи, та записывается с новой страницы. Загрузка страницы считается нормальной в случае, если «дырки* занимают не более 20 % объема страницы.
Порядок выделения страниц для хранения данных никак не оптимизирован. На отдельной служебной странице БД хранятся номера всех свободных страниц. Для сохранения записей одной таблицы БД не предпринимается никаких действий по выделению смежных страниц, а выделяется первая страница в списке свободных. Если свободной страницы нет, добавляется новая в конец БД. Только в этом случае размер БД возрастает.
Структура записей; поддерживающая режим множества версий, и неоптимальное выделение страниц ведут к высокой степени фрагментации БД и, как следствие, к замедлению работы с ней. Поэтому необходимо периодически производить дефрагментацию БД. Дефрагментированная БД характеризуется расположением записей таблиц БД на смежных страницах и отсутствием «мусора». Под «мусором» понимаются версии записей, с которыми не работает никакая активная транзакция.
Для удаления «мусора» БД сохраняется на дисковом носителе и затем восстанавливается из сделанной резервной копии с помощью утилиты IBConsole (для предыдущих версий InterBase — с помощью утилиты InterBase Server Manager). Этот процесс гарантирует удаление всего «мусора», так как в момент сохранения
и восстановления БД обеспечивается отсутствие активных подключений к БД со стороны других пользователей, а значит, и отсутствие активных транзакций. Кроме того» в InterBase предусмотрено автоматическое удаление «мусора» на фоне активных транзакций. Интервал, через который происходит автоматическое удаление «мусора», по умолчанию составляет 20 000 транзакций. Это значение может быть изменено с помощью утилиты IBConsole. При автоматической очистке удаляются только те версии записей, для которых нет активных транзакций. В результате могут быть удалены не все старые версии.
ВНИМАНИЕ
Если довольно долго не осуществляется принудительная очистка страниц БД InterBase, это может привести к существенному (в десятки раз) снижению производительности сервера. При активной работе с БД рекомендуется производить принудительную очистку БД InterBase не реже 2-3 раз в неделю (или даже ежедневно).
Типы данных InterBase
Как уже говорилось, сервер InterBase выбран в качестве базового сервера прежде всего из-за того, что он входит в комплект поставки Delphi. Описанные в этом приложении типы данных относятся именно к InterBase, хотя многие другие SQL- серверы имеют схожие типы данных В отличие от других серверов, сервер InterBase:
не имеет автоинкрементного типа данных и компенсирует его отсутствие особым механизмом генераторов;
не имеет логического типа данных и вместо него предлагает использовать символьный тип Char (1) или VarChar (1);
не имеет денежного типа данных;
использует столбцы-массивы.
Несмотря на это InterBase как, возможно, ни один другой SQL-сервер следует промышленному стандарту SQL92. Как бы там ни было, большинство его типов данных совпадают с аналогичными типами Delphi,
Обзор типов данных InterBase
Типы столбцов, которые могут использоваться в таблицах сервера InterBase, перечислены в табл. А.2.
Таблица А.2. Типы данных сервера InterBase
Тип столбца
Размер, байт
Описание
SMALLINT
2
Целочисленные значения от -32 768 до +32 767
INTEGER
4
Целочисленные значения от -2 147 483 648 до +2 147 483 647
FLOAT
4
Вещественные числа до 7 значащих цифр в диапазоне от 3,4 • 10'38 до 3,4 • 10+38
Тип столбца
Размер, байт
Описание
DOUBLE
PRECISION
8
Вещественные числа до 15 значащих цифр в диапазоне от 1,7 • 10"308 до 1,7 • Ю+308
NUMERIC ИЛИ DECIMAL
Переменный
Вещественные числа с фиксированной запятой. При определении этого типа дополнительно указывается общее количество значащих цифр числа и количество цифр в дробной части
CHAR{n)
ИЛИ CHARACTER
0-32 767
Текстовый столбец длиной до п символов
VARCHAR(n)
ИЛИ CHAR[ACTER]
VARYING
0-32 767
Текстовый столбец переменной длины, содержащий до л символов
DATE
8
Дата в пределах от 01.01.0100 до 11.12.5941. Также может хранить сведения о времени
BLOB
Переменный
Любой тип двоичных данных
Столбцы могут определяться в SQL-операторах CREATE TABLE — создать таблицу БД, CREATE DOMAIN — создать домен и ALTER TABLE — изменить структуру таблицы.
Пример описания столбцов разного типа при определении таблицы:
CREATE TABLE MixTable(
/* столбец типа INTEGER; вместо INT можно использовать INTEGER */ Coll 工NT,
/* столбец-массив из трех значений SMALLINT */
СО12 SMALLINT[3],
/* символьный столбец длиной до 70 символов с возможностью использовать кириллицу */
СО13 VARCHAR(70) CHARACTER SET Winl251f
/* символьный столбец из одного символа со значением *Y", заданным по умолчанию; такие столбцы заменяют логический тип, если значениями являются Y, N, Т, F */
Со14 CHAR(l) DEFAULT 'Y',
/* ветцественный столбец, который не может быть пустым */
Col5 FLOAT NOT NULL,
/* вещественный столбец; его значения содержат до 12 значащих цифр, из которых 2 представляют дробную часть: 1234567890,12 */
Со16 NUMERIC(12,2))
При определении столбца с помощью спецификатора DEFAULT можно указать значение, заданное по умолчанию. В этом случае сервер автоматически поместит в столбец указанное значение, если при вводе новой записи этот столбец остался пустым:
CREATE TABLE MoveBook(..., IsDelNakl CHAR(l) DEFAULT *F')
При определении значения по умолчанию можно использовать три стандартных значения:
USER — помещает в столбец новой записи регистрационное имя пользователя БД;
"NOW* — помещает в столбец текущие дату и время;
"TODAY” — помещает в столбец текущую дату.
Обратите внимание: значение USER указывается без кавычек, в то время как два других — в кавычках.
Как видно из табл. А.2, в InterBase не определен логический тип. Вместо него можно использовать тип CHAR (1) с указанием значений типа Т, F, Y, М Д> Н, - и т. п. При переносе таблиц Paradox утилита Datapump (поставлялась с предыдущими версиями Delphi) заменяет значения True и False логического поля, соответственно, символами т и F столбца CHAR (1). Однако компонент TDBCheckBox (флажок), который обычно визуализирует логическое значение, при связи его со столбцом CHAR (1) показывает значение True независимо от содержимого столбца (даже если он содержит NULL). Происходит зто по той причине, что его свойства ValueChecked и ValueUnchecked содержат значения True и False, заданные по умолчанию. Чтобы компонент правильно отображал логические значения, в эти свойства следует поместить нужные значения. Например:
DBCheckBoxl.ValueChecked := 'Т;С;Д;д1
DBCheckBoxl.ValueUnchecked := *F;f;Н;н'
Столбцы-массивы
Столбец любого типа, кроме типа BLOB, может быть объявлен как столбец-массив. Такие столбцы вместо единичного значения содержат массив значений одинакового типа, доступ к каждому из которых возможен с помощью индекса. Для создания столбца-массива в конце его определения указывается в квадратных скобках целое число, определяющее количество элементов массива. Например:
CREATE TABLE MYTABLE (A INTEGER [3])
В этом примере столбец А будет содержать по 3 целочисленных значения в каждой записи таблицы MYTABLE. Однако следует учесть, что стандарт SQL92, которому в целом следуют InterBase и BDE, не поддерживает столбцы-массивы, поэтому, например, нельзя выполнить следующие операторы:
INSERT INTO МуTable (A[l]) Values(1) /* Недопустимый символ [ */ INSERT INTO MyTable (A) Values(1,2,3) /* Количество значений не равно количеству столбцов */
Доступ к отдельным значениям столбца-массива возможен только с помощью низкоуровневых API-функций InterBase, что затрудняет практическое использование массивов (подробное описание работы со столбцами-массивами см. в документации к InterBase).
Типы DECIMAL и NUMERIC
Типы DECIMAL и NUMERIC задают вещественные значения и определяют в них фиксированное количество знаков после запятой. Формат определения этих типов:
имя_столбца [=] {DECIMAL I NUMERIC} [(точность [, масштаб])]
Здесь точность — общее количество знаков в хранимом числе (максимум 15), масштаб — количество знаков в дробной части (может быть равен нулю). Во всех случаях масштаб должен быть меньше точности. Например:
CREATE TABLE MYTABLE (DECIMAL_COLUMN DEC工MAL(9,2))
Замечу, что специальных типов DECIMAL и NUMERIC не существует, а вместо них используется тип INTEGER или DOUBLE PRECISION: если точность (количество знаков в числе) меньше 10, то реальный тип столбца — INTEGER, если больше или равно 10, реальный тип столбца — DOUBLE PRECISION. Поскольку в столбцах типа INTEGER хранить дробные значения нельзя, то независимо от того, указано количество знаков после десятичной точки или нет, объявление DECIMAL и NUMERIC с общим числом разрядов меньшим 10 приведет к тому, что фактически в столбце будут храниться только целочисленные значения. Например, если в столбец DECIMAL_COLUMN таблицы MYTABLE (см. выше) поместить значение 123.456, фактически в таблице будет храниться число 123, а все цифры дробной части будут безвозвратно потеряны.
Тип DATE
Столбцы типа date позволяют хранить значения даты в пределах от 01.01.0100 до 11.12.5941, а также значения времени (тип DATE InterBase полностью совместим с типом TDat eTime Delphi).
Если ввод данных в столбец типа DATE производится из утилиты IBConsole, значения даты должны указываться в формате InterBase. Согласно этому формату, значения даты состоят из номера дня (01-31), месяца (JAN-DEC) и года. Эти значения отделяются друг от друга разделителями. Стандартным разделителем является символ дефиса (-), но принимаются и пробел, правый слеш (/) и точка (.). Значения дат в InterBase должны лежать в диапазоне от 1-JAN-100 до 11- DEC-5941. Интерпретация формата представления значений типа date зависит от настройки — программы или операционной системы компьютера. Полезно всякий раз при старте приложения программно переустанавливать формат даты и времени к привычному нам российскому формату:
procedure TForml.FormCreate(Sender: TObject);
begin
Dateseparator := *.';
ShortDat eFormat : = • dd. mm. yyyy * ;
ShortTimeFormat := 'hh:iran:ss‘;
end;
Таким образом можно игнорировать неопределенность текущей настройки операционной системы на конкретном компьютере.
В InterBase значения типа DATE совместимы со строковыми типами. Поэтому, если в SQL-операторах InterBase требуется интерпретировать значения типа DATE как строку, нет необходимости в приведении типов. Например, можно так записать в символьный столбец S значение типа DATE (символы I I означают операцшо конкатенации, или сцепления, строк, функция NOW возвращает текущие дату и время):
UPDATE SOMETABLE
SET S = "Дата отгрузки " I I NOW;
Кроме того, присваивание значения полям типа DATE также производится в символьном формате:
UPDATE Nakls
SET NDate = "01.01.2000h
WHERE NaklID<100
Типы CHAR и VARCHAR
Столбцы типа CHAR и VARCHAR позволяют хранить текстовые значения длиной до л символов. В любом случае п не может превышать 32 Кбайт.
Как сказано в документации, тип CHAR (п) определяет текстовые столбцы фиксированной длины. Определение «фиксированная длина» означает, что даже если в столбец записано меньше п символов, незаполненное пространство заполняется пробелами. При хранении завершающие пробелы удаляются, что позволяет хранить действительно значащее содержимое столбцов типа CHAR (п) и сближает их со строками переменной длины. При чтении значения столбца завершающие пробелы вставляются в столбец снова.
ПРИМЕЧАНИЕ
Опытным путем нетрудно выяснить, что Delphi при работе с InterBase интерпретирует столбцы типа CHAR и VARCHAR как TStringField При этом, во-первых, столбцы типа CHAR всегда читаются без завершающих пробелов, во-вторых, при занесении завершающих пробелов в столбец (а часто это бывает необходимо) типа CHAR они всегда удаляются, в то время как в столбце типа VARCHAR, наоборот, они всегда хранятся.
Тип VARCHAR (п) определяет текстовые столбцы переменной длины. Определение «переменная длина» означает, что в записи хранится ровно столько символов, сколько их имеется в значении столбца. Например, если для VARCHAR (100) значения столбцов в одной записи — «Петров», а в другой — «Барабанова, в первом случае хранится 6 символов, а во втором — 9. Столбцы VARCHAR (п) позволяют экономить дисковое пространство, давая возможность серверу располагать больше записей на странице БД, однако они читаются медленнее, чем CHAR(n).
Попытка записать в столбец CHAR (VARCHAR) более чем п символов приведет к удалению лишних символов.
Формат определения текстовых столбцов:
имя_столбца [=] (CHAR I CHARACTER I CHARACTER VARYING I VARCHAR}
[(n)] [CHARACTER SET набор_символов]
Здесь п определяет длину текстового столбца. Если аргумент п опущен, по умолчанию подразумевается 1.
Спецификатор CHARACTER SET позволяет установить кодировку путем указания имени применяемого набора символов. Если спецификатор CHARACTER SET опущен, используется кодировка» принятая по умолчанию для БД (устанавливается в предложение DEFAULT CHARACTER SET оператора CREATE DATABASE). Если определен набор символов, то в столбец невозможно ввести символы, не входящие в данную таблицу кодировки. Для представления столбцов, которые будут содержать русскоязычные тексты, рекомендуется использовать набор символов WIN1251 или CYRL, например:
CREATE TABLE MYTABLE (S CHAR(20) CHARACTER SET CYRL)
Если при создании БД и описании столбца набор символов не указан, принимается по умолчанию набор NONE, который позволяет вводить в текстовые столбцы символы любых кодировок. Однако для столбцов с этим набором символов могут возникнуть проблемы при записи их значения в столбцы, которым набор символов назначен явно.
Порядок сортировки символов определяет принцип, по которому символьные значения будут сравниваться и сортироваться в операторах SELECT (если в нем присутствуют разделы WHERE, ORDER BY), при обновлении индексов и т. д. При объявлении символьного поля порядок сортировки может явно указываться следующим спецификатором:
COLLATE порядок^сортировки
Для кириллического набора символов WIN12 51 можно использовать порядок сортировки WIN12 51 или PXW_CYRL, для набора CYRL — CYRL или DB_RUS. Например:
CREATE TABLE MYTABLE (S CHAR(20) CHARACTER
SET WTN1251 COLLATE PXW.CYRL);
Если задан набор символов, но не указан порядок сортировки, принимается одноименный с набором символов порядок (для CYRL — CYRL, для WIN1251 — WIN1251). Два порядка сортировки для кириллических наборов задают две разные сортировки: первая (заданная по умолчанию) — сортировка в стиле MS-DOS:
А В С D ... Z а b с d ... z А Б В Г ... Я а б в г ... я
Вторая — сортировка в стиле Windows:
aAbBcCdD . . . zZaA6EsBrr ...兄兄
При указании строковых значений в SQL-операторах эти значения должны заключаться либо в апострофы, либо в двойные кавычки. Если значение указано в апострофах, в строке значения можно использовать двойные кавычки как обычный символ и наоборот. Если значение должно одновременно содержать и кавычки, и апострофы, используется операция конкатенации I I для сцепления двух строк с разными обрамляющими символами:
INSERT INTO МуТаЫе (S)
VALUES("Апостроф ' * I I'и кавычки " в одной строке')
Помимо операции конкатенации для работы со строковыми значениями может использоваться функция UPPER, преобразующая буквы в прописные. При работе с кириллицей эта функция дает верный результат только для набора WIN1251 и порядка PXW_CYRL. Для остальных сочетаний она не преобразует кириллицу, а для набора CYRL и порядка DB_RUS — искажает русскоязычный текст.
Тип BLOB
В столбцах типа BLOB хранят данные, которые имеют переменную длину и шггер- претируются как последовательность байтов (графические образы, тексты большой длины, звуковые файлы, видеоизображения и т. п.). При этом интерпретация содержимого BLOB-столбца может ложиться не только на клиентскую часть, но и на сервер. В последнем случае в серверной БД могут быть созданы так называемые BLOB-фильтры, определяющие способы преобразования BLOB-значений из одного вида в другой. Например, преобразование изображений из одного графического формата в другой.
InterBase хранит значения BLOB-столбцов в самой БД в виде сегментов. Одна операция ввода-вывода при доступе к BLOB-информации оперирует одним сегментом. В таблице БД, если в ней объявлен столбец типа BLOB, хранится указатель на начальный сегмент столбца в области хранения BLOB-информации этой БД. Длина сегмента тапа BLOB не влияет на производительность InterBase. Тем не менее ее можно определять явно при создании BLOB-столбца:
В BLOB SEGMENT SIZE 1024
По умолчанию длина сегмента составляет 80 байт, максимальная длина сегмента —32 Кбайт (32 768 байт).
Для типа BLOB может бьпъ указан подтип, определяющий, какой тип данных будет записан в этот столбец. Подтип есть условное число. Положительные значения зарезервированы InterBase: 0 (по умолчанию) для указания двоичных данных и 1 для указания ASCII-текстов. Отрицательные значения могут использоваться программистом для определения собственных подтипов. Указание подтипа производится с помощью спецификатора SUB_TYPE:
имя_столбца BLOB SUB_TYPE -1
Интерпретация подтипа не отслеживается сервером и целиком возлагается на программиста.
Если для BLOB-столбца НД создан объект-поле, значение типа BLOB для текущей записи можно сохранить в файле и загрузить из файла:
procedure TForml.FormActivate(Sender:TObj ect);
begin
MyTable.Open;
MyTable.Append;
MyTablelmage.LoadFromFile('ATHENA.BMP*);
MyTableName.Value := 'Голова Афины *;
MyTable.Post;
end;
Денежные столбцы
В InterBase нет столбцов денежного типа (Currency). Вместо них обычно используются столбцы FLOAT или DOUBLE PRECISION. При выводе их значений в визуализирующих компонентах они представляют денежные суммы как значения с плавающей запятой, что в большинстве случаев мешает их восприятию. Вернуть этим столбцам нормальный денежный вид можно либо в обработчике события OnGetText объекта-поля, либо с помощью его (объекта-поля) свойства DisplayEdit. В обработчике можно использовать оператор такого вида:
procedure TForml.QUSUMMAGetText(Sender: TField;
var Text: String;
DisplayText: Boolean}; begin
Text : = FloatToStrF (quSunnna.AsFloat #
ffCurrency # 10 # 2) end;
В свойстве DisplayEdit можно указать следующую маску:
###,###-00*р.1
Конечный результат будет одинаков, но указать маску, как мне кажется, проще.
Генераторы
Как уже говорилось, в InterBase нет автоинкрементного тип& Поля автоинкрементного типа автоматически заполняются уникальными числовыми значениями при вводе очередной записи. Такие поля обычно используются для создания первичных ключей.
Вместо автоинкрементных полей InterBase предоставляет механизм зенерато, ров — особых программ, которые хранят некоторое значение вплоть до момента, когда оно будет использовано, после чего изменяют хранимое значение на заданную величину.
Генератор создается следующим оператором:
CREATE GENERATOR Имя^генератора
После создания генератора ему необходимо присвоить начальное значение таким оператором:
SET GENERATOR Имя_генера тора ТО Яа чальное^значение
Для получения очередного значения генератора используется такая функция:
GEN_ID (Имя^гвкератора, ДГаг)
Здесь Шаг — целое число, на которое изменяется текущее значение генератор%
Проиллюстрируем использование генератора на примере поля NakllD таблшсы NAKLS. Создаем генератор:
CREATE GENERATOR NAKLS_NAKLID
SET GENERATOR NAKLS_NAKLID TO 1
Однажды созданный генератор хранится в БД наряду с другими ее сущностями —таблицами, индексами, хранимыми процедурами и т. п. Используем генератор при вводе очередной записи:
INSERT INTO NAKLS VALUES (GEN_ID (MAKLS_NAKLID, 1), …)
Для удаления генератора используется оператор DROP:
DROP GENERATOR NAKLS_NAKLID
Совместимость типов
При выполнении операций над столбцами разного типа InterBase пытается автоматически привести типы таким образом, чтобы значения, участвующие в операции, принадлежали совместимым типам. Кроме того, для явного приведения типов можно использовать функцию CAST, которая приводит типы внутри оператора select, обычно в секции where:
CAST (<значение> I NULL AS ТипДанных)
Совместимыми считаются только типы DATE, CHAR и NUMERIC.
Вот как можно привести значение столбца Date_Data (тип DATE) к типу CHAR и сравнить его со значением столбца Char_Data (тип CHAR):
SHIjECT
WHERE CHAR_DATA <= CAST(DATE_DATA AS CHAR);
Домены
Доменами называются заранее созданные описания столбцов. Наряду с другими сущностями БД, домены должны иметь уникальные имена. Однажды созданный домен хранится в БД и может использоваться вместо типа столбца. С помощью доменов достигается унификация типов данных, хранящихся в различных столбцах, возможно, разных таблиц.
Пусть, например, в столбцах Namel и Name2 таблицы Firms будет содержаться информация о контактных лицах партнера. Оба столбца должны иметь одинаковую длину, и в них может использоваться кириллица. Объявление таблицы может выглядеть следующим образом:
CREATE TABLE Firms(..., Namel VARCHAR(40) CHARACTER SET WIN1251 COLLATE PXW—CYRL, Name2 VARCHAR(40) CHARACTER SET WIN1251 COLLATE PXW—CYRL,…)
Вместо этого объявления можно сначала создать домен:
CREATE DOMAIN FirnuNames AS VARCHAR(40) CHARACTER SET WIN1251 COLLATE PXW—CYRL
Далее этот домен используется при объявлении таблицы:
CREATE TABLE Finns (.… Namel Firm_Names, Name2 Fintc,Naiaes,,..)
Ограничения на значения столбцов
При определении (изменении) таблицы или домена на значения столбца могут налагаться ограничения. В этом случае InterBase будет автоматически отслеживать вводимые в столбец значения, отвергая те из них» которые не удовлетворяют наложенным на столбец охраничениям. Охраничение накладывается спецификатором check и имеет такой формат:
CHECK (<ограничение>)
<ограничение> =
{<значение> <знак операции> {<значение1> I (<выбор_одного>)}
I <значение> [NOT] BETWEEN <значение1> AND <значение2>
I <значение> [NOT] LIKE <маска_подобия> [ESCAPE <символ>]
I <значение> [NOT] IN (<значение1>
[, <значение2> ...] I <выбор_многюс>)
1 <значение> IS [NOT] NULL
I <значение> {[NOT] {= I < | >} | >= I <=} (ALL I SOME I ANY} <<выбор_многих>)
I EXISTS {<выражение_выбора>)
I SINGULAR (<выражение_выбора>)
I <значение> [NOT] CONTAINING <значение1>
I <значение> [NOT] STARTING [WITH] <строка>
I NOT < ограничение>
I <ограничение> OR <ограничение>
I <ограничение> AND <ограничение>}
<значение> = {столбец I <константа> I <выражение> I <функция>
I NULL I USER I RDB$DB_KEY
} [COLLATE collation]
<константа> = число I *строка"
<функция> = {
COUNT (* I [ALL] <значение> I DISTINCT <значение>)
I SUM ([ALL] <значение> 1 DISTINCT <значение>)
I AVG ([ALL] <значение> I DISTINCT <значение>)
I MAX ([ALL] <значение> I DISTINCT <значение>)
I MIN ([ALL] <значение> I DISTINCT <значение>)
I CAST (<значение> AS <тиюханных>)
I UPPER (<значение>)
I GEN_ID (генератор, <значение>)
Ниже перечислены используемые обозначения:
<знак операции> — один из следующих символов или их комбинация:
=<><=>= !v !> о 1 =
<выбор_одного> — оператор SELECT, возвращающий одно значение или не возвращающий ничего;
<маска_подобия> — произвольная строка, возможно, содержащая символы- заменители % (символ процента) и/или — (символ подчеркивания):
символ процента означает произвольное (в том числе и нулевое) количество любых символов, которые могут стоять на его месте;
символ подчеркивания означает, что на его месте должен стоять любой символ;
<символ> — любой символ, отличный от символа-заменителя, который в маске подобия играет роль символа-заменителя;
<выбор__многих> — оператор SELECT, который может возвращать более одного значения (список значений) или ни одного;
<выражение_выбора> — оператор SELECT, который может возвращать более одного значения (список значений) или ни одного.
Примеры наложения ограничений:
CREATE TABLE MixTable(
/* Столбец не должен содержать отрицательных значений */ Coll INT СНЕСК(Со11>=0),
/* Значения столбца >= 100 и <= 200 */
Со12 INT CHECK(Col2 BETWEEN 100 AND 200),
/* Значения столбца должны Со13 CHAR(40) CHECK(Со13 /* Значения столбца должныСО14 CHAR(20) CHECK(Со14/* Значения столбца должныNakllD таблицы Nakls *//* Значения столбца должны Со13 CHAR(40) CHECK(Со13 /* Значения столбца должныСО14 CHAR(20) CHECK(Со14/* Значения столбца должныNakllD таблицы Nakls */заканчиваться символами "у.е." */ LIKE '% у.е.'), заканчиваться символом "%" */ LIKE '%'%' ESCAPE '!')r совпадать с одним из значений столбца
/* Значения столбца должны Со13 CHAR(40) CHECK(Со13 /* Значения столбца должны
СО14 CHAR(20) CHECK(Со14
/* Значения столбца должны
NakllD таблицы Nakls */
/* Значения столбца должны Со13 CHAR(40) CHECK(Со13 /* Значения столбца должны
СО14 CHAR(20) CHECK(Со14
/* Значения столбца должны
NakllD таблицы Nakls */
Со15 INT CHECK(Со15 IN (SELECT BookID FROM Books)), /* Столбец должен содержать значения большие, чем значение,
возвращаемое генератором GEN_BOOKS */
Со1б 工NT CHECK(Со1б > Gen__ID(GEN_BOOKS,0)),
/* Строка в значении столбца должна начинаться пробелом */
Со17 CHAR(5} CHECK(Со17 STARTING WITH " 口))
Ручное администрирование сервера
Под ручным администрированием понимается воздействие на сервер со стороны администратора с целью поддержания работоспособности этого сервера. Администратор также обычно назначает права доступа, создает базы данных,
осуществляет периодическое сохранение баз данных на внешних носителях информации.
Для ручного администрирования используются утилиты InterBase Service Maiiager и IBConsoIe. Их вы найдете в программной группе Пуск ► Все программы ► InterBase 7.5 Developer Edition.
В окне утилиты InterBase Server Manager отображается состояние сервера (рис. А.1).
I 行 AuKWMtb广 Manual
j GFrogram RtetSBodancNntetBaefiKChange J
j ThelhtotBmeSfltw » cwent(y Running $吵二 I j P gtn ihelnlwSate «eivet a« a «ervce on Wridbws NT
j§酬侧 ^P0rto^“ [ . Guanfen 生吧呵;.;J
Рис. A.l. Окно утилиты InterBase Server Manager
Если сервер запущен, в строке Status имеется слово Running, в противном случае — Stopped. По умолчанию при установке сервера он становится службой Windows и автоматически стартует при запуске ОС. Об этом свидетельствует установленный переключатель Automatic в группе Startup Mode. Если щелкнуть на кнопке Server Properties, вы увидите окно, показанное на рис. А.2.
В строке License указывается максимальное количество одновременных подключений к серверу (20), а в строке Number of attachments — текущее количество подключений. В строке Capabilities перечисляются обслуживаемые сервером протоколы (протоколы TCP/IP н NetBEUI означают, что сервер может использоваться в Интернете и в локальной сети), а также указывается возможность использования локального клиента (то есть клиента, размещенного на машине сервера).
За текущим состоянием сервера следит специальная утилита InterBase Guardian for Windows. Ее задача — перезапустить сервер, если он по каким-либо причинам «рухнет». Количество перезапусков, осуществленных этой утилитой, можно увидеть после щелчка в окне утилиты InterBase Server Manager (см. рис. А.1) на кнопке Guardian Properties.
Утилита IBConsole (рис. А.З) используется главным образом для создания файла БД.
:GerMaf *в §&йв [ ;
ш lnte<Bd6e SQL Server foi WindowsI
■ LccaligCAPfogiam File 式italic%;;侬瓜
Version:Wl-V7.5.ai29
二-20Umw
:NetBEUI Support
,Loc^a艇gujjppt]
InterBase: Settings C:屮rogr频 Fih»\BffllendMnterBase75 ?
TCP Port Na融50 .
Numbei 0fM«chmnU: 0
Nunbtfr dd^Ubastts: 0
OK I Отмена J ;二- J Справка |
Для работы с ней нужно прежде всего зарегистрироваться на сервере (команда Server ► Register). В окне регистрации (рис. Л.4) следует выбрать сервер (локаль- Hbiii пли уличенный) и ввести имя и пароль.
Soryer Information ~
];; s ^4ocel Server Г gemole Server 扌:SfinwNama_NetworkPiotocot
'6btName:
* ре^сйШх
:! P SflvoAliwirAxmaiion
• V” kQQjy^ [f^/Ofyi^^^Qf^ *—一…—“,"i—.I”r»»*^..c-*'..^^r.;.……c
U*erN«w:jsYSDBA~~
Рис. A.4. Регистрация администратора на сервере
ПРИМЕЧАНИЕ
Серверы InterBase всегда имеют хотя бы одного за]х?гис1рировапного нользпвателх (администратора) с именем SYSDBA и паролем masterkey (пароль чувствителен к реплстру букв).
Для создания новой базы данных выберите команду Database ► Create Database, открыв окно, показанное на рис. А.5.
В списке File(s) следует указать маршрут доступа к фа1!лу БД' и, при необходимости, ее размер в страницах. Длина страницы в байтах задается выбором в списке Page Size и по умолчанию равна 4096. Если таблицу предполагается использовать на платформе .NET, в списке Default Character Set следует выбрать пункт попе 一 это гарантирует правильное отображение кириллицы в программах любого типа. Наконец, в строке Alias нужно ввести имя БД, под которым она будет доступна утилите IBConsoIe.
Для заполнения вновь созданной БД таблицами и данными щелкните на инструментальной кнопке Interactive SQL или выберите команду Tools 卜 Interactive SQL (рис. A.6).
После подготовки запроса нажмите клавиши Ctrl+E, щелкните на ин струме 11 г<ът ьной кнопке Execute нлн, наконец,, выберите в меню команду Query 卜 Execute.
Краткое справочное руководство по языку SQL вы найдете в приложении Б.
Умалчиваемое расширение для файла БД — gdb. Однако вы можете использовать любое расширение или даже нс использовать его вовсе.
502 Приложение А • Сервер InterBase
Setyec Local Server
氏傅
■ [^enama(#
.缴娥綱酶礴緜;£,'泊";4 ,
£ OfiBonx :
;]呢更丁丁
i; befauft Chaiectef Sei
p Reg#ei database
Jbibl
ФВБ^
MN1251
£К J Cancel |
Рис. А.5. Создание новой БД
Рис. А.б. Окно для ввода SQL-запросов
Программное администрирование сервера
Базовые классы
Все компоненты группы Service категории InterBase Admin1 имеют общий родительский класс TIBCustomService. Его основные свойства, методы и события представлены далее в табл. А.З, А.4 и А.5.
Таблица А.З. Свойства класса TTBCustomService
Свойство
Описание
property Active : Boolean;
Подключает/отключает БД
property LoginPrompt : Boolean;
Если содержит True, в момент подключения к БД появится диалоговое окно регистрации
property Params : TStrings;
Содержит набор параметров, уточняющих подключение
type TProtocol = set of (TCP,
Определяет сетевой протокол для связи с уда-
SPX, NamedPipe, Local);
property Protocol: TProtocol;
ленным сервером
property ServerName : String;
Имя исполняемого файла сервера с возможным маршрутом доступа
Таблица А.4. Методы класса TIBCustomService
Метод
Описание
procedure Attach;
Присоединяет компонент к БД
procedure Detach;
Отсоединяет компонент от БД
Таблица A.5. События класса TIBQistomServfce
Событие
Описание
property OnAttach: TNotifyEvent ;
Возникает при присоединении к БД
property OnLogin: TNotifyEvent;
Возникает в момент регистрации на сервере
Прямым потомком класса TIBCustomService является класс TIBControl- Service, который расширяет функциональность своего родителя за счет свойства IsServiceRurming и метода SexviceStart:
property IsServiceRunning: Boolean;
procedure Servicestart;
Свойство содержит True во время выполнения службы и получает значение False в момент ее остановки. Метод стартует службу.
Эта категория в палитре компонентов доступна только в режимах создания VCL- или >У1п32-приложений.
Наследником класса TIBControlService является класс TIBControlAnd- QueryService. В нем определены два свойства и два метода, представленные в табл. А.6 и А.7.
Таблица А.6. Свойства класса TIBControlAndQueryServIce
Свойство
Описание
property Buf ferSize: Integer;
Задает/указывает размер буфера
property Eof : Boolean;
Содержит True, если встретился конец файла
Таблица A.7. Методы класса TIBControlAndQueryService
Метод
Описание
function Get Next Chunk: String;
Получает следующий блок данных
function GetNextLine : Strin?;
Получает следующую строку данных
Класс TIBBackupRestoreService является непосредственным родителем компонентов TlBBackupService и TiBRestoreService. Его свойства перечислен ны в табл. А.8. Все свои методы и события он наследует от родителей.
Таблица А.8. Свойства класса TIBBackupRestoreService
Свойство
Описание
property SQLRole: String;
Задает/указывает SQL-роли службы
property Verbose : Boolean;
Если содержит True, служба выполняется в фоновом режиме
Компоненты TIBlnstall и TIBUninstall наследуют от базового класса TIBSetup, свойства и события которого перечислены в табл. А.9 и А. 10.
Таблица А.9. Свойства класса TIBSetup
Свойство
Описание
property Errorcontext : Pointer;
Устанавливает пользовательские данные для функции ошибок
property MsgFilePath: String;
Указывает полный маршрут доступа к файлу с сообщениями
property Progress: Integer;
Возвращает текущий процент выполнения задачи в диапазоне от 0 до 100
property RebootToComplete: Boolean;
Если содержит True, по окончании процесса компьютер перезагружается
property Statuscontext: Pointer;
Устанавливает пользовательские данные для функции статуса
Программное администрирование сервера 505
Таблица А.10. События класса TIBSetup
Событие
Описание
type TIBSetupOnError = function (Sender: TObject; IscCode: MSG_NO; ErrorMessage: String): Integer of object;
Возникает в случае ошибки: IscCode — номер ошибки; ErrorMessage — сообщение об ошибке
property OnError:
TIBSetupOnError;
type TIBSetupOnStatus = function (Sender: TObject):
Integer of object;
Возникает периодически для информирования пользователя о состоянии процесса установки
property OnStatusChange: TIBSetupOnStatus;
type TIBSetupOnWaming = function (Sender: TObject;
Warningcode: MSG_NO;
WarningMessage: String):
Integer of object;
Возникает при необходимости дать предупреждение в ходе установки: Warningcode — код предупреждения; WarningMessage — текст предупреждения
property OnWarning: TIBSetupOnWarning;
Компонент TIBConfigService
С помощью компонента TIBConfigService можно осуществлять конфигурирование некоторых параметров БД. Большинство своих свойств, методов и событий компонент наследует от родительских классов TIBCustomService и TIBControl- Service. Он имеет единственное собственное свойство:
property DatabaseName: String;
В этом свойстве задаются полный маршрут доступа и имя файла БД. Наиболее важные собственные методы компонента перечислены в табл. А.11.
Таблица А.11. Методы компонента TIBConfigService
Метод
Описание
procedure ActivateShadow?
Активизирует предварительно созданную резервную копию БД
procedure BringDatabaseOnline ;
Подключает БД к серверу
procedure SetAsyncMode (Value: Boolean);
Если Value содержит True, после обращения к методу запись в БД идет в асинхронном режиме (через промежуточный буфер)
procedure SetPageBuf Eers (Value:Integer);
Устанавливает количество (Value) страниц для буферизации записей
продолжение 身
Таблица А.11 (продолжение)
Метод
Описание
procedure SetReadonly (Value:
Если Value содержит True, после обращения
Boolean);
к методу запрещается любое изменение БД
procedure SetReserveSpace (Value: Boolean);
procedure
SetSweepinterval(Value: Integer);
Указывает количество резервных страниц для размещения разных версий одной записи
Указывает количество транзакций, через которое будет происходить автоматическая чистка БД от устаревших версий записей
type TShutdownMode = set of (Forced, DenyTransaction, DenyAttachment);
procedure
ShutdownDatabase(Options: TShutdownMode; Wait: Integer);
Отключает БД от сервера. Способ отключения задается параметром Options: Forced — немедленно по истечении Wait секунд; DenyTransaction —сразу после завершения очередной транзакции; DenyAttachment — после отключения всех пользователей
Компонент не имеет собственных событий.
Компонент TIBBackupService
Компонент TIBBackupService предназначен для создания копии БД. Собственные свойства компонента представлены в табл. АЛ2. Компонент не имеет оригинальных методов и событий.
Таблица А.12. Свойства компонента TIBBackupService
Свойство
Описание
property BackupFile: TStrings;
Определяет имя и, возможно, полный маршрут доступа к файлу для создания архива
property BlockingFactor :
Определяет количество блоков информации
Integer;
для копирования на ленточный накопитель
property DatabaseName: String;
type TBackupOptions = set of (IgnoreChecksums, IgnoreLimbo, MetadataOnly, NoGarbageCollection, OldMetadataDesc, NonTransportable, ConvertExtTables);
Маршрут доступа и имя файла БД
Задает параметры архивации: IgnoreChecksums —игнорировать контрольные суммы на каждой странице; IgnoreLimbo — ипюриро- вать незавершенные транзакции; Metadata- Only —архивировать только метаданные: NoGarbageCollection — не архивировать устаревшие записи; OldMetadataDesc — за-
property Options :
TBackupOptions;
писывать метаданные в старом стиле (для совместимости с ранними версиями InterBase); NonTransportable —сохраненные данные MOiyr быть восстановлены только на машине с ОС Windows; ConvertExtTables — преобразовывать внешние таблицы во внутренние
Компонент TIBRestoreService
Компонент TIBRestoreService предназначен для восстановления БД из еде- ланной ранее архивной копии. Компонент не имеет собственных методов и событий, а его собственные свойства перечислены в табл. АЛЗ.
Таблица АЛЗ. Свойства компонента TIBRestoreService
Свойство
Описание
property BackupFile : TStrings;
Определяет имя и, возможно, полный маршрут доступа к файлу архива
property Dat abas eName : TStrings;
type TRestoreOption = (Deactivatelndexes, NoShadow, NoValidityCheck, OneRelationAtATime, Replace r CreateNew, UseAllSpace);
Маршрут доступа и имя файла БД
Определяет параметры восстановления: De- activatelndexes — не активизировать индексы; NoShadow — залрещает создание копии существующей БД; NoValidityCheck — не проверять ссылочные целостности; OneRela-
TRes t oreOpt ions = aet of
TRestoreOption;
tionAtATime — сохраняет одновременно вместе с таблицей все относящиеся к ней мета-
property Options: TRestoreOption
данные; Replace — заменять существующую в БД информацию новой; CreateNew — создать новую БД; UseAllSpace — использовать все пространство страницы для размещения записей
property PageBuffers: Integer;
Определяет размер буфера страниц в килобайтах
property Pagesize:Integer;
Определяет размер страницы в килобайтах
Компонент TIBValidationService
Компонент TIBValidationService проверяет текущее состояние БД. Он является наследником класса TIBControlAndQueryService. Собственные свойства и методы компонента показаны в табл. А. 14 и А.15.
Таблица А.14. Свойства компонента TIBValidationService
Свойство
Описание
property DatabaseName: String ;
type TTransactionGlobalAction = (CommitGlobal# RollbackGlobal4 RecoverTwoPhaseGlobal,
NoGlobalAction);
property Global Act ion:
Маршрут доступа и имя файла БД
Проверка глобальных транзакций: Commit- Global — проверка подтверждения; RollbackGlobal — проверка отката; Recover- TwoPhaseG 1 oba 1 — проверка двухфазного подтверждения; NoG 1 oba 1 Act i on — не про-
TTransactionGlobalAction;
верять глобальные транзакции
продолжение 夕
Таблица А.14 (продолжение)
Свойство
Описание
property LimboTransactionlnfo:
[Index:Integer]
TLimboTransactioninfo;
Открывает индексированный доступ к незавершенным транзакциям
property
LiwboTransaetionlnfoCount: integer;
Количество транзакций в свойстве Limbo
Transactioninfo
type TValidateOption =
(LimboTransactions, CheckDB, IgnoreChecksum, Ki11Shadows, MendDB, SweepDB, ValidateDB, VaiidateFull);
TValida t eOpt i ons = set of TValidateOption;
property Opt ions: TValidateOptions;
Определяет параметры проверки: LimboTransactions —получить список незавершенных транзакций; CheckDB — только проверять БД и не корректировать ее; Ignore- Checksum — игнорировать ошибки в контрольных суммах; Ki 11 shadows — удалять недействительные резервные файлы; MendDB — корректировать ошибки в БД перед ее сохранением; ValidateDB —проверять структуру БД; ValidateFull — проверить фрагмента* цию записей
Таблица A.15. Методы компонента TIBValidationService
Метод
Описание
function
FetchLimboTransactioninfo;
Возвращает информацию об отложенных транзакциях
function
FixLiwboTransactionErrors;
Восстанавливает отложенные транзакции после коррекции ошибок
Компонент TIBStatisticalService
Компонент TIBStatisticalService предназначен для сбора статистических данных о БД. Его свойства указаны в табл. А.16.
Таблица А.16. Свойства компонента TIBStatisticalService
Свойство
Описание
property DatabaseName: String;
Имя и маршрут доступа к файлу БД
type TStatOption = (DataPages, DbLog, Headerpages, Indexpages, SystemRelations};
TStatOptions = set of
TStatOption;
property Options: TStatOptions;
Определяет параметры статистики: Data- Pages — требуется статистика о данных в БД; DbLog — требуется протокол работы; HeaderPages —требуется информация о заголовках страниц; IndexPages —требуется информация по индексным страницам; SystemRelations —требуется информация по системным таблицам
В табл. А.17 перечислены методы компонента.
Таблица А.17. Методы компонента UBStatisticalService
МетодОписание
function GetNextChunk : String;Получает следующий блок данных
function GetNextLine: String;Получает следующую строку данных
Компонент TIBLogService
Компонент TIBLogService предназначен для получения от сервера протокола его работы (даты и моменты запуска, кто запустил).
Свойства, методы и события компонента унаследованы им от родительского класса TIBControlAndQueryService.
Компонент TIBSecurityService
Компонент TIBSecurityService позволяет программно управлять правами пользователей InterBase. В частности, с его помощью можно добавить нового или удалить существующего пользователя, назначить пользователю нужные права и т. д. Компонент является наследником класса TIBControlAndQuery Service, но имеет собственные свойства, перечисленные в табл. А.18.
Таблица А.18. Свойства компонента TIBSecurityService
Свойство
Описание
property FirstName: String;
Имя пользователя
property GroupID: Integer;
Индекс группы пользователя
property LastName: String;
Фамилия пользователя
property MiddleName: String;
Отчество пользователя
property Password: String;
Пароль
type TSecurityAction = (Act ionAddUser, ActionDeleteUser, ActionModifyUser, ActionDisplayUser};
property Security Action: TSecurityAction;
Права пользователя: ActionAddUser — разрешается добавлять нового пользователя; Ас- tionDeleteUser — разрешается удалять существующего пользователя; ActionModi fy- User — разрешается изменять права пользователя; ActionDisplayUser — разрешается просматривать информацию о правах пользователей
property UserID: Integer;
Идентификатор пользователя
property Userinfo [Index: Integer]: TUserlnfo;
Открывает индексированный доступ к зарегистрированным пользователям
property User infoCount: Integer;
Количество пользователей в списке User info
property UserName: String;
Регистрационное имя пользователя
Компонент TIBServerProperties
Компонент TIBServerProperties позволяет получить от сервера разнообразную информацию, включая его параметры, версию, лицензионные данные и т. д. Он является прямым наследником класса TIBCustomService. В табл. А.19 и А.20 приводятся собственные свойства и методы компонента.
Таблица А.19. Свойства компонента TIBServerProperties
Свойство
Описание
property Conf igParams : TConfigParams;
Параметры конфигурации
property Databaseinfo:
TDatabaselnfo;
Информация о базах данных и текущее количество подключений
property Licenseinfo: TLicenselnfo;
Лицензионные параметры сервера
TPropertyOption = (Database, License, Configparameters, Version);
TPropertyOpt ions = set of TPropertyOption;
property Options :
TPropertyOptions;
Обеспечивает настройку компонента на получение нужной информации: Database — ин- формацин о БД (Databaseinfo); License — информации о лицензии (Licenseinfo); Соп- figParameters — ииформации о параметрах конфигурации (conf igParams); Version — информации о версии сервера (VersionInfo)
property Versioninfo :
TVersionlnfo;
Информация о версии сервера
Таблица А.20. Методы компонента TIBServerProperties
Метод
Описание
procedure Fetch;
Получает всю информацию, определенную в свойстве Options
procedure FetchConfigParams;
Получает параметры конфигурации
procedure FetchDatabaselnf o;
Получает информацию о БД
procedure FetchLiceriselnfo;
Получает информацию о лицензии
procedure Fetchversioninfo;
Получает информацию о версии
Компонент TIBLicensingService
С помощью компонента TIBLicensingService можно управлять лицензионными ограничениями сервера — добавлять количество разрешенных одновременных подключений пользователей (после приобретения дополнительной лицензии). Большинство серверов БД (и в их числе InterBase) поставляются на условиях лицензионного ограничения, определяющего максимальное количество
одновременных подключений к серверу и максимальное количество зарегистрированных на нем пользователей. Например, поставляемый с Delphi сервер InterBase версии 7.5 рассчитан не более чем на 20 подключений одновременно. Такое количество может подойти для некоторых небольших офисов, но в большинстве случаев его явно недостаточно. В этом случае закупается дополнительная лицензия, например, на 50 или 100 подключений.
Компонент является прямым наследником класса TlBControlService, Перечислены собственные свойства и методы компонента в табл. А.21 и А.22.
Таблица А.21. Свойства компонента TIBLicensingService
Свойство
Описание
type TLicensingAction =
Определяет вид действия: LicenseAdd — до-
(LicenseAdd, LicenseRemove);
бавление лицензии; LicenseRemove — уда-
property Action:
TLicensingAction;
ление лицензии
property ID: String;
Идентификатор лицензии
property Key : String;
Ключ лицензии
Таблица А.22. Методы компонента TIBLicensingService
Метод
Описание
procedure AddLicense;
Добавляет лицензию
procedure RemoveLicense;
Удаляет лицензию
Компонент TIBInstall
Компонент TIBInstall предназначен для установки компонентов сервера. Он является прямым потомком класса TlBSetup. Собственные свойства и методы компонента приводятся в табл, А.23 и А.24.
Таблица А.23. Свойства компонента TIBInstall
Свойство
Описание
property DestinationDirectory :
String;
Определяет каталог размещения сервера
property InstallOptions :
Определяет устанавливаемые компоненты про-
Tinstailoptions;
граммного обеспечения сервера
property SourceDirectory:
Каталог (устройство) с дистрибутивом сер-
String;
вера
property SuggestedDestination:
Возвращает каталог размещения сервера, за-
String;
данный по умолчанию
property UnlnstallFile: String;
Возвращает имя файла с информацией для процесса удаления сервера
Таблица А.24. Методы компонента TIBInstall
Метод
Описание
TCmdOpt ion =《cmDBMgmt, cmDBQuery, cmUsrMgmt 1;
TConnectivityOption = (cnODBC, cnOLEDB, cnjDBC);
TExamplesOption = {exDB, exAPI);
TMainOption = (moServer, moClient, moConServer, moGuiTools, moDocumentation f moDevelopment);
Получает описание указанного компонента сервера: TCmdOption — комавды сервера; TConnectivityOption — драйвер сервера; TExamplesOption — примеры; TMainOption —основные характеристики
function GetOpt ionDescr ip t ion
(Option: TCmdOption) : String;
function GetOptionDescription (Option: TConnectivityOption):
String;
function GetOptionDescription
(Option: TExan^plesOption):
String;
function GetOptionDescription
(Option: TMainOption) : String;
function GetOptionName (Option:
Возвращает название нужного Компонента
TCmdOption): Strinff;
function GetOptionName (Option: TConnectivityOption): String;
functionGetOptionName (Option: TExamplesOption): String;
functionGetOptionName (Option:
TMainOption): String;
fuactlon GetOptionSpaceRequired (Option: TCmdOption) : Longword;
function GetOptionSpaceRequired
Возвращает требуемое пространство диска для размещения компонента
(Option: TConnectivityOption):
Longword;
function GetOptionSpaceRequired (Option: TExamplesOption): Longword;
function GetOptionSpaceRequired (Option: TMainOption) : Longword;
procedure Installcheck;
procedure InstallExecute;
Проверяет готовность к установке
Вьтолняет установку
Компонент TIBUnlnstall
Компонент TIBUnlnstall удаляет установленные компоненты сервера. Он — наследник класса TIBSetup. Собственное свойство у него едвдст^эдное:
property UnlnstallFile : String;
Это свойство содержит имя файла с информацией об уетщфв号^ных змпо” ментах. Два его метода, соответственно, проверяют готовность к удалению и удаляют сервер:
procedure UnIns ta1ICheek;
procedure UnlnstallExecute;
17 3e.449
者,ч?變^卒举餐终^不二;J T俨鬣暫彰者,ч?變^卒举餐终^不二;J T俨鬣暫彰Краткая справка по языку SQL
者,ч?變^卒举餐
终^不二;J T俨鬣暫彰
者,ч?變^卒举餐
终^不二;J T俨鬣暫彰
Как и всякий другой язык программирования, SQL требует определенных усилий для его освоения. Однако программисту баз данных без этого языка не обойтись. В этом приложении я постараюсь по возможности лаконично описать основные приемы создания SQL-запросов.
Для иллюстрации особенностей создания SQL-запросов удобно использовать утилиту SQL Explorer, которая вызывается из среды Delphi выбором команды Tools ► Explore (если вы настроили этот пункт меню так, как описано в разделе «Создание псевдонима БД» главы 1) или запуском файла dbexplor.exe, который находится в папке BIN каталога размещения Delphi. После вызова утилиты разыщите в окне браузера псевдоним BIBLDATA, щелкните на значке узла слева от него, чтобы получить доступ к БД «Книголюб». Поскольку эта БД — файл-сервер- ная (или» скорее всего, локальная), в ней хранятся только таблицы. Раскройте узел Tables и щелкните на имени любой таблицы, после чего перейдите на вкладку Enter SQL (рис. Б.1).
Советую перед началом работы с запросами изменить заданный по умолчанию шрифт, который используется в окне формирования запроса: вместо пропорционального системного установите более привычный для программиста моноширинный шрифт Courier New (шрифт выбирается через меню утилиты с помощью команды View ► Text Font). Выполнить подготовленный запрос можно с помощью кнопки Execute query справа от панели запроса.
Простая выборка данных
Для выборки данных служит оператор SELECT. В простейшем виде этот оператор имеет такой формат:
SELECT Список_полей FROM Список_таблиц
,1ЧМТН«凱献ЕГ
Рис. Б.1. Формирование SQL-запроса и его выполнение
Здесь SELECT (выбор) и FROM (из) — зарезервированные слова. Подобно зарезервированным словам Delphi, они не могут использоваться в качестве имен полей, таблиц или иных сущностей БД. Если из таблиц в списке таблиц выбираются все поля, вместо списка полей можно указать символ звездочки (*). Таким образом, показанный на рис. Б.1 запрос означает выбор всех полей из таблицы BOOKS.
Сразу же замечу, что SQL-интерпретатор BDE игнорирует регистр букв в зарезервированных словах, названиях полей, таблиц и других сущностей БД (индексы, ограничения и т. п.). Однако для наглядности я выделяю зарезервированные слова SQL прописными буквами.
Уже этот простейший формат выборки таит в себе массу возможностей: он позволяет формировать НД из нужных полей нужных таблиц. Например, следующий оператор выберет только три поля из таблицы Books:
SELECT BName, BAuthor, ВPublish FROM Books
Выборка из связанных таблиц
Хотя простейший оператор SELECT допускает одновременную выборку данных из нескольких таблиц, в этом формате он не учитывает возможные связи между таблицами. Например, рассмотрим следующий запрос:
SELECT * FROM Nakls, Firms
Если выполнить этот запрос (я не рекомендую вам этого делать, если ваш компьютер работает с процессором на частоте менее 400 МГц), будет получен никому
516 Приложение Б • Краткая справка по языку SQL
не нужный НД, в котором каждая накладная повторяется столько раз, сколько записей хранится в таблице FIRMS1 (НД будет содержать 718 ■ 124 = 89 032 записи). Чтобы учесть реляционную связь по полям NFirm и Firm工D, нужно установить критерий отбора:
SELECT * FROM Nakls, Firms WHERE FirmID=NFirm
Критерий отбора формулируется в секции, которая начинается зарезервированным словом WHERE (где). Как видите, чтобы связать две таблицы, мы просто указали, что для каждой записи таблицы NAKLS (она открывает перечень таблиц) в поле NFirm содержится шифр связанной с ней записи из таблицы FIRMS. В результирующем НД будет столько записей, сколько их имеется в таблице NAKLS, причем к каждой записи NAKLS будут справа добавлены все поля записи таблицы FIRMS с информацией об указанном в накладной партнере.
Следующий запрос создаст НД (рис. Б.2), который почти в точности повторит НД Nakls, отображаемый в сетке DBGridl программы из главы 1:
SELECT
NakllD, NDate, FName, TName, NSum, NPayedSum, NRetSum, NCoeff, NRetDate
FROM
Nakls, Firms, TypeNakl
WHERE
FirmID=NFirm AND TypeID=NType
IsSF айой^〜ЙГIsSF айой^〜ЙГНСМЙЬМ*А«Ш» •:… о*^*м> jacbp^l '-:屯 DUebasef大弟 8IEUMTA公 0 ТаЫм■*; я ^кя^З*. Я FWMs.ce4 Я movesook.m.t: я MU1S.DB• я PAYMENT5.DB* ⑪ MsSearety.db у S) кжттда. оеНСМЙЬМ*А«Ш» •:… о*^*м> jacbp^l '-:屯 DUebasef大弟 8IEUMTA公 0 ТаЫм■*; я ^кя^З*. Я FWMs.ce4 Я movesook.m.t: я MU1S.DB• я PAYMENT5.DB* ⑪ MsSearety.db у S) кжттда. ое-—.¥茁事贡謚二%諡占価浴一—--—.¥茁事贡謚二%諡占価浴一—-SELECT N&kllD, NDace, Шше, Шеше, NSuin, NPeyedSg, NRecSwn, NCoeff, NRecDacaPROS NakL・,РАпм, TypeNaklFirwID-NFlr» IND TypelD-NTypeSELECT N&kllD, NDace, Шше, Шеше, NSuin, NPeyedSg, NRecSwn, NCoeff, NRecDacaPROS NakL・,РАпм, TypeNaklFirwID-NFlr» IND TypelD-NTypeЯ irKNAKL.oeЯ irKNAKL.oeу. 4 oeoEMos.♦: W IB_B]Bl.r,弟 IBlocd•玄 Loc*l5erve(♦ ? xv««ne 5arpie Mabue 20c 專 冒 Бям денных MS Access4. 5k 3z <SA5E :£ f Ф«йгы Excelу. 4 oeoEMos.♦: W IB_B]Bl.r,弟 IBlocd•玄 Loc*l5erve(♦ ? xv««ne 5arpie Mabue 20c 專 冒 Бям денных MS Access4. 5k 3z <SA5E :£ f Ф«йгы Excel而砧 卒$&£ 芯前甬£.型;*М5;аз.м.гою -д^лаг-тш而砧 卒$&£ 芯前甬£.型;*М5;аз.м.гою -д^лаг-тш70;02.03.2000 :БУКС-ГКИООО306^16.0 3.2000 :Эко-ТрвпдэОООИТЦ305 46.03.2000 :ЦСК₽кдк 303 ; 1S.O3.2OOO *и*оф饱66 02-03,2000 .000 №д4т>уъстж)"Нагмдж*431 ;22.И.2000 Пап«онн>мтепы:>1юООО *02.03.2000 ;К<мсагпбанкн(1 ДО 63.02.02000 : ДографООО70;02.03.2000 :БУКС-ГКИООО306^16.0 3.2000 :Эко-ТрвпдэОООИТЦ305 46.03.2000 :ЦСК₽кдк 303 ; 1S.O3.2OOO *и*оф饱66 02-03,2000 .000 №д4т>уъстж)"Нагмдж*431 ;22.И.2000 Пап«онн>мтепы:>1юООО *02.03.2000 ;К<мсагпбанкн(1 ДО 63.02.02000 : ДографООО"而E ;.F.二@宙*衣串蕊」「®r Поставка не рмтншго ;27И7,00р.: Поставка нд раатмигм :ЭТ 679,00р..Поставке мрмтмыгай 'ISSfiOjOOp,; :Поставк4 не рмлкмцига : 52Я,00р.:Поставке ндрешмншм :>Ф0в?,50р.: Пктмкйндрмчкмцж :7t В1|,0Ор.: Пост awe м рмжмипО ;10绥!哄.:20 Ткзставкамроапови» : 1584,00().;Постмка на рмшмшм : 646,DDp, i"而E ;.F.二@宙*衣串蕊」「®r Поставка не рмтншго ;27И7,00р.: Поставка нд раатмигм :ЭТ 679,00р..Поставке мрмтмыгай 'ISSfiOjOOp,; :Поставк4 не рмлкмцига : 52Я,00р.:Поставке ндрешмншм :>Ф0в?,50р.: Пктмкйндрмчкмцж :7t В1|,0Ор.: Пост awe м рмжмипО ;10绥!哄.:20 Ткзставкамроапови» : 1584,00().;Постмка на рмшмшм : 646,DDp, i
IsSF айой^〜ЙГ
IsSF айой^〜ЙГ
НСМЙЬМ*А«Ш» •:… о*^*м> jacbp^l '
-:屯 DUebasef
大弟 8IEUMTA
公 0 ТаЫм
■*; я ^кя^З
*. Я FWMs.ce
4 Я movesook.m
.t: я MU1S.DB
• я PAYMENT5.DB
* ⑪ MsSearety.db у S) кжттда. ое
НСМЙЬМ*А«Ш» •:… о*^*м> jacbp^l '
-:屯 DUebasef
大弟 8IEUMTA
公 0 ТаЫм
■*; я ^кя^З
*. Я FWMs.ce
4 Я movesook.m
.t: я MU1S.DB
• я PAYMENT5.DB
* ⑪ MsSearety.db у S) кжттда. ое
-—.¥茁事贡謚二%諡占価浴一—-
-—.¥茁事贡謚二%諡占価浴一—-
SELECT N&kllD, NDace, Шше, Шеше, NSuin, NPeyedSg, NRecSwn, NCoeff, NRecDaca
PROS NakL・,РАпм, TypeNakl
FirwID-NFlr» IND TypelD-NType
SELECT N&kllD, NDace, Шше, Шеше, NSuin, NPeyedSg, NRecSwn, NCoeff, NRecDaca
PROS NakL・,РАпм, TypeNakl
FirwID-NFlr» IND TypelD-NType
Я irKNAKL.oe
Я irKNAKL.oe
у. 4 oeoEMos
.♦: W IB_B]Bl
.r,弟 IBlocd
•玄 Loc*l5erve(
♦ ? xv««ne 5arpie Mabue 20c 專 冒 Бям денных MS Access
4. 5k 3z <SA5E :£ f Ф«йгы Excel
у. 4 oeoEMos
.♦: W IB_B]Bl
.r,弟 IBlocd
•玄 Loc*l5erve(
♦ ? xv««ne 5arpie Mabue 20c 專 冒 Бям денных MS Access
4. 5k 3z <SA5E :£ f Ф«йгы Excel
而砧 卒$&£ 芯前甬£.型;*
М5;аз.м.гою -д^лаг-тш
而砧 卒$&£ 芯前甬£.型;*
М5;аз.м.гою -д^лаг-тш
70;02.03.2000 :БУКС-ГКИООО
306^16.0 3.2000 :Эко-ТрвпдэОООИТЦ
305 46.03.2000 :ЦСК₽кдк
303 ; 1S.O3.2OOO *и*оф饱
66 02-03,2000 .000 №д4т>уъстж)"Нагмдж*
431 ;22.И.2000 Пап«онн>мтепы:>1юООО *02.03.2000 ;К<мсагпбанкн(1 ДО 63.02.02000 : ДографООО
70;02.03.2000 :БУКС-ГКИООО
306^16.0 3.2000 :Эко-ТрвпдэОООИТЦ
305 46.03.2000 :ЦСК₽кдк
303 ; 1S.O3.2OOO *и*оф饱
66 02-03,2000 .000 №д4т>уъстж)"Нагмдж*
431 ;22.И.2000 Пап«онн>мтепы:>1юООО *02.03.2000 ;К<мсагпбанкн(1 ДО 63.02.02000 : ДографООО
"而E ;.F.二@宙*衣串蕊」「®r Поставка не рмтншго ;27И7,00р.: Поставка нд раатмигм :ЭТ 679,00р..
Поставке мрмтмыгай 'ISSfiOjOOp,; :Поставк4 не рмлкмцига : 52Я,00р.:
Поставке ндрешмншм :>Ф0в?,50р.: Пктмкйндрмчкмцж :7t В1|,0Ор.: Пост awe м рмжмипО ;10绥!哄.:20 Ткзставкамроапови» : 1584,00().;
Постмка на рмшмшм : 646,DDp, i
"而E ;.F.二@宙*衣串蕊」「®r Поставка не рмтншго ;27И7,00р.: Поставка нд раатмигм :ЭТ 679,00р..
Поставке мрмтмыгай 'ISSfiOjOOp,; :Поставк4 не рмлкмцига : 52Я,00р.:
Поставке ндрешмншм :>Ф0в?,50р.: Пктмкйндрмчкмцж :7t В1|,0Ор.: Пост awe м рмжмипО ;10绥!哄.:20 Ткзставкамроапови» : 1584,00().;
Постмка на рмшмшм : 646,DDp, i
Orowmrtrffadtd
ПРИМЕЧАНИЕ
В отличие от подстановочных полей в наборе Nakls программы из главы 1, связыва* ние таблиц в запросе не требует обязательного наличия индексов по подстановочным полям, но если такие индексы есть (как в нашем случае), BDE будет их использовать.
Сортировка записей
Чтобы предыдущий пример действительно в точности повторял НД Nakls, нам нужно отсортировать записи по полю NakllD. Для сортировки используется секция, начинающаяся зарезервированными словами ORDER BY (сортировать по):
SELECT
NakllD, NDate, FName, TName, NSum, NPayedSum,
NRetSum, NCoeff, NRetDate
FROM
Nakls, Firms, TypeNakl
WHERE
FirmID=NFinn AND TypeID=NType
ORDER BY NakllD
Как и при установлении связи между таблицами, сортировать можно по любым полям, не обязательно индексным.
Сложные критерии отбора
С помощью секции where можно не только связывать таблицы» но и создавать довольно сложные критерии отбора данных. Для этого в секции указывается произвольное количество операторов вида ПОЛЕ 〜ЗНАЧЕНИЕ, связываемых логическими операциями NOT, AND, OR, где знак тильды (~) означает операцию отношения (эти операции SQL совпадают с операциями отношения Delphi):
SELECT
NakllD, NDate, FName, TName, NSum, NPayedSum,
NRetSum, NCoeff, NRetDate
FROM
Nakls, Firms, TypeNakl
WHERE
FirmID=NFirm AND TypeID=NType AND (NSum>100000 OR NRetSum>0)
ORDER BY NakllD
В этом примере отбираются только те накладные, сумма которых превышает 100 000 рублей или в которых ненулевая сумма возврата (рис. Б.З). Обратите внимание на два обстоятельства. Во-первых, приоритет операций отношения в SQL выше приоритета логических операций — это избавляет от необходимости расстановки многочисленных скобок. Во-вторых, операция OR имеет меньший приоритет, чем операция AND. Если бы в последнем примере мы убрали скобки, результирующий НД содержал бы записи, в которых каждая накладная с суммой
больше 100 000 рублей повторялась бы столько раз, сколько имеется накладных с ненулевой суммой возврата.
:^^^SS^F^^ "*詬'二:;'"»嚼繇^^^^Ul.03.2000 'очка Соиналь^йу>«ууоп>т:^^^SS^F^^ "*詬'二:;'"»嚼繇^^^^Ul.03.2000 'очка Соиналь^йу>«ууоп>т6 01.03.2000 ;7 01.03.2000 ; 10:а1.оз.2(юо :27 01.03.200028 01.03.2000 交% .0^2000 &位&&Й во аг.оз.гооо67 [Ьг.оэ.гаю62 J33.O3.2OOo"88 03.С3.200096 03.03.2000100 03^03 2000109 06.03-2000116:0б'0Х20б0126 07.03.20006 01.03.2000 ;7 01.03.2000 ; 10:а1.оз.2(юо :27 01.03.200028 01.03.2000 交% .0^2000 &位&&Й во аг.оз.гооо67 [Ьг.оэ.гаю62 J33.O3.2OOo"88 03.С3.200096 03.03.2000100 03^03 2000109 06.03-2000116:0б'0Х20б0126 07.03.2000『очка. МП4ЭН:ООО Издаггвп»ство "Нолидж" ООО ИэАбехтво "Молил*: :Точса. МГЮМ“Qa. МИЭМ "'' ^ООО Издательство Iw*" ^Точса. Институт жлодажи .Точка. Соцнвлшый ужввроггет :Точка. Социа/ъшй ужмроггет :М1ДИ(СЭАО ''':ЦОСРидвс;Склад N9 2' ^Склад №? 2:Точка. Лстмтут моподвхх i ООО №двт»льство "Нолидж'1 ^ОООИзАатааствоХалидж*『очка. МП4ЭН:ООО Издаггвп»ство "Нолидж" ООО ИэАбехтво "Молил*: :Точса. МГЮМ“Qa. МИЭМ "'' ^ООО Издательство Iw*" ^Точса. Институт жлодажи .Точка. Соцнвлшый ужввроггет :Точка. Социа/ъшй ужмроггет :М1ДИ(СЭАО ''':ЦОСРидвс;Склад N9 2' ^Склад №? 2:Точка. Лстмтут моподвхх i ООО №двт»льство "Нолидж'1 ^ОООИзАатааствоХалидж*鳶StSPeE「丁 : ^^ +二二]^^^^£Продажа ha peanmaono;550,00р. :а,00р. :550.0C ^Продшл ha peanmaono: 2 326f?0p.0,00p.2 320,76 ^Поставка на рмжзацмюi155 бЮ^ООр. ^60 20l,65p> i?5 408^ ^|Поставка на реа/мзацню\155 610,00р.:;0,00p.。庙号鳶StSPeE「丁 : ^^ +二二]^^^^£Продажа ha peanmaono;550,00р. :а,00р. :550.0C ^Продшл ha peanmaono: 2 326f?0p.0,00p.2 320,76 ^Поставка на рмжзацмюi155 бЮ^ООр. ^60 20l,65p> i?5 408^ ^|Поставка на реа/мзацню\155 610,00р.:;0,00p.。庙号Продаже на реалимцпо : 1 408.13р. :0,00р.:Продаже на реалимцпо : 1 408.13р. :0,00р.:Продам на реалгаацпо ; 1500,00р」0,00р. : 261,找工Продам на реалгаацпо ; 1500,00р」0,00р. : 261,找工Постаюц на рмгимцио ; М8 200,00р/62Э71,Э9р-Постаюц на рмгимцио ; М8 200,00р/62Э71,Э9р-Продаже м рвамаиию . 'Продажа на рвалшцию ; Продаже на решммцню :Продажа ш реализацию;Поставка на реалимцию ,Продаже м рвамаиию . 'Продажа на рвалшцию ; Продаже на решммцню :Продажа ш реализацию;Поставка на реалимцию ,О^ОСО^ОС3S42,00p,j aOQpJ 3 542, ОС 3 40Л50р. i 0,00р/ 2 374, К ''就向:「.0,浴:гва(9С эт тоор/гэ 743,25р. : 631,ОС IMS,2Sp・; dOOp」! 935,2!3S42,00p,j aOQpJ 3 542, ОС 3 40Л50р. i 0,00р/ 2 374, К ''就向:「.0,浴:гва(9С эт тоор/гэ 743,25р. : 631,ОС IMS,2Sp・; dOOp」! 935,2!Продажа на реалинцию : 5 69в,00р, 852,26р. 1845,7, ;Прадйка на реалимцпо : 2 938.В8Р. : 0,00р. | 1 535,» Продажа на реалммцню ; 5 ZSSjOp.J О^ООр. 46О,ОС Поставка но реалимцию ; 395 200,00р. : 0,00р, ; 0。Продажа на реалинцию : 5 69в,00р, 852,26р. 1845,7, ;Прадйка на реалимцпо : 2 938.В8Р. : 0,00р. | 1 535,» Продажа на реалммцню ; 5 ZSSjOp.J О^ООр. 46О,ОС Поставка но реалимцию ; 395 200,00р. : 0,00р, ; 0。Поставке на рмлимиию ; 123 500,吗.:0,00р.;Поставке на рмлимиию ; 123 500,吗.:0,00р.;о,осо,ос
:^^^SS^F^^ "*詬'二:;'"
»嚼繇^^^^Ul.03.2000 'очка Соиналь^йу>«ууоп>т
:^^^SS^F^^ "*詬'二:;'"
»嚼繇^^^^Ul.03.2000 'очка Соиналь^йу>«ууоп>т
6 01.03.2000 ;
7 01.03.2000 ; 10:а1.оз.2(юо :
27 01.03.2000
28 01.03.2000 交% .0^2000 &位&&Й во аг.оз.гооо
67 [Ьг.оэ.гаю
62 J33.O3.2OOo"
88 03.С3.2000
96 03.03.2000
100 03^03 2000
109 06.03-2000
116:0б'0Х20б0
126 07.03.2000
6 01.03.2000 ;
7 01.03.2000 ; 10:а1.оз.2(юо :
27 01.03.2000
28 01.03.2000 交% .0^2000 &位&&Й во аг.оз.гооо
67 [Ьг.оэ.гаю
62 J33.O3.2OOo"
88 03.С3.2000
96 03.03.2000
100 03^03 2000
109 06.03-2000
116:0б'0Х20б0
126 07.03.2000
『очка. МП4ЭН
:ООО Издаггвп»ство "Нолидж" ООО ИэАбехтво "Молил*: :Точса. МГЮМ
“Qa. МИЭМ "'' ^ООО Издательство Iw*" ^Точса. Институт жлодажи .Точка. Соцнвлшый ужввроггет :Точка. Социа/ъшй ужмроггет :М1ДИ(СЭАО '''
:ЦОСРидвс
;Склад N9 2
' ^Склад №? 2
:Точка. Лстмтут моподвхх i ООО №двт»льство "Нолидж'
1 ^ОООИзАатааствоХалидж*
『очка. МП4ЭН
:ООО Издаггвп»ство "Нолидж" ООО ИэАбехтво "Молил*: :Точса. МГЮМ
“Qa. МИЭМ "'' ^ООО Издательство Iw*" ^Точса. Институт жлодажи .Точка. Соцнвлшый ужввроггет :Точка. Социа/ъшй ужмроггет :М1ДИ(СЭАО '''
:ЦОСРидвс
;Склад N9 2
' ^Склад №? 2
:Точка. Лстмтут моподвхх i ООО №двт»льство "Нолидж'
1 ^ОООИзАатааствоХалидж*
鳶StSPeE「丁 : ^^ +二二]^^^^£
Продажа ha peanmaono;550,00р. :а,00р. :550.0C ^
Продшл ha peanmaono: 2 326f?0p.0,00p.2 320,76 ^
Поставка на рмжзацмюi155 бЮ^ООр. ^60 20l,65p> i?5 408^ ^|
Поставка на реа/мзацню\155 610,00р.:;0,00p.。庙号
鳶StSPeE「丁 : ^^ +二二]^^^^£
Продажа ha peanmaono;550,00р. :а,00р. :550.0C ^
Продшл ha peanmaono: 2 326f?0p.0,00p.2 320,76 ^
Поставка на рмжзацмюi155 бЮ^ООр. ^60 20l,65p> i?5 408^ ^|
Поставка на реа/мзацню\155 610,00р.:;0,00p.。庙号
Продаже на реалимцпо : 1 408.13р. :0,00р.:
Продаже на реалимцпо : 1 408.13р. :0,00р.:
Продам на реалгаацпо ; 1500,00р」0,00р. : 261,找工
Продам на реалгаацпо ; 1500,00р」0,00р. : 261,找工
Постаюц на рмгимцио ; М8 200,00р/62Э71,Э9р-
Постаюц на рмгимцио ; М8 200,00р/62Э71,Э9р-
Продаже м рвамаиию . 'Продажа на рвалшцию ; Продаже на решммцню :
Продажа ш реализацию;Поставка на реалимцию ,
Продаже м рвамаиию . 'Продажа на рвалшцию ; Продаже на решммцню :
Продажа ш реализацию;Поставка на реалимцию ,
О^ОС
О^ОС
3S42,00p,j aOQpJ 3 542, ОС 3 40Л50р. i 0,00р/ 2 374, К ''就向:「.0,浴:гва(9С эт тоор/гэ 743,25р. : 631,ОС IMS,2Sp・; dOOp」! 935,2!
3S42,00p,j aOQpJ 3 542, ОС 3 40Л50р. i 0,00р/ 2 374, К ''就向:「.0,浴:гва(9С эт тоор/гэ 743,25р. : 631,ОС IMS,2Sp・; dOOp」! 935,2!
Продажа на реалинцию : 5 69в,00р, 852,26р. 1845,7, ;Прадйка на реалимцпо : 2 938.В8Р. : 0,00р. | 1 535,» Продажа на реалммцню ; 5 ZSSjOp.J О^ООр. 46О,ОС Поставка но реалимцию ; 395 200,00р. : 0,00р, ; 0。
Продажа на реалинцию : 5 69в,00р, 852,26р. 1845,7, ;Прадйка на реалимцпо : 2 938.В8Р. : 0,00р. | 1 535,» Продажа на реалммцню ; 5 ZSSjOp.J О^ООр. 46О,ОС Поставка но реалимцию ; 395 200,00р. : 0,00р, ; 0。
Поставке на рмлимиию ; 123 500,吗.:0,00р.;
Поставке на рмлимиию ; 123 500,吗.:0,00р.;
о,ос
о,ос
Рис. Б.З. Результат сложного критерия отбора записей
Справа от операции отношения указывается значение. Если это значение — текстовое или типа дата-время, оно должно заключаться в обрамляющие апострофы или двойные кавычки. Кроме того, к значению текстового поля можно применять операцию LIKE, когда значение справа от операции LIKE представляет не все поле, а лишь его часть:
SELECT BName FROM Books WHERE BName LIKE ИЯ%" ORDER BY BName
Этот запрос отбирает из таблицы BOOKS только те названия книг, которые начинаются с буквы «Я» (рис. Б.4).
При определении части текстового поля в операции LIKE символ процента (%) указывает, что на его месте могут стоять любые символы. Следующий запрос отберет все книги, в названиях которых хотя бы раз встречается буква «я»:
SELECT BName FROM Books WHERE BName LIKE "%я%и ORDER BY BName
Сложные критерии отбора 519
С помощью зарезервированного слова IN (в [диапазоне]) можно перечислить несколько допустимых значений поля. Следующий запрос отбирает названия 1-й, 3-й и 7-й книг из таблицы BOOKS (рис. Б.5):
SELECT BName FROM Books
WHERE BookID IN (1,3,7)
,10 wh/t на урок M5 Word 2000
笺 10 минут на урок.Освой самостоятельно MS Excel 2000■
£ 13 шагов к успеху или литические советы как быстро достичь карьеры в j
Рис. Б.5. Результат использования операции IN
Вместо перечня допустимых значений в круглых скобках после операции IN можно разместить вложенный оператор SELECT. Если требуется посмотреть список всех покупателей, еще не оплативших поставленные им книги, можно сформировать такой запрос (рис. Б.6):
SELECT FName FROM Firms
WHERE FirmlD IN
(SELECT NFirm FROM Nakls
WHERE NPayedSum=0 AND NType IN (1,7))
ORDER BY FName
Рис. Б,б. Результат формирования списка значений вложенным оператором SELECT
Псевдонимы полей, таблиц и комментарии
В наших таблицах нет совпадающих имен полей за счет того, что каадое поле в любой таблице начинается с буквы, соответствующей начальной букве имени таблицы. А что делать, когда имена полей из двух и более таблиц совпадают? Если бы мы, например, пренебрегли нашим правилом и не поставили префиксы, появи- лись бы два имени Name и следующий фрагмент привел бы к неоднозначности:
SELECT
NakllD, Date# Name, Name, Sum, PayedSum,...
Чтобы исключить неоднозначность, в таких случаях имена полей дополняют именами их таблиц:
SELECT
NakllD, Date, Finns.Name, Types.Name, Sum, PayedSum,...
Поскольку совпадающие имена таблиц могут встречаться и в других секциях запроса, для упрощения их именования в SQL разрешено вместо имени таблицы использовать ее псевдоним:
SELECT
NakllD, Date, F.Name, T.Name, Sum, PayedSum,...
FROM Nakls, Finns F, Types T ..,
Псевдоним указывается сразу за именем таблицы в секции FROM.
Иногда бывает удобно переименовать поле. Особенно часто это необходимо при обращении к агрегатным функциям (см. раздел <Агрегатные функции и группировка записей»), так как возвращаемое ими значение по умолчанию имеет имя этой фушсции. Для переименования используется зарезервированное слово AS:
SELECT AVG(NSum-NPayedSum-NRetSum) AS Debt
В любом месте запроса может присутствовать комментарий:
SELECT
/* Совпадающие имена полей дополняются псевдонимами таблиц */
NakllD, Date# F.Name, Т.Name, Sum, PayedSum,...
/* Псевдонимы задаются символами сразу за именем таблицы */
FROM Nakls, Firms F, Types T
Агрегатные функции и группировка записей
Вместо имен полей и/или вместе с ними в секции SELECT можно использовать одну из следующих агрегатных функций:
AVG — возвращает среднее значение аргумента;
COUNT — подсчитывает количество вхождений аргумента во все записи НД;
МАХ — возвращает максимальное значение аргумента;
м工N — возвращает минимальное значение аргумента;
SUM — суммирует значения аргумента.
Агрегатные функции и группировка записей 521
В качестве аргумента при обращении к агрегатной функции может стоять произвольное выражение, составленное из полей НД. Например, следующий запрос возвращает среднее значение долга покупателей (рис. Б.7):
SELECT AVG(NSrnn-NPayedSum-NRetSwn)
FROM Nakls
WHERE NType in (1,7)
3805,64p/
Рис. 6.7. Среднее значение долга покупателей
Список всех поставщиков с указанием суммы стоимости всех поставленных ими книг дает такой запрос (рис. В.8):
SELECT SUM(NSura) , FName
FROM Nakls, Firms
WHERE FirmlD^NFirm AND NType in (0,6)
GROUP BY FName
2 6 915,00р. 'АкадемияЧХвнтр ЗАО
^ 92 В12Л1р, ;Альфа-книг«
,42 222,00р. ;БУКС-ГКН ООО
二 27 307,50Р, :6w5叩 о
16 ЗТ,00р.『ородщ ©ридическое бгоро
二 27 567恒7 Ди^*М4ФИ
& 646jOOp. ^Дограф ООО
千 12 7глздПдодэ(«^<^^
3 300,00р.衣 Экспресс ООО
二 83 165,00р」Ик2 淞
17 028fB0p. ^Институт психотерапии ЗАО
1 584j00p. :Коксалтбдмкир АО
二礴速ZK^^.r1^?, 二,
а ИТбО^ООр^Ладья+Оод
Рис. Б.8. Список поставщиков
Разумеется, интересно получить не только суммы поставок, но и имела партнеров, поэтому в приведенном выше запросе в секции SELECT указаны агрегатная функция и поле таблицы FIRMS. Для подобного рода запросов, в которых вместе с агрегатными функциями фигурируют и поля таблиц, SQL требует секции группировки GROUP BY, в которой в обязательном порядке перечисляются все поля, указанные в секции SELECT.
С помощью зарезервированного слова HAVING накладываются ограничения на группировку записей. В следующем запросе возвращаются все покупатели, затраченные ими на покупку книг деньги и количество купленных книг при условии, что закупалось не менее четырех книг (рис. Б.9):
SELECT FNAME, SUM(NSUM), COUNT(MOVEID)
FROM NAKLS, FIRMS, MOVEBOOK
WHERE FIRMID=NFIRM AND MOVEID=NAKLID AND NTYPE IN(2, 7)
GROUP BY FNAME
HAVING COUNT(MOVEID)>=4
Андреев C.B. ПБОЮЛГУП **ОЦ Московсшй Дом Книги*Андреев C.B. ПБОЮЛГУП **ОЦ Московсшй Дом Книги*ГончаровДементьев ЧПКя«с»а_ЧПКомбукОООКонпютер ИнмитсНаумов ООО Изаатетство "Нолидж"Ридас ЛТД-1Розничная гродвжа тндм ообЦСК РидасЯноверГончаровДементьев ЧПКя«с»а_ЧПКомбукОООКонпютер ИнмитсНаумов ООО Изаатетство "Нолидж"Ридас ЛТД-1Розничная гродвжа тндм ообЦСК РидасЯновер56332,2В44Мв' [ 29717,456 Т 55656^318 ']'5635,4 ;63366,092 * 9903;Йё322456332,2В44Мв' [ 29717,456 Т 55656^318 ']'5635,4 ;63366,092 * 9903;Йё3224父: 4!MJ "'el 7 ■ и父: 4!MJ "'el 7 ■ и"90816,*20^345694,674';Э4(“Й)7999999эГ麻"90816,*20^345694,674';Э4(“Й)7999999эГ麻3958,4;7790,74]9в5Л1вТ3958,4;7790,74]9в5Л1вТ10;10;
Андреев C.B. ПБОЮЛ
ГУП **ОЦ Московсшй Дом Книги*
Андреев C.B. ПБОЮЛ
ГУП **ОЦ Московсшй Дом Книги*
Гончаров
Дементьев ЧП
Кя«с»а_ЧП
КомбукООО
Конпютер Инмитс
Наумов ООО Изаатетство "Нолидж"
Ридас ЛТД-1
Розничная гродвжа тндм ооб
ЦСК Ридас
Яновер
Гончаров
Дементьев ЧП
Кя«с»а_ЧП
КомбукООО
Конпютер Инмитс
Наумов ООО Изаатетство "Нолидж"
Ридас ЛТД-1
Розничная гродвжа тндм ооб
ЦСК Ридас
Яновер
56332,2В
44Мв' [ 29717,456 Т 55656^318 ']'5635,4 ;63366,092 * 9903;Йё
3224
56332,2В
44Мв' [ 29717,456 Т 55656^318 ']'5635,4 ;63366,092 * 9903;Йё
3224
父: 4!
MJ "'el 7 ■ и
父: 4!
MJ "'el 7 ■ и
"90816,*20
^345694,674';Э4(“
Й)7999999эГ麻
"90816,*20
^345694,674';Э4(“
Й)7999999эГ麻
3958,4;7790,74]9в5Л1вТ
3958,4;7790,74]9в5Л1вТ
10;
10;
Рис. Б.9. Ограничение на группировку
Условие HAVING отличается от WHERE тем, что в нем можно использовать агрегатные функции, а в WHERE — нельзя.
При использовании агрегатных функций иногда требуется исключить из списка повторяющиеся значения полей. Для этого служит зарезервированное слово DISTINCT. Например, представленный ниже запрос вернет количество всех накладных, связанных с поставкой книг (рис. Б.10):
SELECT COUNT(NFirm) FROM Nakls
WHERE NType IN (0,6)
Рис. 6.10. Количество накладных поставки
В то же время следующий запрос вернет количество поставщиков (рис. Б.11):
SELECT COUNT(DISTINCT NFirm) FROM Nakls
WHERE NType IN (0,6)
Рис. Б.11. Количество поставщиковРис. Б.11. Количество поставщиков
Рис. Б.11. Количество поставщиков
Рис. Б.11. Количество поставщиков
Создание/удаление таблиц и индексов
Для создания таблицы используется следующий оператор:
CREATE TABLE Имя_таблицы(Определения_полей)
Здесь Имя_таблицы — произвольное имя (не должно совпадать ни с одним именем уже существующих в БД таблиц); Определения_полей — список имен полей с обязательным указанием их типов. Например:
CREATE TABLE NewTable(Fieldl CHAR(20), Field2 INT)
При определении текстовых полей полезно явно указывать кодировку символов, иначе в нерусифицированных версиях Windows вы не сможете в такой столбец ввести русскоязычные строки:
CREATE TABLE NewTable{Fieldl CHAR(20) CHARACTER SET Winl251, Field2 INT)
Допустимые типы полей в общем случае зависят от типа таблиц. Поскольку в файл- серверных БД Delphi создает таблицы типа Paradox, в операторе CREATE TABLE можно использовать следующие типы полей:
CHAR(N), CHARACTER(N) — символьное поле длинойN символов (до 255);
INT, INTEGER — соответствует типу integer языка Delphi;
SMALLINT — соответствует типу Smalllnt языка Delphi;
BLOB — цепочка байтов неопределенной длины;
FLOAT — соответствует типу Real языка Delphi;
DATE — поле для хранения даты;
BOOLEAN — соответствует типу Boolean языка Delphi.
За типом поля при его описании можно указывать зарезервированные слова not NULL (поле не может быть пустым), UNIQUE (значения поля не должны повторяться).
Для удаления существующей таблицы используется оператор
DROP TABLE Имя_таблицы
Для создания индекса служит оператор
CREATE INDEX Имя_индекса ON Имя__таблицы (Список_полей)
Например:
CREATE INDEX Indexl ON NewTable(Fieldl, Field2)
Первичный ключ — это отсортированный индекс с уникальными значениями:
CREATE UNIQUE ASCENDING INDEX Books_ID ON Books(BooksID)
Следующий оператор удаляет ранее созданный индекс:
DROP INDEX Имя_индекса
Изменение таблиц
Под изменением таблицы понимается изменение структуры ее полей или типов ее полей. Для вставки поля используется оператор вида
ALTER TABLE Имя_таблицы ADD Имя^^описание^поля
Например:
ALTER TABLE BOOKS ADD COVER BLOB SEGMENT SIZE 2048
Удаление поля:
ALTER TABLE Имя_таблицы DROP ЙМЯ_ПОЛЯ
Например:
ALTER TABLE BOOKS DROP COVER
Изменить тип поля без потери данных в общем случае нельзя. Но если новый тип совместим с прежним» то сначала создается временное поле нужного типа, в него копируется содержимое изменяемого поля, старое поле удаляется, создается одноименное старому поле нового типа, в него переносятся данные из временного поля и затем временное поле уничтожается. Например, в таблице NAKLS есть поле NFIRM типа SMALLINT. Оно используется для кода партнера. Емкость этого типа — 32 767 положительных значений. Таким образом, максимальное количество партнеров (поставщиков и покупателей) не может быть больше этого значения. Допустим, нам нужно увеличить емкость этого поля, сделав его тип INTEGER. Вот как это можно сделать:
/* Создаем временное поле */
ALTER TABLE NAKLS ADD NFIRM_TEMP INT /* Переносим данные */
UPDATE NAKLS SET NFIRM_TEMP = NFIRM
/* Удаляем старое поле и переобъявляем его */
ALTER TABLE NAKLS DROP NFIRM
ALTER TABLE NAKLS ADD NFIRM INT
/* Наполняем его */
UPDATE NAKLS SET NFIRM = NFIRM_TEMP ALTER TABLE NAKLS DROP NFIRM_TEMP
Вставка, удаление и редактирование записей
В таблицу БД запись вставляется с помощью оператора
INSERT INTO Имя_таблицы (Список_полей) VALUES (Список_значений)
Например:
INSERT INTO TypeNakl (TName, TypelD) VALUES ("Врак", 8)
Каждому полю в списке полей должно соответствовать нужное значение в списке значений. Если заполняются все поля записи, список полей вместе с обрамляюпхи-
Вставка/ удаление и редактирование записей 525
ми скобками можно опускать. В этом случае значения в списке значений перечисляются в строгом соответствии с порядком следования полей в структуре таблицы:
INSERT INTO TypeNakl VALUES (8, "Врцк")
С помощью оператора INSERT можно вставить сразу группу зазшсёй. Пусть, например, таблица создана показанным ниже оператором:
СЙЕАТЕ TABLE NewTable(MovelD TNT, MNakl SMALLINT, MBook SMALLII4T, MQuan SMALLINT, MPrice Float)
Тогда следующий оператор вставит в нее список книг для накладной с идентификатором 100:
INSERT INTO NewTable
SELECT * FROM MoveBook
WHERE MNakl=100
Для удаления записей используется оператор
DELETE FROM Имя_таблицы WHERE Условие_выборки_записей
Например:
DELETE FROM TypeNakl WHERE TypeID=8
ВНИМАНИЕ!
Если в запросе delete опустить секцию where, из таблицы будут удалены все записи.
Изменение отдельных полей таблицы реализуется оператором
UPDATE Имя_таблицы SET Имя_поля=Значение WHERE Условие^выборки
Например:
UPDATE TypeNakl SET TName="Списание в брак" WHERE TypeID=8
За зарезервированным словом SET может стоять произвольное количество полей с указанием их значений; два соседних присваивания Имя_поля=3начение разделяются запятой. Если опустить секцию WHERE, будут изменены значения всех записей таблицы.
ВВ
В
В
Краткая справка по языкам HTML и XML
Знакомство с языком HTML
Язык HTML (Hyper Text Markup Language 一 язык гипертекстовой разметки) является основным язиком общения в гигантской Всемирной Паутине (WWW). В его основе лежит система 齊叫 с помощью которых в обычный текстовый файл вставляется служебная информации управляющая работой браузера.
Система тегов
Знакомство с HTML начнем с короткого примера. Создайте с помощью Блокнота Windows такой текстовый файл:
<HTML>
<HEAD>
<Т1ТЬЕ>Простой пример доз^мента HTML</TITLE>
</HEAD>
<BODY>
<Н1>Заголовок первого уровня</Н1>
<Н2>Заголовок второго уровня</Н2>
Текстовая строка первого абзаца.<BR>
Текстовая строка второго абзаца.
</BODY>
</HTML>
Сохраните этот файл под именем Examplel.htm. Тогда при загрузке этого файла в браузер он будет выглядеть так, как показано на рис. ВЛ.
Как видно из примера, теги представляют собой английские слова, обрамленные угловыми скобками. Тег <HTML> извещает о начале документа, написанного на
языке HTML, а парный ему тег </HTML> — о его конце. Эти теги необязательны, и их можно без каких-либо последствий опускать. Сам документ разделен на две неравные части: заголовок (reni <HEAD> и </HEAD>) и тело (<BODY> и </BODY>). Заголовок несет информацию о содержимом страницы. Он отображается в строке заголовка окна браузера. Его можно опускать — в зтом случае вместо него в строке заголовка окажется имя файла HTML-страницы. Тело документа опускается значительно реже (в отличие от обрамляющих его тегов <BODY> и </BODY>). В нем размещаются смысловые компоненты документа — заголовки, текст, изображения, перекрестные ссылки и т. п.
£аил Оравка вид Избранное Сдрвис д^мвка. 图^
令好… 方"因囤艦产…険》136Pg.电0"% ■ "
Адресу ;蜀 CRDoaiments and SettbgsVlana而он 4окументьАРе17У2\5оиг816а{Д]就 Переход ;:tei.%h 艺
Заголовок первого уровня
Заголовок второго уровня
Текстовая строка первого абзаца.
Текстовая строка второго абзаца.
篇f^^^^侖二i%^^^二1!曲;讪隔*高323;二二::价二干*2国总^电应也电i^&sxi^f;ZZZ
Рис- В.1. Отображение файла Examplel.htm в окне браузера
Обратите внимание: почти все теги делятся на открывающие и закрывающие. Закрывающие отличаются наличием косой черты перед условным английским словом. Исключение сделано для тегов <BR> н <Р>. Оба тега завершают текущий абзац и поэтому не имеют парных тегов. Тег <Р> не только завершает текущий абзац, но и вставляет перед следующим абзацем небольшой пропуск. Если эти теги опустить, браузер считает весь текст принадлежащим одному абзацу (посмотрите на строку второго абзаца). Регистр букв в теге не имеет значения. Угловые скобки (< и >), амперсант (&) и двойные кавычки (") в рамках HTML считаются специальными символами. Если понадобится вставить в текст эти специальные символы, они заменяются следующихж последовательностями:
открывающая угловая скобка — <
закрывающая угловая скобка — >
амперсант — &ашр;
двойные кавычки — ".
528 Приложение В • Краткая справка по языкам HTML и XML
Гиперссылки
Характерной особенностью гипертекстовой страницы является возможность вставки в нее гиперссылок (гипертекстом является текст справочного Ыр-файла, так что понятие гиперссылки вам знакомо). Для вставки гиперссылки используется тег А. В следующем примере в текст вставляется гиперссылка на собственную домашнюю страницу, а также демонстрируется размер шрифта (рис. В.2):
<Т?1ТЪЕ>Пример использования гиперссылки и демонстрация шрифтов</TITLE><Н2>Демонстрация гиперссылки</Н2>Щелкните на выделенном тексте, чтобы посмотреть<ВЯ><А HREF="http://127.0.0.1"><FONT Color = red>MOX)домашнюю страницу< /FONTx/AxBR><Н2>Демонстрация размеров шри:фта</Н2><Т?1ТЪЕ>Пример использования гиперссылки и демонстрация шрифтов</TITLE><Н2>Демонстрация гиперссылки</Н2>Щелкните на выделенном тексте, чтобы посмотреть<ВЯ><А HREF="http://127.0.0.1"><FONT Color = red>MOX)домашнюю страницу< /FONTx/AxBR><Н2>Демонстрация размеров шри:фта</Н2><FONT vFONT 〈FONT 〈FONT <FONT 〈FONT <FONT 〈FONT 〈FONT<FONT vFONT 〈FONT 〈FONT <FONT 〈FONT <FONT 〈FONT 〈FONTSize=l> Size=2> Size=3> Siz2=4> Size二5A Size=6> Size=7> Size=8>Size=l> Size=2> Size=3> Siz2=4> Size二5A Size=6> Size=7> Size=8>Size=l Size=2Size=3 Size=4Size=5 Size=6Size=l Size=2Size=3 Size=4Size=5 Size=6AA66BBrr</F0NTxBR>AA55BBrr</F0NTxBR>AA66BBrr</F0NTxBR>AA65BBrr</F0NTxBR>AA66BBrr</F0NTxBR>AA66BBrr</F0NTxBR>AA66BBrr</F0NTxBR>AA55BBrr</F0NTxBR>AA66BBrr</F0NTxBR>AA65BBrr</F0NTxBR>AA66BBrr</F0NTxBR>AA66BBrr</F0NTxBR>Size=7</FONT>Size=8</FONT>Size=7</FONT>Size=8</FONT>Size=100> Size=100</FONT>Size=100> Size=100</FONT>強竹- ◎,曲图心1P Поиск ☆哂《Л⑥衾, ◎国"*『♦““I;;;;;;.,. ““亠;.;;.:11—L..l“;“;";;;”,“I_л —ag,屬 ШШШШШШШШШ^ШШШИШЯ^ Е| пщ..『《 »強竹- ◎,曲图心1P Поиск ☆哂《Л⑥衾, ◎国"*『♦““I;;;;;;.,. ““亠;.;;.:11—L..l“;“;";;;”,“I_л —ag,屬 ШШШШШШШШШ^ШШШИШЯ^ Е| пщ..『《 »
<Т?1ТЪЕ>Пример использования гиперссылки и демонстрация шрифтов
</TITLE>
<Н2>Демонстрация гиперссылки</Н2>
Щелкните на выделенном тексте, чтобы посмотреть<ВЯ>
<А HREF="http://127.0.0.1">
<FONT Color = red>MOX)домашнюю страницу< /FONTx/AxBR>
<Н2>Демонстрация размеров шри:фта</Н2>
<Т?1ТЪЕ>Пример использования гиперссылки и демонстрация шрифтов
</TITLE>
<Н2>Демонстрация гиперссылки</Н2>
Щелкните на выделенном тексте, чтобы посмотреть<ВЯ>
<А HREF="http://127.0.0.1">
<FONT Color = red>MOX)домашнюю страницу< /FONTx/AxBR>
<Н2>Демонстрация размеров шри:фта</Н2>
<FONT vFONT 〈FONT 〈FONT <FONT 〈FONT <FONT 〈FONT 〈FONT
<FONT vFONT 〈FONT 〈FONT <FONT 〈FONT <FONT 〈FONT 〈FONT
Size=l> Size=2> Size=3> Siz2=4> Size二5A Size=6> Size=7> Size=8>
Size=l> Size=2> Size=3> Siz2=4> Size二5A Size=6> Size=7> Size=8>
Size=l Size=2
Size=3 Size=4
Size=5 Size=6
Size=l Size=2
Size=3 Size=4
Size=5 Size=6
AA66BBrr</F0NTxBR>
AA55BBrr</F0NTxBR>
AA66BBrr</F0NTxBR>
AA65BBrr</F0NTxBR>
AA66BBrr</F0NTxBR>
AA66BBrr</F0NTxBR>
AA66BBrr</F0NTxBR>
AA55BBrr</F0NTxBR>
AA66BBrr</F0NTxBR>
AA65BBrr</F0NTxBR>
AA66BBrr</F0NTxBR>
AA66BBrr</F0NTxBR>
Size=7</FONT>
Size=8</FONT>
Size=7</FONT>
Size=8</FONT>
Size=100> Size=100</FONT>
Size=100> Size=100</FONT>
強竹- ◎,曲图心1P Поиск ☆哂《Л⑥衾, ◎国"*
『♦““I;;;;;;.,. ““亠;.;;.:11—L..l“;“;";;;”,“I_л —
ag,屬 ШШШШШШШШШ^ШШШИШЯ^ Е| пщ..『《 »
強竹- ◎,曲图心1P Поиск ☆哂《Л⑥衾, ◎国"*
『♦““I;;;;;;.,. ““亠;.;;.:11—L..l“;“;";;;”,“I_л —
ag,屬 ШШШШШШШШШ^ШШШИШЯ^ Е| пщ..『《 »
Демонстрация гиперссылкиR
Щелкните на выделенном тексте, чтобы посмотреть
亭В,丿口乙■脾泣以員1〃?О СГр我h总口了
Демонстрация размеров шрифта
$ai ААббхкг
Size・2 ААББввп1
Size=3 ААббввгг
Sizc=M ААббввгг
Size=5 ААббввгг
Size=6 ААббввгг
Size=7 Size=8 Size= 100
Рис В.2. Демонстрация гиперссылки и размеров шрифта
Как видим, после тега А следует пробел, имя параметра HREF, знак равенства и в двойных кавычках URL-адрес документа, который будет вызываться после щелчка мышью на гиперссылке. В примере используется URL в виде сетевого имени локального компьютера. Если ваша домашняя страница размещена на сервере поставщика услуг Интернета или на другом сетевом компьютере, нужно соответствующим образом изменить URL.
Шрифты
Любой фрагмент текста может быть выделен шрифтом. Для этого используется тег FONT, за которым через пробел следуют один или несколько параметров; каждый параметр представляет собой пару вида ИМЯ=ЗНАЧЕНИЕ, соседние параметры разделяются точкой с запятой. Например, следующий тег определяет вывод укрупненным шрифтом зеленого цвета:
<FONT Size=5; Color=Green>
Тег FONT могут обрамлять следующие уточняющие теги:
<в> (</в>) — полужирное начертание;
<1> (</1>) — наклонное начертание (курсив);
<и> (</и>) — подчеркнутое начертание;
<тт> (</ТТ>) — моноширинный шрифт.
Замечу, что параметры размера и цвета шрифта могут трактоваться по-разному в браузерах разного типа. Вместо физических параметров шрифта, определяемых тегом FONT, можно использовать следующие логические теги:
vDFN> — выделяет текст (обычно курсивом);
<ЕМ> — выделяет текст курсивом;
<CODE> — выделяет текст моноширинным шрифтом;
<STRONG> — выделяет текст полужирным начертанием.
Списки
С помощью тегов <Ы> можно определять списки. Списки бывают нумерованные и маркированные. Нумерованному списку предшествует тег <OL>, маркированному —тег <UL>. В следующем примере демонстрируются логические шрифты и разного рода списки (рис. В.З):
<Т1ТЬЕ>Логические шрифты и списки</Т1ТЬЕ>
<Н2>Теги логических шрифтов</Н2>
<DFN>3tot текст выделен тегом &1 tDFN>< /DFNxBR>
<ЕМ>Этот текст выделен тегом <EM></EMx/BR>
<CODE>3tot текст выделен тегом <CODE></CODE><BR>
<STRONG>Этот текст выделен тегом <STRONG></STRONG>
<Н2Демонстрация списков</Н2> нумерованный список:
vOL>
<Ы>Первый уровень
530 Приложение В • Краткая справка по языкам HTML и XML
<Ы>Первый уровень
<0L>
<Ы>Второй уровень
</0L>
</0L>
Маркированный список:
<UL>
<Ы>Первый уровень
<Ы>Первый уровень
<UL>
<Ы>Второй уровень
<UL>
<Ы>Третий уровень
</UL>
</UL>
</UL>
£айл Оравка ^<д Избранное Сдреис (прамй,* Др
О№яь ' © ' Й Й ⑦&М;喻 j»*»»"憑?启 * I Zp^丄閭 CA^OCUf06rto.1a1nds鼻,《Q*W :「;矍贈^;У『F^t
Теги логических шрифтов
Этот текст выделен тегом <DFN>
Этот текст выделен тегом. <ЕМ>
Этот текст выделен тегом <СООЕ>
Этот текст вьщелен тегом <STRONG>
Демонстрация списков
Нумц)ованный список:
Пц)вый уровень
Пфвый уровень
Второй уровть
Маркированный список:
Пц)вый уровень
Пц)вый уровеньI
о Второй уроветьI
■ Третий уровень
對 ПК. — —「LF ;扌吟1«^М.「hi]'"二]
Рис, В.З. Логические шрифты и списки
Знакомство с языком HTML 531
Изображения
С помощью тега IMG в документ можно вставить изображение (рис. В.4):
<Т1ТЬЕ>Пример вставки в HTML-документ насбраженм兄〈/TITLE〉 <Н2><Сепгег>Изображение вставлено с помощью тега
<CODE><IMG SRC></CODEx/Centerx/H2>
<IMG SRC=npwstitle.gif" BORDER=1 ALIGN^Left HSPACE=20 VSPACE=20> Этот текст обтекает рисунок справа. Параметр HSPASE определяет расстояние (в пикселах) от рисунка до текста по горизонтали, а параметр VSPACE 一 по вертикали.
Файл Правка 恥 Цзбржое С&реис Ставка
©f「鬱 '•窗 @ f^1>^поиск 貪И36f j 0 0"毒盲*」0
Wzjk状;Wzjk状;L;产 7-^х,,;:;…“;,;f,*";""x";:「,•;・м:";т;“7—^^~~• ;, ,; 3,; ;:,;;,";;;";;■,;••;;,•;•••;:;;:•;’ :;>.「••,•"• ““•;■—i-i— ;™мл а»и^、…‘г ",■■-■■■■■
Wzjk状;
Wzjk状;
限晔:! ^j C ^Documents and Settings\nana\|40M д(жументь|\РеРУ2\5оигсе\СЬар 23\НТМ1\Ех:^4 |Д Переход
Изображение вставлено с помощью тега <img sro
黑^^^&^瀛黑^^^&^瀛Microsoft .Personal Web ServerMicrosoft .Personal Web Serverот рисунка до текста по горизонтали, а параметр VSPACE - по вертикали.от рисунка до текста по горизонтали, а параметр VSPACE - по вертикали.Этот текст обтекает рисунок справа. Параметр HSPASE определяет расстояние (в пикселах)Этот текст обтекает рисунок справа. Параметр HSPASE определяет расстояние (в пикселах)
黑^^^&^瀛
黑^^^&^瀛
Microsoft .
Personal Web Server
Microsoft .
Personal Web Server
от рисунка до текста по горизонтали, а параметр VSPACE - по вертикали.
от рисунка до текста по горизонтали, а параметр VSPACE - по вертикали.
Этот текст обтекает рисунок справа. Параметр HSPASE определяет расстояние (в пикселах)
Этот текст обтекает рисунок справа. Параметр HSPASE определяет расстояние (в пикселах)
;0 Мойкотьютер
Рис, B.4. Вставка в документ изображения
С помощью параметра ALT=" текстовая строка" задается альтернативный текст, заменяющий рисунок, если в браузере запрещен просмотр изображений.
Уточняющие параметры и цвет
В HTML имеется много тегов, которые могут сопровождаться уточняющими параметрами. В предыдущем примере с помощью параметров SRC и BORDER задаются, соответственно, имя файла с изображением и тип рамки, параметр ALIGN определяет выравнивание изображения относительно текста и т. д. В теге BODY с помощью параметров можно указать цвета фона и текста страницы или изображение,
которое будет служить фоном. Следующий тег определяет светло-серый цвет фона и желтый цвет текста:
<BODY BGCOLOR=■#D3D3D3 w TEXT="yellow">
Цвет определяется двумя способами: условным названием (red, blue, white и т. п.) или числом в цветовой модели RGB. В последнем случае задается триада байтов, каждый из которых определяет интенсивность красной, зеленой и синей составляющих соответственно. Следующие параметры определяют красный цвет:
BGCOLOR=*,red"
BGCOLOR="#FF0000,'
BGCOLOR="255,OrO"
BGCOLOR=-100%,0%,0%"
Комментарии
С помощью тега <!- .. .> в HTML-текст можно вставлять комментарии:
<!-Этот комментарий не интерпретируется браузером как HTML-текст >
Современная версия языка — Dynamic HTML v.4.0 — способна передавать браузеру специальные программные средства (таблицы стилей, сценарии и т. п.), с помощью которых браузер может создавать динамически меняющиеся страницы самостоятельно, без дополнительной помощи веб-сервера. Так как старые версии браузеров «не знают> новшества HTML, эти средства в теле страницы выделяются специальными комментариями:
<!— Описание сценария ―>
Диалоговые средства
В языке развиты диалоговые средства для создания интерактивных страниц. В простейшем случае — это форма с единственной кнопкой (рис. В.5):
<HTML>
<HEAD>
<Т1ТЬЕ>Пример формы с кнопкой</TITLE>
</HEAD>
<BODY BGCOLOR= -blanchedalmond'* >
<CENTRE>
<H2>После щелчка на кнопке "Моя страница" будет показана умалчиваемая страница сервера</Н2>
<!- Тег HR определяет горизонтальную линию:>
<HR>
<FORM АСТ1О№"ЬЪер://127.0.0Ли METHOD= нGET">
<INPUT TYPE="submit" VALUE="Моя страница•*>
</FORM>
</CENTER>
</BODY>
</HTML>
Рис. В.5. Пример страницы с формой и кнопкой на ней
С помощью параметра ACTION тега FORM определяется URL-адрес, который будет вызван после щелчка пользователя на кнопке типа submit. Необязательный параметр METHOD определяет метод протокола HTTP (см. далее), который следует использовать для обращения. Кнопки, как и некоторые другие компоненты, предназначенные для диалога с пользователем (поля ввода, флажкн и переключатели), определяются тегом INPUT с параметрами NAME н TYPE. Параметр NAME задает уникальное для формы имя компонента (переключатели, входящие в одну группу, имеют одинаковые значения этого параметра). Параметр TYPE определяет тип вставляемого в форму диалогового элемента и может иметь одно из следующих значений:
button — кнопка, для которой можно написать обработчик события OnClick;
checkbox — флажок;
file — внешний файл с описанием компонентов формы;
hidden — скрытый компонент (используется для отправки на сервер данных, полученных из других форм);
image — изображение, при щелчке на нем мышью на сервер отсылаются координаты указателя относительно левого верхнего угла изображения;
password — строка парольного ввода (текст заменяется звездочками);
radio — переключатель;
reset — кнопка сброса, после щелчка на ней все компоненты формы получают умалчиваемые параметры;
submit — кнопка подтверждения; после щелчка по ней вызывается URL-адрес, указанный тегом FORM, и ему передается строка параметров вида
ИМЯ=ЗНАЧЕНИЕ&ИМЯ=ЗНАЧЕНИЕ&...&ИМЯ=ЗНАЧЕНИЕ
text — поле ввода.
Если параметр TYPE опущен, создается поле ввода. Если опущен параметр NAME, диалоговый компонент не участвует в передаваемой серверу строке пар ИМЯ= ЗНАЧЕНИЕ.
Примеры определения разных компонентов диалоговой формы показаны на рис. В.6.
Представленные на рисунке интерфейсные элементы созданы с помощью следующего кода:
<Т1ТЬЕ>Демонстрация диалоговых средств</Т1ТЪЕ>
<BODY BGCOLOR=яblanchedalmond">
<! -Поле ввода длиной до 50 символов с умалчиваемым значением: >
<INPUT TYPE=*text* NAME="txtFavoritи VALUE= nВведите ваше мнение" SIZE=50> Это поле ввода<Р>
<1-Кнопка, для которой следует написать обработчик ONCLICK:>
<INPUT TYPE="buttonH NAME="bthOK" VALUE='OK"
ONCLICK="alert('Нажата кнопка OK *)* > Это кнопка с обработчиком <Р>
<!-Флажок:>
<INPUT TYPE="checkbox" NAME=B chkYes■ CHECKED> Флажок<Р>
v!-Два переключателя:>
<INPUT TYPE="radio* NAME^rdColoL VALUE= "Черный" CHECKED> Группа<Р>
<INPUT TYPE="radio* NAME="rdColor" VALUE= * Белый"> переключателей<Р>
<!-Многострочное текстовое поле, в котором выводятся
4 строки длиной по 52 символа (без отсечения границами компонента> :>
<TEXTAREA ROWS=4 COLS=52 NAME="mmlnputn>
Первая строка
Вторая строка
</TEXTAREA> Многострочное текстовое поле<Р>
<!-Раскрывающийся список:>
<SELECT SIZE=1 NAME=wselDays">
<OPTION СОРТ工ON <OPTION <OPTION</SELECT></BODY><OPTION СОРТ工ON <OPTION <OPTION</SELECT></BODY>VALUE="0и > воскресенье
<OPTION СОРТ工ON <OPTION <OPTION
</SELECT>
</BODY>
<OPTION СОРТ工ON <OPTION <OPTION
</SELECT>
</BODY>
VALUE="1"> понедельник
VALUE= * 2"> вторник
VALUE=・3*> среда Раскрывающийся список
В примере в качестве функции обработки события щелчка на кнопке ОК используется стандартная функция alert» которая создает и показывает диалоговое окно с сообщением. В реальной форме для этих целей в текст помещается сценарий, написанный на языке JavaScript или VBScript.
Таблицы
Рассмотренные средства языка не позволяют проектировщику страницы располагать текст по своему усмотрению — этим занимается браузер, исходя из разрешающей способности экрана и размеров открытого оква. Однако иногда бывает необходимо точное позиционирование текста и рисунков. В этом случае в страницу вставляются таблицы, определяемые тегами <TABLE> и </TABLE>. Между ними с помощью тегов <TR> и </TR> описываются все строки таблицы. Охшса- ние строки заключается в перечислении содержимого всех ее ячеек, обрамленном тегами <TD> и v/TD>. Теги TABLE могут сопровождаться многочисленными
536 Приложение В • Краткая справка по языкам HTML и XML параметрами, определяющими наличие и вид рамки, ширину и высоту таблицы, цвет фона и т. д.:
<Т1ТЬЕ>Демонстрация таблицы</Т1ТЬЕ>
<Н2>Текст и изображения в одной таблице</Н2>
<TABLE BORDER=3 BGCOLOR;"blanchedalmond" BOR1DERCOLOR="blackH
WIDTH=300>
<CAPTION ALIGN=bottom>HeKOTOpue рисунки</САРТ10Ы>
<TRxTD>04km</TDxTD Align=center> <IMG SRC二"glasses .bmp*,></TDx/TR>
<TRxTD>IlO4Ta для меня< /TDxTD Align=centerxIMG
SRC=" email me .gif ></TDx/TR>
<ТНхТ0>Звезда</TDxTD Align=centerxIMG SRC=Gstar .bmp"</TDx/TR> </TABLE>
Этот код создает таблицу, представленную на рис. В.7. Теги <CAPTION> и </CAPTlON> определяют поясняющую надпись, а необязательный параметр ALIGN — расположение надписи относительно таблицы.
Рис. В.7. Пример таблицы
В таблицы можно вставлять изображения форматов JPEG, GIF и BMP.
Отдельные ячейки таблицы можно объединять, если в тег <TD> включить параметр СОЬЗРА№число или ROWSPAN=4Hcno. Первый служит для объедикения
Знакомство с языком HTML 537
ячеек по горизонтали, второй — по вертикали, а параметр число задает количество объедш1ясмых ячеек (рис. В.8):
<Т1ТЪЕ>0бъединение ячеек</Т1ТЬЕ>
<TABLE BORDER=3 BGCOLOR=иЬ1апсЬес1а1топ6и BORDERCOLOR="black"
WIDTH=300>
<CAPTION ALIGN=bottomxSTRONG>MoM дети< / STRONGx /CAPTION>
<TRxTDx/TDxTD COLSPAN=2 Align=center><B>napaMeTpbi</TDx/TR>
<TRxTDx/TDxTD Align=centerxB>Bo3pacT</B></TDxTD Align=center>
<B>Poct</Bx/TD>< /TR>
<ТК><ТП>Ольга</TDxTD Align=center>34</TDxTD Align=center>
183</TDx/TR>
<тв><ТО>Александр</TDxTD Align=center>15</TDxTD Align=center>
177</TDx/TR>
<ТК><ТП>Василий</TDxTD Align=center>ll</TDxTD Align=center>
160</TDx/TR>
</TABLE>
файл Правка 凱i Избранное : С*ис 5рмжафайл Правка 凱i Избранное : С*ис 5рмжаi吸剪хi吸剪х
файл Правка 凱i Избранное : С*ис 5рмжа
файл Правка 凱i Избранное : С*ис 5рмжа
i吸剪х
i吸剪х
@М 一 ◎,园画心:q2 ^кМранное 0、@*編:•里加守通Rspwq [⑥ UtDocumehts and 竺ghgsVlanaWtoM дстсума二叨向ЛЛг\5оигсе1СЬар-23\НТ№\Е>^Д 8Я 吋竺MV舔森顯飙
Параметры
Возраст
■ Рост
Ольга
33
183
Александр :
15
177
Василий
И
160
Мон дети
也「篁券》
Рис. В.8. Объединение ячеек
Фреймы
Фреймы предоставляют механизм фрагментации страницы: с их помощью, например, можно получить страницу, показанную на рис. В.9.
i整同观
Amf j邑 C:\Documents and Setbngs\nana\MoM “окуненты\Ре!7Уг\^игЕСЬар一Z3\HTf^\Example9.htfn ^|,ёЯ Лоррхщ:: >С>м^
Изображение вставлено с ; |j помощью тега <img sro %Изображение вставлено с ; |j помощью тега <img sro %团 Флажок团 Флажок0 Переключатель выбрая0 Переключатель выбрая.^Вввдитв в&ше ннвнив Это поле ввода.^Вввдитв в&ше ннвнив Это поле ввода^Этокнопка с обработчиком^Этокнопка с обработчикомО йгот0*>О йгот0*>После щелчка на кнопке нМоя страница0 будет показана страница сервера по умолчаниюПосле щелчка на кнопке нМоя страница0 будет показана страница сервера по умолчаниюПочта для меняПочта для меняТекст и изображения в одной таблицеТекст и изображения в одной таблицеОчкиОчкиЗвездаЗвездаНекоторые рисункиНекоторые рисункиIX心痴殛逗IX心痴殛逗
Изображение вставлено с ; |j помощью тега <img sro %
Изображение вставлено с ; |j помощью тега <img sro %
团 Флажок
团 Флажок
0 Переключатель выбрая
0 Переключатель выбрая
.^Вввдитв в&ше ннвнив Это поле ввода
.^Вввдитв в&ше ннвнив Это поле ввода
^Этокнопка с обработчиком
^Этокнопка с обработчиком
О йгот0*>
О йгот0*>
После щелчка на кнопке нМоя страница0 будет показана страница сервера по умолчанию
После щелчка на кнопке нМоя страница0 будет показана страница сервера по умолчанию
Почта для меня
Почта для меня
Текст и изображения в одной таблице
Текст и изображения в одной таблице
Очки
Очки
Звезда
Звезда
Некоторые рисунки
Некоторые рисунки
IX心痴殛逗
IX心痴殛逗
Рис. В.9. Страница сформирована из четырех фреймов
Для формирования страницы с фреймами вместо тегов <BODY> используются теги <FRAMESET> и <FRAME>. Параметры первого описывают общую структуру страницы: количество горизонтальных и/или вертикальных полос, в которых будут располагаться фреймы, размеры полос, наличие между ними разграничивающей рамки и г п. В каждом теге <FRAME> обязательно должен присутствовать параметр SRC, с помощью которого указывается страница, из которой формируется содержимое фрейма. Вот HTML-текст, с помощью которого получен предыдущий рисунок:
<TITLE>I4 л люстрация фреймов</гГ1ТЬЕ>
<FRAMESET COLS="50%, 50%" ROWS二"50名,50%n FRAMEBORDER=0>
<FRAME SP.C=" Example4 .htm" >
d'KAME SRC="Example5.htm">
vF'RAME SRC=" Example6 . htm" >
《FRAME SRC-*1 Example? .htm">
</FRAMSET>
Если в страницу нужно просто вставить содержимое одной или нескольких других страниц, используется так называемый плавающий фрейм. Он задается тегом
<IFRAME> и рядом параметров, в которых указывается источник данных и положение фрейма на странице:
<Т1ТЬЕ>Иллюстрация плавающего фрейма</Т1ТЬЕ>
<30DY>
<Н2>Плавающий фрейм с рисунком<:/Н2>
Размещение текста относительно плавающего фрейма.
<IFRAME SRC="Example4 .htm" ALXGN^right WIDTH^^O%1' HEIGHT=" 80% " > </IFRAME>
Текст обтекает рисунок слева. Это достигается установкой параметра vCODE>ALIGN=rightv/CODE> (допустимые значения <CODE>left, right, top, bottom<:/CODE>).
</BODY>
Страница, созданная с помощью этого кода, представлена на рис. В.10.
Рис. В.1О. Пример плавающего фрейма
Другие возможности
Для выделения отдельных частей страницы (без фреймов) используется тег <DIV>T с помощью параметра STYLE которого можно задать стиль фрагмента: шрифт, расположение фрагмента на странице, фоновый цвет и т. п. Например:
<D工V ID=TopDIV STYLE="position: absolute; top: 100; left: 140; height: 30; Width: 100; background: red; font-size: 30;
color: white; z-index: 3">
Закрывающая область
</DIV>
В этом тексте определяется фрагмент с именем TopDIV, располагающийся на расстоянии 100 пикселов ниже и 140 пикселов правее левого верхнего угла окна. Выводимый в нем текст будет иметь белый цвет на красном фоне. Для фрагмента определен так называемый z-индекс, или индекс глубины. Последний создает эффект 2,5-мерности изображения: чем больше z-индекс, тем «выше» на плоской проекции окна расположен данный фрагмент относительно других фрагментов. Как видим, фрагменты можно именовать, что позволяет ссылаться на них (и их стили) в так называемых сценариях. Сценарии — это относительно небольшие программы, которые получает браузер вместе с другими данными. Они интерпретируются браузером как некоторые действия, которые он должен совершить при отображении страницы. Например, сценарий может заставить перемещаться фрагменты на зкране, создавая динамическое изображение без малейшего участия в этом веб-сервера.
Для создания сценария используется язык JawaScript или (только для IE) VBScript. Все современные браузеры поддерживают так называемую виртуальную машину Jawa (a IE имеет также интерпретатор Visual Basic), что позволяет создавать с помощью сценариев поразительные эффекты.
Знакомство с языком XML
В последнее время стремительно развивается мощный язык XML (extensible Markup Language — расширяемый язык разметки), который построен на тех же принципах, что и HTML, но позволяет программисту вводить собственные теги и описывать связанные с ними действия. Таким образом, HTML — это <обычный> язык программирования, синтаксис которого заранее описан. В отличие от него XML — это метаязык, то есть язык создания языков. В нем описаны лишь минимальные синтаксические правила, с помощью которых программист создает собственный язык разметки» позволяющий любым интерпретаторам XML (поддержка XML включена в последние версии браузеров IE, NC и Opera) максимально точно отображать закодированные этим языком данные.
В Delphi имеются специальные утилиты и компоненты, ориентированные на преобразование информации из БД в XМL-документ и обратно.
Причины разработки XML
Естественно спросить: для чего придумьшать новый язык, ведь HTML до сих пор прекрасно справлялся со всеми задачами WWW. Дело в том, что HTML представляет собой статический набор правил разметки текста и, следовательно,
его возможности ограничены этим набором. В то же время существует множество задач (в том числе задач удобного представления любых структурированных данных, например, полученных из баз данных), которые трудно <втиснуть» в узкие рамки правил HTML. Постоянное расширение HTML невозможно по той простой причине, что это ведет к автоматическому <разбуханию» соответствующих браузеров. Значительно проще не переделывать браузеры, а «научить» их понимать метаязык типа XML, в котором правила разметки описаны в самом документе и, следовательно, могут меняться в зависимости от конкретной задачи.
Следует оговориться, что и HTML и XML являются подмножествами значительно более мощного языка SGML (Standardized Generalized Markup Language — универсальный стандартизованный язык разметки), который был разработан и принят в качестве международного стандарта (ISO 8879) еще в 1986 году. Этот язык» рассчитанный <на все случаи жизни»> не получил широкого распространения из-за своей чрезмерной сложности. Постоянно развивающиеся потребности WWW и статические правила HTML вступили в конфликт, единственным разумным выходом из которого было создание облегченного подмножества <заумного» SGML. Таким языком и стал язык XML (его описание занимает 26 страниц против более 500 страниц описания SGML).
Чтобы пояснить разницу между HTML и XML, рассмотрим такой гипотетический пример. Допустим, в нашей БД хранится информация о книгах (упоминавшаяся в главе 1 таблица BOOKS). Если бы вы захотели показать пользователям все книги по цене не более 50 р., вы не смогли бы этого сделать средствами HTML. В то же время с помощью XML эта задача легко решается, потому что при описании каждой книги на XML мы можем предусмотреть, например, теги <цена> и </цена>, между которыми можно поместить цену книги. После такой разметки нетрудно отобрать только те записи, которые содержат нужные цены.
Структура XML-документа
Особенностью структуры XМ L-документа является наличие в нем трех частей: раздела определения типа документа (Document Type Definition, DTD), шаблона преобразования и собственно текста документа.
Раздел DTD говорит о том, какая разметка используется в документе. Именно в этом разделе средствами XML описывается любой вновь вводимый тег. Шаблон преобразования указывает способ представления на экране того или иного тега. Наконец, в текст документа помещаются описанные в DTD теги с текстовыми данными.
Вот как, например, может быть описан элемент книга.
издательство,издательство,isbn?, цена?)>isbn?, цена?)><!ELEMENT книга (название, автор,
издательство,
издательство,
isbn?, цена?)>
isbn?, цена?)>
<!ELEMENT книга (#PCDATA)>
V!ELEMENT<I ELEMENT v!ELEMENT v!ELEMENTV!ELEMENT<I ELEMENT v!ELEMENT v!ELEMENTавтор (#PCDATA)> издательство (#PCDATA)> isbn (#PCDATA)>
V!ELEMENT
<I ELEMENT v!ELEMENT v!ELEMENT
V!ELEMENT
<I ELEMENT v!ELEMENT v!ELEMENT
цена (#PCDATA)>
Сразу же уточню, что элементом в XML называется комбинация обрамляющих тегов и заключенной в них текстовой информахщи:
<имя_тега> Текстовая информация </имя_тега>
Для описания элемента нужно указать, из каких составных элементов он состоит и что входит в каждую составную часть. В нашем примере элемент книга состоит из пяти вложенных элементов, причем три первых (название, автор, издательство) обязаны быть в информации о книге, а два других (isbn, цена) могут отсутствовать — об этом свидетельствует знак вопроса, стоящий за именем вложенного элемента. Вложенные элементы должны появляться в документе в порядке их перечисления.
Символы # PCDATA определяют так называемые анализируемые символьные данные (parsed character data). Анализатор браузера просматривает эти данные в поиске символа <, открывающего очередной тег, — вот почему этот символ нельзя помещать в символьные данные. Если понадобится отобразить его на экране, следует использовать символы-заменители < ;.
ПРИМЕЧАНИЕ
Символъьзаменители всегда начинаются символом &, завершаются символом ; и не могут быть пробелами.
Таким образом, приведенный выше фрагмент DTD позволяет создать такую разметку:
<книга>
<название>ХМЬ. Новые перспективы WWW</Ha3BaHne>
<автор>Бумфрей Ф. и др.</автор>
<издательство>ДМК</издательство>
<isbn>5-93700-007-2</isbn>
<цена>120р.</цена>
</книга>
Правильно описанный документ должен содержать корневой элемент. Его теги должны обрамлять всю остальную информацию. Если» например, мы хотим опубликовать перечень книг» можно создать такой корневой элемент книги:
<!DOCTYPE книги [
<!ELEMENT книги (книга*)>
<книги>
</книги>
Тег DOCTYPE объявляет имя корневого элемента, а в обрамляющих скобках [ и ] описываются этот элемент и все входящие в него элементы. В нашем примере корневой Элемент книги содержит 0 и более элементов книга — об этом свидетельствует символ * за именем элемента книга.
Шаблон преобразования указывает, как должен отображаться текст. Он всегда создается как внешний файл по отношению к основному XML-документу, в котором создается ссылка на этот файл. Шаблон представляет собой текстовый документ, составленный либо по правилам так называемых каскадных таблиц стилей, либо по правилам XML-подобного языка XSL (extensible Stylesheet Language — расширяемый язык таблиц стилей). Каскадные таблицы стилей узаконены и в HTML, однако для XML намного удобнее использовать мощные возможности языка XSL. Необходимость шаблона преобразования определяется тем, что в XML отсутствуют какие-либо средства форматирования отображаемого текста (шрифты, таблицы, блоки и т. п.). Без шаблона браузер не сможет нужным образом воспроизвести теги и отобразит документ так, как он выглядит в окне текстового редактора —с DTD и всеми тегами.
Таким образом, XML-документ содержит только отображаемые данные и ничего другого, в то время как шаблон преобразования определяет вид этих данных в окне браузера. Такое разделение определяет возможность динамического изменения шаблона преобразования в ответ на те или иные действия пользователя. Если, например, шаблон создает в окне браузера поле ввода и кнопку, пользователь может ввести в поле требуемую сумму и щелкнуть на кнопке. Обработчик щелчка, написанный на языке JavaScript (JScript, VBScript), заменит текущий шаблон другим, и в окне появятся сведения только о тех книгах, цена которых соответствует введенной сумме.
Если данные не предназначены для отображения в окне браузера, для XML-документа не создается шаблон преобразования. Вы можете спросить — для чего нужен такой документ? Дело в том, что язык XML чрезвычайно удобен для хранения структурированных данных, какими являются, например, наборы данных. Если вы заглянете в папку Source каталога размещения Delphi, то обнаружите в ее многочисленных вложенных папках XML-документы, не предназначенные для отображения в браузере и хранящие данные из тех или иных ТБД.
Замечательной особенностью языка XML является то( что он допускает отсутствие DTD! Можно не описывать вводимые теги, лишь бы документ отвечал двум требованиям:
в документе должен быть единственный корневой элемент, то есть элемент, который не может быть частью никакого другого элемента;
элементы не должны перекрывать друг друга.
Нельзя написать так:
<элемент1>
<элемент2>
</элемент1> </элемент2>
Нужно так:
<элемент1>
<элемент2>
</элемент2>
</элемент!>
Документы, которые удовлетворяют указанным требованиям, называются правильными. Правильные документы, содержащие DTD и строго следующие этому описанию, называются состоятельными.
Перед тем как перейти к пояснению XML и XSL на примерах, следует сделать два важных замечания.
Во-первых, язык XML (XSL) чувствителен к регистру букв. Теги <тег> и </Тег> — это разные теги!
Во-вторых, документы XML/XSL должны кодироваться кодировкой Unicode (по два байта на каждый символ). Чтобы создать текстовый файл с кодировкой Unicode, нужно в диалоговом окне сохранения файла открыть список Тип файла или Кодировка и выбрать пункт Документ Unicode. Замечу, что популярный редактор Блокнот в Windows 95/98/2000 (но не в ХР1) не может работать с кодировкой Unicode. Для этих ОС нужно использовать редактор WordPad или Word. В то же время анализаторы браузеров Internet Explorer допускают и обычную однобайтную кодировку. В инструкции анализатору <?xml?> можно указать кодировку с помощью атрибута encoding:
<?xml version="1.0" encodings"WINDOWS-1251м ?>
Простой пример
Создадим такой XML-документ:
<1Объявление версии XML -~>
<?xml version="1.0" encoding="WINDOWS-1251"?>
<пример>
<строка.1>3накомство с языком</строка.1>
<строка.2>XML</строка.2>
</пример>
Теги < ' -Комментарий --> определяют, как и в HTML, комментарий. Комментарий разрешается вставлять в любом месте, где можно поставить пробел.
С помощью тегов <?...?> в документ вставляются так называемые инструкции анализатору (processing instructions) — что-то наподобие директив компилятору в языке Delphi. Следующая инструкция извещает анализатор браузера о том, что документ создан средствами XML и использует кодировку, позволяющую вставлять в текст символы кириллицы:
<?хш1 version="1.0n encoding3MWINIX)WS-1251и?>
Наш документ относится к правильным XML-документам: он имеет корневой элемент <примерх/пример> с двумя вложенными в него элементами. Имена тегов должны начинаться буквой или символом подчеркивания и могут содержать произвольные буквы Unicode, цифры, точку, тире и двоеточие. Нельзя использовать символы xml в любом сочетании регистров как начальные символы имени тега. Спецификация XML 1,0 не накладывает ограничений на длину имен тегов.
Знакомство с языком XML 545
Располагаемый между тегами текст может содержать произвольные символы Unicode, кроме открывающей уголковой скобки <. Элемент может и не содержать никакого текста — такой элемент называется пустым. Для него используется сокращенный синтаксис:
<пустой_элемент/>
Пустые элементы обычно имеют атрибуты, применяемые для передачи анализатору дополнительной информации.
Если для документа не указан шаблон преобразования, браузер воспроизводит весь текст документа так, как это показано на pic B.tl.
Файл Правка 秋 & убранное Сдюис Qipwca
Назад ▼
C&J貿C&J貿C:\Documents and 5ettlngs\nana\MoH документы\ОеГ7У2\5оигсе\^х] ^J Переход 匕即佻田 *
C&J貿
C&J貿
<?xml version=l'1.0" encoding=,fWINDOWS-12Sla ?〉
-<прим&р>
<строка.1>3накомство с языком</стрйка. 1>
<CTpOKa.2>XML</CTpOKa.2>
</лрммер>
:“学脸К^^T好:[
Рис. В.11. Вид документа, не связанного с таблицей стилей
Шаблон преобразования
Создадим такой шаблон преобразования:
<?Х1П1 version21" 1.0" encoding=,'VJINDOWS-1251n ?>
<xsl:stylesheet version^n1.0"
xml ns:xsl = "ht tp://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<p><strongxxsl : value-of select^" / /строка . 1 ” />< /strongx/p>
<pxxsl:value-of select= 11 / /строка . 2 M /></p>
</xsl:template>
</xsl:styLesheet>
Теги xsl : stylesheet должны обрамлять тело шаблона, созданного средствами языка XSL. Помимо атрибута определения версии, открывающий тег обязан содержать ссылку на так называемое пространство имен. Эту ссылку задает следующий атрибут:
xmlns: xslhttp : / /№/w. w3 . org /1999 ZXSL/Traiis formn
Смысл атрибута заключается в указании анализатору на то, что где бы ни ветре- тплся элемент с префиксом xsl :, его нужно 11 н герпрстиро вать и соответствии со спецификацией XSL. И хотя параметр атрибута Hhttp: //www.w3 .org/1999/
IX Зак 449
XSL/Transform** представляет собой правильный URL-адрес, в момент анализа текста компьютер не обязательно связан с Интернетом. Сочетание xmlns является зарезервированным словом, за которым должны стоять двоеточие и символы xsl или f о, знак равенства и URL-адрес.
При ссылке на пространство имен http: / /www.w3 .org/1999/XSL/Transform мы получаем доступ к новейшей версии XSL — языку XSLT (буква «Т» означает Transform — расширяемый язык преобразования таблиц стилей). Этот язык доступен в браузерах IE5 и выше, устанавливаемых в Windows 98/2000/ХР. Если ваш браузер не поддерживает X$LT, вам нужно ссылаться на пространство имен http: /www.w3 .org/TR/WD-xsl. При этом значительная часть примеров окажется неработоспособной.
Любой шаблон задает образец для сопоставления и обрабатывающее действие. С помощью тега xsl : template задается образец, при этом информация для сопоставления определяется атрибутом match. Параметр " /" атрибута указывает на корневой элемент документа (в нашем примере — на тег пример). Встретив корневой элемент, анализатор обращается к шаблону в поисках указания на то, что нужно сделать с этим элементом. Такое указание он находит в двух следующих строках, обрамленных тегами <р>. Эти теги в HTML заставляют браузер начать новый абзац. Обратите внимание: в HTML тег <р> не имеет парного ему закрывающего тега, а в XML (XSL) любой открывающий тег обязательно должен сопровождаться закрывающим, поэтому каждая строка завершается тегами </р>. Внутри строк вставлены пустые теги xsl :value-of. Они обязывают анализатор найти в документе теги строка. 1 и строка. 2 и вставить в выходной поток заключенную в них информацию.
Чтобы анализатор смог найти шаблон документа, в документ нужно вставить инструкцию следующего вида:
<?хш1:stylesheet href="Examplе_1.xsl" type='text/xsl'?>
Атрибут href ссылается на содержащий шаблон файл, а атрибут type сообщает анализатору, что он будет иметь дело с текстом на языке XSL.
В результате в окне браузера документ отображается так, как показано на рис. В.12. Нетрудно заметить, что, изменяя шаблон, можно управлять порядком появления информации в окне браузера. Если, например, поменять названия тегов в атрибутах select, получим окно, показанное на рис. В.13,
Заметьте: исходный XML-документ остался без изменения, изменен лишь шаблон преобразования.
В рассмотренном примере вместо короткого и предельно простого кода на языке HTML использованы довольно сложные конструкции на языках XML и XSL. Вот как выглядит вариант реализации этого примера на HTML:
<HTML>
<BODY>
<PxSTRONG>3HaKOMCTBo с языкомс / STRONG>
<P>XML
</BODY>
</HTML>
Файл Правка % Цзбраннов Cgpewc Справка
® 3― ◎,国■囤 С^р Поиск ^Иэбранное 鱼注 & 晶"圻弋,昌 апа\Мон документы\Ре[7У2\5оигсе\СКар 23\ХМ1\ЕхатрЬ J .html [^.| 目 Перевод .金城洋毎
XMLXML^Готово:^Готово:时.?<1сй компьютер ,;.;.: ;::;%时.?<1сй компьютер ,;.;.: ;::;%
XML
XML
^Готово:
^Готово:
时.?<1сй компьютер ,;.;.: ;::;%
时.?<1сй компьютер ,;.;.: ;::;%
Рис. В.12. Простой пример в окне браузераРис. В.12. Простой пример в окне браузераРис. В. 13. Изменение порядка следования строкРис. В. 13. Изменение порядка следования строк
Рис. В.12. Простой пример в окне браузера
Рис. В.12. Простой пример в окне браузера
Рис. В. 13. Изменение порядка следования строк
Рис. В. 13. Изменение порядка следования строк
Конечно же, для создания простых страниц вроде той, что показана на рис. В.12, лучше использовать HTML. Преимущества XML в полной мере проявляются при обработке информации, содержащей множество однотипных записей, то есть полученной из наборов данных.
Обработка таблицы
Создадим следующий XML-документ:
<?xml version-111 . О" encoding= "WINDOWS-12 51 ° ?>
<?xml-stylesheet href="Example_2.xsl" type="text/xsl"?>
<кн.иги>
<книга>
<казвание>ХМЕ. Новые перспективы WWW</название>
< а в тор > Бумфре й Ф. и др.</автор>
<издат>ДМК</издат>
<isbn>5-93700-007-2</isbn>
<год>2000</год>
<страниц>688M/страниц»
<цёна>12Ор.</цена>
</книга>
<книга>
<название>ХМЬ и Java 2. Библиотека программиста (+CD)
</название>
<автор>Даконта М.# Сазанич А,</автор>
<издат>Питер</издат>
<год>20 01</год>
<isbn>5-318-00187-4</isbn>
<страниц>384</странии>
<цена>7Ор♦" цена>
</книга>
<книга>
<название>Электронный магазин на Java и ХМЬ</название>
<автор>Брогден В・, Минник К.</автор>
<издат>Питер</издат>
<isbn>5-316-00400-8</isbn>
<год>2002</год>
<страниц>400</страниц>
<цена>100р.</цена>
</книга>
<кн1?га>
<название>Рег! й XML. Библиотека программиста</название>
<автор>Рэй 9一 Макинтош Д,</автор>
<издат>Питер</издат>
<isbn>6-94723-482-3</isbn>
<год>2003</год>
<страниц>208</страниц>
<цена>90р.</цена>
</книга>
</книги>
В этом XML-документе описываются параметры четырех книг. Для отображения списка в таблице создадим шаблон преобразования:
<?xml version=ttl.0" encoding="WINDOWS-1251"?>
<xsl:stylesheet version^** 1.0*
xmlns:xsl="http://www.w3.org/1999/XSL/Transform*>
.<xsl:template niatch=n/">
<table border=n1">
<tr bgcolor=fl #CCCCCCn>
<td align=”center"><Ь>Название</Ь></td>
<td align="centerм><Ь>Автор</b></td>
<td align="center"><Ь>Издат. </bx/td>
<td alignsMcenterH><b>rofl</bx/td>
<td aligri="center”><b>ISBN</b></td>
<td align="center"><Ь>Стр.</bx/td>
<td align=”center"><Ь>Цена</b></td>
</tr>
Знакомство с языком XML 549
<xsJ:for-each selauu ="кммрм/кнмга">
<tr>
<tdxxsl : value-of<tdxxsl : value-ofselect="название"/></td>select="название"/></td>
<tdxxsl : value-of
<tdxxsl : value-of
select="название"/></td>
select="название"/></td>
<tdxxsl : value-of<tdxxsl : value-of<tdxxsl : value-of<tdxxsl : value-of<tdxxsl : value-of<tdxxsl : value-of<tdxxsl : value-of<tdxxsl : value-ofselect="aBTop"/></td> selec七二"мздзт"/></td> зе1есс=мгод"/></td> select^*' isbn" /></td>
<tdxxsl : value-of
<tdxxsl : value-of
<tdxxsl : value-of
<tdxxsl : value-of
<tdxxsl : value-of
<tdxxsl : value-of
<tdxxsl : value-of
<tdxxsl : value-of
<td aligns и rightM xxsl:value-of select ="страницw/></td>
<td align= ”right"xxsl:value-of select二°иена"/></td>
</tr>
v/xsl:for-each>
</table>
</xsl:tGmplate>
</xsl:$二yi^fh巳巳匸>
Для обработки всех книг используется тег <xls : for-each>. Его атрибут select должен указывать полное имя обрабатываемых тегов книга с перечислением всех вышележащих тегов — "книги/книга". Вложенные в него теги определяют форматирование всех параметров каждой книги исходного документа.
Наличие в XSL циклических тегов xls : for-each существенно сокращает объем кода. Представьте себе, каким громоздким был бы HTML-документ, описы- иаютии хотя бы сотню книг.
На рис. В.14 показано окно браузера со списком книг.
£айп Ораме Вид Цзвр«*«в Серене ^мкз£айп Ораме Вид Цзвр«*«в Серене ^мкз8"小0囱图心.аm ☆—аз;®二.4m》'"i!❸ UWocunents end 5аШпд5^Папа\Мои Акуиенты37У2\5оигсе*тр 23\心t叵empte 2,mii.Ц書^・Пц^хм 5«мм:8"小0囱图心.аm ☆—аз;®二.4m》'"i!❸ UWocunents end 5аШпд5^Папа\Мои Акуиенты37У2\5оигсе*тр 23\心t叵empte 2,mii.Ц書^・Пц^хм 5«мм:
£айп Ораме Вид Цзвр«*«в Серене ^мкз
£айп Ораме Вид Цзвр«*«в Серене ^мкз
8"小0囱图心.аm ☆—аз;®二.4
m》'"i!❸ UWocunents end 5аШпд5^Папа\Мои Акуиенты37У2\5оигсе*тр 23\心t叵empte 2,mii.Ц書^・Пц^хм 5«мм:
8"小0囱图心.аm ☆—аз;®二.4
m》'"i!❸ UWocunents end 5аШпд5^Папа\Мои Акуиенты37У2\5оигсе*тр 23\心t叵empte 2,mii.Ц書^・Пц^хм 5«мм:
, 「 通』》",_ 宀一7 物再巧寐骯:需* 叱嗨》
;XML. Новые перспективы WWW:Бунфрей Ф. и др 'Д1^К 12000.5-93700-007-2 : 688- 120
;XML и Java 2. Библиотека программиста (+СС).:Да«овтаМ.< Сазанич А .Питер .2001 ;5^318-00187-4 ; 384 ;70
:Электр-снный магазин на Java и XML^Брогден Б, МиннииК Дитер 2002 5-316-00400-8: 400 ; 100.
'Perl и XML. Библиотека программиста?Рэй Э..Макинтош Д Питер 2003 б-94723-482-3< 203i 90:
Рис. В. 14. Список книг
Сортировка
Разделение документа на две части — данные и шаблон преобразования — позволяет, не меняя данные, менять их вид в окне браузера.
Добавим в тег xsl : for-each атрибут order-by:
<xsl : Eor-each seiect= икниги/книгам order-by =11 цена*'>
Результат показан на рис. В.15.
Й1»ЖЙ1»Ж
Й1»Ж
Й1»Ж
£Ал Пике,2к и^ин*» <^swt_ &4WA _ _-⑥…f 豆一一⑥…旨一 @丁0tn№0tM№ ОбмСФИП-物мрйП«*» Ив^фМИО* 内0«<4陵;£Ал Пике,2к и^ин*» <^swt_ &4WA _ _-⑥…f 豆一一⑥…旨一 @丁0tn№0tM№ ОбмСФИП-物мрйП«*» Ив^фМИО* 内0«<4陵;,•;ЙД0*й・^^ С \FITER\Jig:,v2\s£cVh>ap_23^<b<l\E;3mple:!xfnr,•;ЙД0*й・^^ С \FITER\Jig:,v2\s£cVh>ap_23^<b<l\E;3mple:!xfnr归•各 鎗П0«4 n«w*® 1电.三.•/Лареш»彳 <:Ссыжй ”;归•各 鎗П0«4 n«w*® 1电.三.•/Лареш»彳 <:Ссыжй ”;
£Ал Пике,2к и^ин*» <^swt_ &4WA _ _
-⑥…f 豆一一⑥…旨一 @丁
0tn№0tM№ ОбмСФИП-物мрйП«*» Ив^фМИО* 内0«<4陵;
£Ал Пике,2к и^ин*» <^swt_ &4WA _ _
-⑥…f 豆一一⑥…旨一 @丁
0tn№0tM№ ОбмСФИП-物мрйП«*» Ив^фМИО* 内0«<4陵;
,•;ЙД0*й・^^ С \FITER\Jig:,v2\s£cVh>ap_23^<b<l\E;3mple:!xfnr
,•;ЙД0*й・^^ С \FITER\Jig:,v2\s£cVh>ap_23^<b<l\E;3mple:!xfnr
归•各 鎗
П0«4 n«w*® 1电.
三.•/Лареш»彳 <:Ссыжй ”;
归•各 鎗
П0«4 n«w*® 1电.
三.•/Лареш»彳 <:Ссыжй ”;
I : . ■ ■ ■■ Ншаамиеl^tKTpoHHbJii магазин на Java н XML !XML Новые перспективы WWWI : . ■ ■ ■■ Ншаамиеl^tKTpoHHbJii магазин на Java н XML !XML Новые перспективы WWWI Автор;Еро「Л,н ь , Мннннк 工'Бумфрей Ф н дрI Автор;Еро「Л,н ь , Мннннк 工'Бумфрей Ф н др〔XML к Java 2 ЕнЕлкотека программистз (+CD) Дакснта М . Сазэнич А〔XML к Java 2 ЕнЕлкотека программистз (+CD) Дакснта М . Сазэнич А*'erl н XML Библиотека программиста*'erl н XML Библиотека программиста.Ps而 3 . Макинтош Д.Ps而 3 . Макинтош ДШдах, Год ISBN Стр. Дела :1Пктеу :2002:5-316-0М00-8 400: 100;;Д1^'^bbO'5-9 37 00-007-2 \1^\ 12 0::ПитеР' ;200Т'5-318-00187^ f 384J " 7йЛитер':2003 ^6-94723-482-3^ 2死「/Шдах, Год ISBN Стр. Дела :1Пктеу :2002:5-316-0М00-8 400: 100;;Д1^'^bbO'5-9 37 00-007-2 \1^\ 12 0::ПитеР' ;200Т'5-318-00187^ f 384J " 7йЛитер':2003 ^6-94723-482-3^ 2死「/
I : . ■ ■ ■■ Ншаамие
l^tKTpoHHbJii магазин на Java н XML !XML Новые перспективы WWW
I : . ■ ■ ■■ Ншаамие
l^tKTpoHHbJii магазин на Java н XML !XML Новые перспективы WWW
I Автор
;Еро「Л,н ь , Мннннк 工
'Бумфрей Ф н др
I Автор
;Еро「Л,н ь , Мннннк 工
'Бумфрей Ф н др
〔XML к Java 2 ЕнЕлкотека программистз (+CD) Дакснта М . Сазэнич А
〔XML к Java 2 ЕнЕлкотека программистз (+CD) Дакснта М . Сазэнич А
*'erl н XML Библиотека программиста
*'erl н XML Библиотека программиста
.Ps而 3 . Макинтош Д
.Ps而 3 . Макинтош Д
Шдах, Год ISBN Стр. Дела :
1Пктеу :2002:5-316-0М00-8 400: 100;
;Д1^'^bbO'5-9 37 00-007-2 \1^\ 12 0:
:ПитеР' ;200Т'5-318-00187^ f 384J " 7й
Литер':2003 ^6-94723-482-3^ 2死「/
Шдах, Год ISBN Стр. Дела :
1Пктеу :2002:5-316-0М00-8 400: 100;
;Д1^'^bbO'5-9 37 00-007-2 \1^\ 12 0:
:ПитеР' ;200Т'5-318-00187^ f 384J " 7й
Литер':2003 ^6-94723-482-3^ 2死「/
®^«О®^«О没:;% 二;ЬЙ :2й WXigW:
®^«О
®^«О
Рис. ВД5. Неверная сортировка по столбцу «Цена»
Ошибка в сортировке происходит потому, что но умолчанию анализатор считает со])гир\емыг данные символьными. Уточним атрибут orcler-by:
<xs'l : for-eacri sclecc = " книги/книги " огбег - by - " п\!тпЬег (i;ewci)" >
Теперь столбец будет отсортирован правильно (рис. В.16).
!^№1E3!^№1E33 С ^PiIЕR\<|кП*ASoufcc\Chap_?3\XMI \Esample..? x<nl ■ M»c(o>oll Inlctnct Гхр1шг:(
!^№1E3
!^№1E3
“ ^^ Щмям $и^ &М$МН«9 О^МС ^файк«“ ^^ Щмям $и^ &М$МН«9 О^МС ^файк«二1内 Х1сгМ»И№ gS«*K*二1内 Х1сгМ»И№ gS«*K*?£^W*6 [3^^ER\dd7Y^SouKe\^^?£^W*6 [3^^ER\dd7Y^SouKe\^^^ ■- a ' '0"s*1Щж и^рмно» ^pH*ftftpw#^ ■- a ' '0"s*1Щж и^рмно» ^pH*ftftpw#Пвмн»Пвмн»习:•:家口爲**,: сшлкя >*习:•:家口爲**,: сшлкя >*!Кпввнне:АвхорjXML я Java 2 Библиотека программиста (,+CD) Даконта М , Сазанин А Perl н XML Еиблястека программиста Злектоонный магазин на Java н XML .XML Новые перспективы WWW!Кпввнне:АвхорjXML я Java 2 Библиотека программиста (,+CD) Даконта М , Сазанин А Perl н XML Еиблястека программиста Злектоонный магазин на Java н XML .XML Новые перспективы WWW;Рэй 3 . Макинтош Д Ерсгден Е . Мннннк К Бумфрей Ф н др;Рэй 3 . Макинтош Д Ерсгден Е . Мннннк К Бумфрей Ф н др!1Ьд*Г.^Год ISBKЛитер 2001 ;5-318-00!87--4 ^иТер':2003^-Й723-482-3 ;Пнтер ■2002^-316-00400-8 |ДМК :2000 ^-93700-007-2!1Ьд*Г.^Год ISBKЛитер 2001 ;5-318-00!87--4 ^иТер':2003^-Й723-482-3 ;Пнтер ■2002^-316-00400-8 |ДМК :2000 ^-93700-007-2Сп>, Ц«ма ; 3“ i …70' ”丽90: •100 ■ 100 ;688: 12(1,Сп>, Ц«ма ; 3“ i …70' ”丽90: •100 ■ 100 ;688: 12(1,33科?各瀛f科?各瀛f猷褊i^^^p;猷褊i^^^p;
“ ^^ Щмям $и^ &М$МН«9 О^МС ^файк«
“ ^^ Щмям $и^ &М$МН«9 О^МС ^файк«
二1内 Х1сгМ»И№ gS«*K*
二1内 Х1сгМ»И№ gS«*K*
?£^W*6 [3^^ER\dd7Y^SouKe\^^
?£^W*6 [3^^ER\dd7Y^SouKe\^^
^ ■- a ' '0"s*
1Щж и^рмно» ^pH*ftftpw#
^ ■- a ' '0"s*
1Щж и^рмно» ^pH*ftftpw#
Пвмн»
Пвмн»
习:•:家口爲**,: сшлкя >*
习:•:家口爲**,: сшлкя >*
!Кпввнне:Авхор
jXML я Java 2 Библиотека программиста (,+CD) Даконта М , Сазанин А Perl н XML Еиблястека программиста Злектоонный магазин на Java н XML .XML Новые перспективы WWW
!Кпввнне:Авхор
jXML я Java 2 Библиотека программиста (,+CD) Даконта М , Сазанин А Perl н XML Еиблястека программиста Злектоонный магазин на Java н XML .XML Новые перспективы WWW
;Рэй 3 . Макинтош Д Ерсгден Е . Мннннк К Бумфрей Ф н др
;Рэй 3 . Макинтош Д Ерсгден Е . Мннннк К Бумфрей Ф н др
!1Ьд*Г.^Год ISBK
Литер 2001 ;5-318-00!87--4 ^иТер':2003^-Й723-482-3 ;Пнтер ■2002^-316-00400-8 |ДМК :2000 ^-93700-007-2
!1Ьд*Г.^Год ISBK
Литер 2001 ;5-318-00!87--4 ^иТер':2003^-Й723-482-3 ;Пнтер ■2002^-316-00400-8 |ДМК :2000 ^-93700-007-2
Сп>, Ц«ма ; 3“ i …70' ”丽90: •100 ■ 100 ;
688: 12(1,
Сп>, Ц«ма ; 3“ i …70' ”丽90: •100 ■ 100 ;
688: 12(1,
3
3
科?各瀛f
科?各瀛f
猷褊i^^^p;
猷褊i^^^p;
Рис. В.16. Правильная сортировка
В XSLT есть более мощные средства сортировки. Удали те атрибут order by из гега for-each и сразу за -)тм тегом вставьте такой тег:
<xsl : sorn ortier^ " ascending " sc ] есг = " странги;" / >
Таблица будет отсортирована по возрастанию количества страниц в кишах (рис. В. 17).
Замена параметра "ascenclincj" на ,гdescending" позволяет отсоргировагь книги в обрагиом порядке.
•5 C.\PlT£R\del7 V2\Sou,ce、Chap_ 23XXM1 \£xaniple•5 C.\PlT£R\del7 V2\Sou,ce、Chap_ 23XXM1 \£xaniple臣学乌竺_也_¥°3个 学竺 &рйм臣学乌竺_也_¥°3个 学竺 &рймMfctosnfl Inteirmt EkpIsciMfctosnfl Inteirmt EkpIsci血Ё1血Ё1中「方;< 6 Q扌“中' 羽净a £№*«№№ 6备*如中「方;< 6 Q扌“中' 羽净a £№*«№№ 6备*如j^^舊下一j^^舊下一ITERVfel7vASo<Jce\Chap_23\XML\£k*mple_2.><rNITERVfel7vASo<Jce\Chap_23\XML\£k*mple_2.><rN]窺一盘’1ft ‘i4 —亠Ff?纷嗖К渺^二]窺一盘’1ft ‘i4 —亠Ff?纷嗖К渺^二
•5 C.\PlT£R\del7 V2\Sou,ce、Chap_ 23XXM1 \£xaniple
•5 C.\PlT£R\del7 V2\Sou,ce、Chap_ 23XXM1 \£xaniple
臣学乌竺_也_¥°3个 学竺 &рйм
臣学乌竺_也_¥°3个 学竺 &рйм
Mfctosnfl Inteirmt EkpIsci
Mfctosnfl Inteirmt EkpIsci
血Ё1
血Ё1
中「方;< 6 Q
扌“中' 羽净a £№*«№№ 6备*如
中「方;< 6 Q
扌“中' 羽净a £№*«№№ 6备*如
j^^舊下一
j^^舊下一
ITERVfel7vASo<Jce\Chap_23\XML\£k*mple_2.><rN
ITERVfel7vASo<Jce\Chap_23\XML\£k*mple_2.><rN
]窺一盘’1ft ‘
i4 —亠Ff?纷嗖К渺^二
]窺一盘’1ft ‘
i4 —亠Ff?纷嗖К渺^二
IНя»#«нме< Автор 注&尢工峭 ISBN七砸;風《,I
'Perl и XtdL Библиотека программиста.Рс-й ^,. Макинтош Д|Пятер;2003 :6-?472? 482-3」〔®9(J
iXML и Java 2 Библиотек прсгу?аммисга (+CD) Даконга М, СазанинА-Питерi2001 ^-318-00187-4 ■384;70
^Электронный магазин на Java н XML:Брогдеи Б . Минник К|Питср:2002 :5-316-00400-8-400 ;100 I
!XML Новис перспективы ^JTW^умфрей Ф я др^ДМК:2000 :5-93^00-007-2 :688^А20 ■
>Ж^>Ж^
>Ж^
>Ж^
Рис. В.17. Сортировка по количеству страниц
Фильтрация
В XSLT определен тег xsl : if, с помощью которого можно отбирать записи. Единственным атрибутом этого тега может быть test:
<xsl:i £ test="усповное_внрйжопие">
Условное выражение содержит два операнда и знак операции сравнения между ними. Операции сравнения перечислены в табл. В.1
Таблица В.1. Операции сравнения языка XSLT
Операция
Смысл
Операция
Смысл
Операция
Смысл
匚;
Меньше
Меньше или равно
Раш】。
>
Больше
> =
Больше или равно
1 =
Не равно
Операндами могут быть имена тегов, некоторые встроенные функции и строковые последовательности. Если условное выражение истинно, выполняются все теги, вложенные в тег xsl : if. Вот как, например, можно показать King по цене 100 и менее рублей:
<хs1:i f LesL ^"цена&11;-100">
<t r>
seiecC- 30i?c匚二 selecr- s e丄с c匸= select -seiecC- 30i?c匚二 selecr- s e丄с c匸= select -название"/></二d> dRTOp"/></cd> издат"/></td> год" / х/2> is匕门"//td>название"/></二d> dRTOp"/></cd> издат"/></td> год" / х/2> is匕门"//td><tzdxxsl : value-of
seiecC- 30i?c匚二 selecr- s e丄с c匸= select -
seiecC- 30i?c匚二 selecr- s e丄с c匸= select -
название"/></二d> dRTOp"/></cd> издат"/></td> год" / х/2> is匕门"//td>
название"/></二d> dRTOp"/></cd> издат"/></td> год" / х/2> is匕门"//td>
<r.dxxsl : val:ie-of
<tidxxsl : valiiQ-of v匸dxxsl : value-of <tdxxsl : val ue-of
<td al ign=" right Nxxsl:value-of select - "страниц" / >< / tzd> uL.d al ign^ " r tght,r ><xs 1 : val;.e-o f selecr.= " цена" / >< / r cl> </tr>
xsl:1>
Встроенная функция position() возвращает число, соответствующее номеру текущей записи. Вот как с ее помопхью мояш© вывести только две первые записи:
<xsl:if test="position(}<Зи>
<tr>
</tr>
</xsl:if>
Более сложные фильтры можно создать с помощью тегов choose, when и otherwise:
<xsl:choose>
<xsl :when ге8Ь=пВыражениевдля_проверки',>
<!— Обработка -->
</xsl:when>
<xsl:when test=нДругое_зыражениеи >
<1—Другая обработка -->
</xsl:when>
<xsl:otherwise>
<!—-Обработка, если не выполнена ни одна другая обработка --> </xsl:otherwise>
</xsl:choose>
Концепция объектной модели документа
Концепция объектной модели документа (Document Object Model, DOM) предназначена для средств обработки, какими являются прежде всего сценарии на языках JavaScript, JScript. VBScript. В этой модели XML-документ рассматривается как набор именованных объектов, имеющих связанные с ними свойства и методы. Например, любой документ имеет объекты document и documentEl ement. Первый содержит весь документ в целом, второй — корневой элемент со всеми вложенными в него дочерними элементами. Для объекта do с ume nt Е1 ement определены свойство childList, содержащее список всех дочерних элементов, и метод addchild, с помощью которого можно вставить в документ новый элемент. Замечу, что концепция DOM строго стандартизована, то есть она не зависит от конкретного языка программирования.
Краткая справка по языку Visual Basic .NET
В этом приложении приведены краткие справочные данные по языку программирования Visual Basic .NET. В нем описаны синтаксис языка, типы данных, переменные, преобразования типов, выражения и операторы.
Синтаксис языка
Подобно Delphi, алфавит Visual Basic .NET содержит все латинские буквы и знак подчеркивания. Последний является также знаком переноса части оператора на следующую строку. В этом случае он не должен заканчивать идентификатор:
'Следующий перенос неверен:
Console.WriteLine_
("Hello!”)
'нужно так:
Console.WriteLine _
("Hello!n)
Естественным признаком конца оператора является конец строки. Оператор, как ■это показано выше, может занимать несколько строк. На одной строке могут располагаться несколько операторов. В этом случае между соседними операторами ставится двоеточие:
Console.WriyeLine("Hello!и) : Console.ReadLine(I
Как и в Delphi, в Visual Basic .NET не учитывается регистр букв, но среда Delphi (и Visual Studio) выделяет зарезервированные слова прописными начальными символами (Dim, As, Sub и т, д.).
Символ апострофа (' ) применяется для вставки комментария в текст программы. Его можно вставить в любое место строки, при этом все символы от апострофа до конца строки образуют комментарий.
Типы данных
В Visual Basic .NET имеется три группы типов данных: примитивные, значащие и ссылочные.
Примитивные типы данных совпадают с таковыми в CTS (общей аютемой типов) платформы NET, но их названия в некоторых случаях отличаются. К ним относятся (в скобках дается название типа в CTS) Boolean, Byte, Char, Date (DateTime), Decimal (вещественное, 16 байт), Double (вещественное, 8 байт). Integer (Int32), Long (Int64)r Short (Intl6), Single (вещественное, 4 байта). Названия всех примитивных типов являются зарезервированными словами.
Значащие типы содержат в себе примитивные типы, а также перечисления и структуры (аналог записей в Delphi).
Ссылочные типы содержат ссылки на реальные объекты. К ним относятся классы, массивы, интерфейсы, делегаты и строки.
Объявления переменных
При объявлении переменных используются зарезервированное слово Dim или модификаторы доступа Public, Protected, Friend, Protected Friend, Private и Static. При объявлении сначала указывается одно из перечисленных слов, затем имя переменной, зарезервированное слово As и тип переменной. Переменную можно объявлять в любом месте программы до ее первого использования. При объявлении разрешается инициировать переменную (присваивать ей начальное значение). Например:
Dim Counter As Integer = 1
Private IsCheck As Boolean = False
Protected Btn Ab Button = New Button
Конструкция New имя„класса используется для создания экземпляра нужного класса.
Массивы
Массивы объявляются так же, как и скалярные переменные, но после имени массива должны идти круглые скобки» в которых через запятую указываются верхние значения индексов размерностей (нижнее значение индекса по любой размерности равно нулю). Максимальное количество размерностей — до 60. Например:
Dim Matrix(2, 2) As Double * Массив 3x3 вещественных чисел
Dim Vector(11) Ав Integer ' Одномерный массив из 12 целых чисел
Как и обычную переменную, массив можно инициировать в момент объявления. При этом в скобках не указываются верхние границы индексов» а лишь запятые, если массив многомерный:
Dim Arrayl () As Integer = (1, 2, 3) 'Массив из трех целых чисел
Dim Array2( , ) Ав Integer = (0+1, 0+2), (1+0, 1+3)
Последнее объявление идентично таким строкам:
Dim Array2(1, 1) Ав Integer;
АггауЗ(Q, 0) = 1: Array2(0, 1) = 2
Array2(1, 0} =0: Array2(1, 1) = 3
Если в качестве типа элементов массива используется тип Obj ect, массив может хранить данные разных типов:
Dim Book(2) Ав Object;
Book(0) = "Название*
Book (1} = "Автор1* Book<2) = 123.00
В программе можно использовать динамические массивы, то есть массивы, длина которых изменяется в ходе прогона программы. Для этого массив объявляется с пустыми скобками. На этапе прогона определяется необходимая длина массива по каждому измерению и вызывается оператор ReDim:
Dim Arr() Ав Object
Dim 工,J Ag Integer
1 = 2
J = 2
ReDi® Arr(I, J)
Преобразования типов
Различают явное и неявное преобразования типов. Первое делается в контексте программы, без ведома программиста. Например:
Dim I Ав Integer Dim X Ав Double
X = 123.45
I = X * Неявное преобразование значения типа Double к типу Integer
Замечу, что неявное преобразование может привести к потере точности (в нашем случае 工 получит значение 123) и, как правило, не способствует повышению надежности программ.
Для явного преобразование используются функции CBool, CByte, CChar, CDate, CObj,CInt, CShort, CSng, CStr, СТуре. Все они (кроме СТуре) получают единственный параметр типа Object (то есть любого типа: в Visual Basic .NET тип Object трактуется как Variant) и возвращают результат нужного типа (Bool, Byte, Char и т. д.). Функция СТуре получает два параметра: значение и тип, к которому приводится это значение:
Din S Ав String = "123"
Dim X Ав Integer = СТуре(S, Integer)
Выражения и операции
В табл. Г.1 перечислены арифметические и логические операции Visual Basic NET.
Таблица Г.1. Арифметические и логические операции
Операция
Знак операции
Сложение
Вычитание
Перемена знака Умножение
Деление
Целочисленное деление
Остаток от деления по модулю
Возведение в степень Сравнение Сравнение объектов Подобие Лошческое И Логическое ИЛИ Логическое НЕТ Исключающее ИЛР1 Сокращенное И Сокращенное ИЛИ
\
Mod
<><=>= = <>
Хв
Like
And
Or
Kot
Xor
AndAleo
ОГА.18О
Сокращенные операции AndAlmo и OrAlso имеют такой синтаксис:
выражение! AndAleo выражение2 выражение! ОнАХво выражение2
Они действуют подобно операциям И и ИЛИ, но не вычисляют выражениеЗ, если выражение! дает однозначный результат (False для AndAlmo и True для Or Also).
Операторы присваивания
Оператор присваивания в Visual Basic .NET выполняет ту же функцию, что и в Delphi: он вычисляет значение выражения, стоящего справа от знака присваивания, и присваивает его переменной, стоящей слева от знака. В отличие от Delphi, знаком присваивания является знак равенства (=), а не символы двоеточия и знака равенства (:=).
В Visual Basic NET используются также префиксные формы операторов присваивания: &=, +=, -=, *=, /=, \=, л=. Они действуют следующим образом: над
правым (или левым, см. ниже) выражением осуществляется нужная операция и полученное суммируется со значением переменной слева от знака операции:
Dim S As String =
S &二"World!-
"Hello,"
n
's =
"Hello, World!
Dim i As integer
=123
—
* i =
130
Dim k Ab Integer
=2
k л= 3
'k =
8
Dim b Ab Double =
123.
45
b *= -1
,b =
-123,45
Условный оператор
Условный оператор Visual Basic .NET подобен такому же оператору Delphi, но позволяет обойтись без операторных скобок. Для этого используются зарезервированные слова Ed Xf:
1£ условие Then < произвольное количество операторов > Е1ве < произвольное количество операторов > End if
Если используется по одному оператору в каждом блоке, формы условных операторов в Visual Basic .NET и Delphi совпадают:
1£ условие Then оператор: if условие Then оператор! Slse оператор2
Для сложных проверок можно использовать зарезервированное слово Elself:
if А = 0 Then
Consile.Writeln("ноль")
Blseif А > 0 Tneh
Console.Writein(нбольше нуля")
Else
Console. Writein (** меньше нуля") find If
Оператор выбора
Оператор выбора в Visual Basic .NET подобен оператору case в Delphi, но позволяет обойтись без операторных скобок:
Select Саве переменная
Case значение!
произвольное количество операторов >
Саве значение2
произвольное количество операторов >
find Select
В приведенной синтаксической форме значениеХ может быть конкретным значением переменной выбора, но может также определять диапазоны значений:
Sub ChackValue (^Val num As Integer) 4 Select Case num
Console. WriteLine ("1")
3
Console.WriteLinet"2 или 3B)
to 6
Console.WriteLine("от 4 до 6") Case is > 7
Console -WriteLine("больше 7 й)
End Select End Sub
Оператор For
Как и во многих других случаях, оператор позволяет обходиться без операторных скобок:
For к = начальное^эначение То конечное_значение V группа onejpaTOpoB >
Next к
Оператор While
Оператор с предварительной проверкой условия выполняет вложенные в него операторы до тех пор, пока тестируемое условие остается истинным:
While условие < группа операторов > End While
Оператор Do
Оператор с последующей проверкой условия выполняет вложенные в негр опера- торы до тех пор, пока тестируемое условие остается истинным (вариант While) или ложным (вариант Until):
Do < группа операторов > Loop While условие Do < группа операторов > Loop Until условие
Использование классов общего назначения платформы .NET Framework
Классы общего назначения играют вспомогательную роль, но их значение трудно переоценить. В этом приложении рассматриваются коллекции» классы для работы со строками и файлами, а также сериализация объектов.
Коллекции
Концепция коллекций не нова —bVCLсуществуют классы TList, TStringList и TCollection. Все они решают схожие задачи: обеспечивают удобные средства хранения объектов разного типа. В CTS существует пространство имен System, Collection, которое имеет свои интерфейсы и классы для обслуживания коллекций. К коллекциям относятся списки, стеки, массивы, хэш-таблицы, очереди и словари.
Интерфейсы пространства имен System.Collection
В табл. Д.1 перечислены специальные интерфейсы для работы с коллекциями.
Таблица Д.1. Интерфейсы для работы с коллекциями
ИнтерфейсНазначение
lEnumerableПредоставляет интерфейс для перечисления
элементов коллекции в одном направлении
Таблица Д.1 (продолжение)
Интерфейс
Назначение
ICollection
Определяет размер и методы синхронизации коллекции. Наследует методы интерфейса lEnumerable
IList
Обслуживает коллекцию, элементы которой упорядочены по индексу
IDictionary
Обслуживает коллекцию, состоящую из пар «ключ—значите#
lEnumerator
Определяет методы коллекции с перебором в одном наира&Пбнмм
IDictionaryEnumerator
Определяет перечисление на базе словаря (класс Dictionary)
ICompare
Определяет методы для сравнения двух коллекций
IHashCodeProvire
Определяет хэш-код для указанного объекта
Интерфейс I Enumerable содержит единственный метод:
function GetEnumerator: IEnumerator;
Свойства и методы интерфейса I Enumerator перечислены в табл. Д.2.
Таблица Д.2. Свойства и методы интерфейса lEnumerator
Свойство г метод
Назначение
property Current: Obj ес t ; function MoveNext : Boolean;
pcocedure Reset;
Возвращает текущий элемент коллекции
Делает текущим следующий элемент коллекции и возвращает False, если коллекция исчерпана Делает текущим первый элемент коллекции
Свойства и методы интерфейса iCollection представлены в табл. Д.З.
Таблица Д.З. Свойства и методы интерфейса ICollection
Свойство, метод
Назначение
pcopecty Count : Integer;
Возвращает количество элементов, содержа-
щихся в коллекции
property I s Syn ch ron i z ed :
Возвращает True, если класс Collection
Boolean;
безопасен в отношении потоков
property SynchRoot : Object ;
Возвращает объект, обеспечивающий безопасный в отношении потоков доступ к коллекции
procedure CopyTo(Ar: array;
Копирует коллекцию в массив Аг, начиная
Index:Integer);
с индекса Index
ПРИМЕЧАНИЕ
Безопасными в отношении потоков называются экземпляры классов, которые позволяют сразу нескольким потокам команд обращаться к методам и свойствам объекта без угрозы возникновения конфликтов.
Свойства и методы интерфейса IList показаны в табл. Д.4.
Таблица Д.4. Свойства и методы интерфейса IList
Свойство, метод
Назначение
property IsFixedSize: Boolean;
Возвращает True, если объект List имеет фиксированный размер
property IsReadOnly: Boolean;
Возвращает True, если объект List доступен только для чтения
property Item (Index : Integer): Object;
Возвращает элемент коллекции по его индексу
function Add (Value: Object): Integer;
Вставляет элемент в коллекцию и возвраща* ет его индекс
procedure Clear;
Очищает коллекцию
function Contains (Value: Object): Boolean;
Возвращает True, если коллекция содержит указанный элемент
function IndexOf (Value:
Object):Integer;
Возвращает индекс указанного элемента
procedure Insert(Index:'
Integer; Value: Object);
Вставляет элемент в нужное место коллекции
procedure Remove(Value:
object);
Удаляет элемент из коллекции
procedure RemoveAt(Index: Integer);
Удаляет из коллекции элемент с указанным индексом
Свойства и методы интерфейса 工Dictionary перечислены в табл. Д.5.
Таблица Д.5. Свойства и методы интерфейса IDictionaiy
Свойства, методы
Назначение
property IsFixedSize: Boolean;
Возвращает True, если объект Dictionary имеет фиксированный размер
property IsReadOnly: Boolean;
Возвращает True, если объект Dictionary доступен только для чтения
property Item (Key: Object): Object;
Возвращает элемент коллекции по его ключу
property Kyes : iCollection;
Возвращает коллекцию ключей
property Values: ICollection;
Возвращает коллекцию значений
562 Приложение Д • Использование
классов общего назначения...
Таблица Д.5 (продолжение)
Свойства, методы
Назначение
procedure Add (Key, Value : Objret);
Добавляет элемент в коллекцию
procedure Clear;
Очищает коллекцию
function Contains (Key: Object):
Возвращает True, если элемент с указанным
Boolean;
ключом содержится в коллекции
function Remove(Key: Object);
Удаляет элемент с указанным ключом
Даже беглый обзор интерфейсов показывает, что элементами, хранимыми в коллекциях, могут быть только значения ссыло^шых типов. Это связано с самой природой коллекций, которые представляют собой наборы указателей на хранящиеся в куче данные. Если в коллекции потребуется сохранить значение значимого типа (например, Integer), то можно использовать один из следующих способов: • Перевести это значение в строку:
var i: Integer;
Collection•Add(i.ToString);
• Создать класс-оболочку и сохранять экземпляры этого класса:
type
Wrapperclass = class(&Objetc)
public
Value: Integer;
constructor Create(Vai: Integer); override;
end;
constructor Wrapperclass.Create(Vai: Integer);
begin
inherited Create;
Value := Vai;
end;
Collection.Add(Wrapperclass.Create C123));
Классы пространства имен System.Collection
Помимо описанных интерфейсов, пространство имен содержит соответствующие классы-коллекци и.
Класс Stack
Класс Stack хранит объекты по принципу программного стека: первым пришел, последним ушел (FILO — First In, Last Out). Он исполняет интерфейсы iCollection,
工Enumerable и IClonable, Последний не входит в пространство имен System. Collection. Он имеет метод Clone, который используется для создания новых идентичных объектов.
Собственные методы класса Stack перечислены в табл. Д.6.
Таблица Д.6. Методы класса Stack
Метод
Назначение
function Peek: Object;
Возвращает элемент, находящийся в вершине стека
function Pop : Obj ect ;
Удаляет элемент с вершины стека и коллекции
procedure Push (Obj : Object);
Помещает новый элемент в вершину стека
function ToArray: Obj ect;
Помещает все элементы стека в объект класса ArrayList
Для демонстрации класса stack подготовлена такая программа (проект Add_5\
Collection 弟&cDemddpr):
program StackDemQ;
{$APPTYPE CONSObE)
usee
Sy st«n> Col lect ions ;
procedure Showcollection (Collection: IBnwetr^ble; iResh: String);
/ / Эта »апо^х^тельная процедура печатает ©^р^^ ЯШ U и тёкущ^ё содержимое стека var
EnumSt ack : lEnumerator ;
begin
EniunStack := Collection. беЬЕпшпегаЬог ;
Writein;
Writeln(Rem);
while EnumStack.MoveNext do Writein(EnumStack.Current); end; var
MyStack: Stack;
k: Integer;
beffin
// Создаем коллекцию:
WStack : = Stack.Create;
〃 Наполняем стек шестью строками: for k := 1 to 6 do
MyStack.Push('Строка 1 + k.ToString);
// Показываем его содержимое:
ShowCollection(MyStack, 'Начальное состояние стека:');
// Удаляем вершину стека:
MyStack.Pop;
Showcollection(MyStack, 'Метод POP:');
// Вставляем в стек новый элемент:
MyStack.Push(1===Новая вершина стека===');
ShowCollection(MyStack, 'Метод PUSH:');
Readln;
end.
На рис. Д.1 показан результат работы программы.
脑丸簧鶴门撚悔楠,嗣畸%触瑜密需输出如<м物穂聋瀛峭^山 一г抬則婢#内聲京$吗,n,心%儲、驚. 卜触;
Рис. Д.1. Демонстрация стека
Специально для удобства работы с коллекциями в язык Delphi введен оператор for... in,..do. С его помощью можно несколько упростить процедуру Showcollection:
procedure Showcollection(Collection: IEnumerable; Rem: String); var
k: ^Object; // Twn параметра цикла должен совпадать с типом // элементов коллекции или быть &Objecc
begin
Writein;
Writein(Rem);
for k in Collection do
Writein(k.ToString);
end;
ПРИМЕЧАНИЕ
Параметр цикла for...in...do должен иметь такой же тип, как и элементы коллекции. Если тип элементов неизвестен или в коллекции хранятся элементы разных типов, назначайте ему тип &Obectf который совместим с любым типом CTS, а имеющийся в нем метод ToString преобразует содержимое значения в строку.
Класс Queue
Класс Queue хранит элементы по принципу классической очереди: первым пришел, первым ушел (FIFO — First In, First Out). Подобно стеку, очередь исполняет интерфейсы iCollection,工Enumerable, iClonable.
В табл. Д.7 представлены собственные методы коллекции Queue.
Таблица Д.7. Методы класса Queue
Метод
Назначение
procedure Enqueue;
Добавляет очередной элемент в конец очереди
fimction Dequeue: Object;
Возвращает первый элемент очереди и удаляет его из коллекции
£unction Peek: Object;
Возвращает (но не удаляет) первый элемент очереди
functimiToArray: Object;
Копирует элементы очереди в массив
procedure TrimToSize;
Устанавливает емкость колласщш равной количеству хранящихся в н瞳:®цементов
Класс Queue демонстрирует следующая программа, результат работы которой показан на рис. Д.2 (проект Add_5\pollecHons\QueueDemo.dpr):
program QueueDemo j
{$APPTYPE CONSOLE}
uses
System. Collections?
procedure Showcollection (Collection: lEnumerable; R^s String);
var
S: string;
begin
Writein;
Writein(Rem);
for S in Collection do
Writein(S);
end;
var
MyQueue: Queue;
Integer;
begin
/ / Создаем очередь 方笈 6 элементов ;
MyQueue := Queue.Create(6);
// Наполняем очередь шестью строками: for k 1 to 6 do
MyQueue.Enqueue(* Строка 1 + k.ToString);
// Показываем содержимое очереди;
Showcollection(MyQueue, 'Начальное состояние очереди:');
// Удаляем первый элемент очереди: MyQueue.Dequeue;
ShowCollection(MyQueue, * Метод DEQUEUE:');
// Вставляем в очередь новый элемент:
MyQueue. Enqueue ( * =-=Новьлй элемент очереди==='); ShowCollection(MyQueue, 'Метод ENQUEUE:');
Readln;
end.
.瀛,无*縊篇献&,続磁备療礴裁嬲鱒谶嚇刷載融孤诂1a蠟看牖盛協說緬i甌喊』感飞喩臨喊藏:贯褊嵋颯题”м魄Т厩繳臓實锻*靄您餡瀛输曲标emmMT £厘崎;
Рис. Д.2. Результат работы программы
Как видите, обработка очереди отличается от обработки стека только порядком удаления и добавления элементов.
Класс ArrayList
Класс ArrayList предназначен для хранения объектов произвольного типа (в том числе и ArrayList» то есть допускается создание многомерных хранилищ данных). В отличие от рассматривавшихся ранее классов Stack и Queue, в нем нет четко оговоренного способа пополнения/удаления коллекции. Вместе с тем
он имеет многочисленные методы для сортировки элементов, их поиска и работа с диапазонами. Он исполняет интерфейсы IList, ICollection. lEnumerabe
и IClonable.
В табл. Д.8 перечислены свойства и методы класса.
Таблица Д.8. Свойства и методы класса ArrayList
Свойство, метод
Назначение
property Capacity: Integer;
Определяет текущую емкость коллекции
function Adapter (List : IList): ArrayList;
Создает на основе списка коллекцию ArrayList
procedure AddRange (C: ICollection);
Добавляет в конец ArrayList коллекцию С
function Binarysearch (Obj : Object):Integer;
Осуществляет двоичны 甘 поиск элемента в отсортированной коллекции и возвращает индекс элемента или отрицательное число, если элемент не найден
function FixedSize (A:
ArrayList) : ArrayList;
Возвращает коллекцшо фиксированного размера, элементы которой можно изменять, но нельзя добавлять или удалять
function GetRange (Start, Count Integer): ArrayList;
: Возвращает диапазон элементов
procedure insertRange (Ar: ArrayList);
Вставляет диапазон элементов
function LastlndexOf(Obj:
Object):Integer;
Возвращает индекс последнего вхождения элемента в коллекцию
function Readonly(AL: ArrayList): ArrayList;
Возвращает коллекцию только для чтения
procedure Remove(Obj : Object),
; Удаляет элемент из коллекции
procedure Removelt(Index:
Integer);
Удаляет элемент с заданным индексом
procedure RemoveRange(Index, Count: Integer);
Удаляет диапазон элементов
fubction Repeat(Obj: Object; Count: Integer) : ArrayList;
Создает коллекцию, в которой элемент Obj повторяется Count раз
procedure Reverse;
Изменяет порядок следования элементов на обратный
procedure SetRange(Index: Integer; c: Collection);
Вставляет коллекцию с, начиная с индекса
Index
procedure Sort;
Сортирует коллекцию
procedure TrimToSize;
Устанавливает емкость коллекции равной количеству ее элементов
Класс ArrayList иллюстрирует следующая программа, результат работы кото рой показан на рис. Д.3 (проект Add.5\CollecBons\ArrayListDemo.dpr):
program ArrayListDemo;
{$APPTYPE CONSOLE}
usee
System.Collections;
procedure ShowCollection(Coll: ICollection; Rem: String);
var
Book: String;
begin
Writein;
Writein(Rem);
for Book in Coll do
Writein(Book)?
end;
var
Rooks, SubList, AddList: ArrayList;
begin
П Создаем и наполняем коллекцию:
Books := ArrayList.Create;
Books.Add(*Д.Бокс, К.Сейлз. Основы платформы .NET, том 1.•);
Books.Add(1А.Гарнаев. Visual Studio .NET 20031);
Books.Add('Э.Троелсен- C# и платформа .NET');
Books,Add('К.Пачеко. Delphi for .NET');
Books.Add(* С.Уолтер• ASP.NET*);
ShowCollection(Books, 1Исходная коллекция:*);
〃 Сортируем коллекцию:
Books-Sort;
ShowCollection(Books^ 'Метод SORT:');
/ / Сортируем в обратном порядке:
Books•Reverse;
Showcollection(Books, 1Метод REVERSE:');
// Выделяем диапазон:
SubList := Books•GetRange(2, 3);
Showcollection(SubList, * Метод GETRANGE:');
// Создаем и вставляем диапазон:
AddList := ArrayList-Create(2);
AddList.Addf *H.Секунов. Разработка приложений на C++ и C#');
AddList.Add('М.Кэнту. Delphi 7 для профессионалов');
Books.AddRange(AddList};
Showcollection(Books, 'Метод ADDRANGE:*);
// Иллюстрация метода TrimToSize:
Writein;
Writein(* Емкость перед TRIMTOSIZE:' + Books.Capacity.ToString);
Books.TrimToSize;
Writein(1 Емкость после TRIMTOSIZE:' + Books.Capacity.ToString);
Readln;
end.
s4 「,辎,#一"',心一7即*叔…義筛 ^仆&龍/)#MSm驚%窮發ЫМ需竊AN締шЛат* ”丁糞
Рис. Д.З. Иллюстрация работы с коллекцией ArrayLlst
Замечу, что по умолчанию начальная емкость коллекции ArrayList составляет 16 элементов. При расширении коллекции ее емкость удваивается, составляя 16, 32, 64 и т. д*. элементов. Метод TrimToSize отсекает не используемые в настоящий момент элементы.
Метод Binarysearch реализует алгоритм двоичного поиска элемента и, по идее, работает значительно быстрее, чем поиск перебором. При сравнении по умолчанию учитывается разница в регистре букв. Чтобы не учитывать разницу, следует воспользоваться перекрытой версией метода, в которой вторым параметром обращения задается метол сравнения:
var
AL: ArrayList;
k: Integer;
AL.Sort;
k := AL.Binarysearch('АлФаВиТ*, CaselnsensitiveComparer.Create);
Для работы метода коллекцию необходимо отсортировать, так как двоичный поиск основан на том, что элементы располагаются по возрастанию. Если в коллекции есть несколько экземпляров искомого элемента, метод не гарантирует выбор первого или последнего элемента и возвращает просто индекс одного из одинаковых элементов.
Класс HashTable
Класс HashTable предназначен для создания коллекций, состоящих из пар «ключ— значение». Все ключи должны быть уникальными — это непременное условие. За счет уникальности ключей коллекция позволяет быстро отыскать нужный элемент.
В качестве ключа может использоваться любой набор символов. Перед помещением ключа в коллекцию он хэшируется» то есть к нему применяется один из механизмов получения хэш-кода.
ПРИМЕЧАНИЕ
Хэш-код — это зашифрованный клю% характерной особенностью которого является то, что по этому коду невозможно восстановить исходный ключ. Другая особенность — даже малейшее изменение ключа (например, пропуск одной из сотен букв) порождает совершенно другой хэш-код.
Хэш-коды и связанные с ними значения хранятся в разных сегментах памяти, что ускоряет поиск нужных элементов.
Класс исполняет интерфейсы IDectionary, ICollection, I Enumerable, IC 1 onable и ISerilizable. Последний обеспечивает хранение и чтение данных. В следующей программе, результат работы которой показан на рис. Д4 иллюстрируется использование коллекции (проект Add_5\CollecUons\HashTableDemo.dpr):
program На shTableDemo;
{$APPTYPE CONSOLE}
uses
SysUtils, System.Collections;
type
St-^teCapi tai Info = class / / Класс для хранения
Name: String;// имен столиц а
Foundation: Integer; // дат лх основания
constructor Create(aName: string; aFound: Integer); override;
end;
constructor StateCapitallnfо.Create(aName: String; aFound: Integer); begin
inherited Create;
Name := aName;
Foundation := aFound;
end;
var
HT: HashTable;
procedure Printcapitalinfo(Key: String);
// Выводит элемент данных по его ключу var
CI: StateCapitalInfo;
begin
CI := HT[Key] as StateCapitallnfo;
Writein('Столица: ', CI.Name, 1 Дата основания: CI.Foundation);
end;
begin
HT := HashTable.Create; // Соз да ем и наполняем коллекцию
НТ.Add(*RF*, StateCapitallnfо.Create('Москва', 1047));
НТ.Add('US *, StateCapitallnfо.Create('Вашингтон' , 1791));
НТ.Add('UK *, SCateCapitallnfo.Create('Лондон', 700));
НТ.Add('DN*, StateCapitalInfo.Create('Берлин1 , 731));
/ / Выводим элементы no их ключам;
PrintCapitalInfo(1RF');
PrintCapitallnfo{1 US');
PrintCapitallnfо('UK'};
Printcapitalinfo('DN1);
Readln;
end.
Рис. Д.4. Результат работы программы
Обработка строк
Типы String и System. ^String в Delphi 2005 содержат символы Unicode. В этом, собственно, и заключается главное различие типов string в Delphi 2005 и предыдущих версиях. Однако тип System. ^String от String отличается существенно. В этом разделе описываются эти отличия.
Преобразование значений других типов в строку и обратно
Несмотря на внешнюю схожесть типов String (VCL) и System.^String (CTS), они имеют совершенно разные функции преобразования. В предыдущих версиях Delphi для преобразования значения какого-либо типа в строку использовались многочисленные функции типа XXXToStr (IntToStr, FloatToStr, TimeToStr и т. п.). Обратное преобразование осуществлялось симметричными функциями StrToXXX. В CTS базовый тип System.^Object и, таким образом, все порожденные от него классы имеют метод ToString, преобразующий значение типа в строку. Все значимые типы объявлены в виде записей (структур), имеющих методы ToString и Parse. Наличие этих методов предельно упрощает преобразование типов в строку и обратно:
program ConvertTypesDemo;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
Integer;
b: Boolean;
begin
i := 123456;
b ;= b.Parse(1True *);
Writein(i.toString);
Writein(b.Tostririg)? Readln;
end.
В результате прогона этой программы (проект Add_5\Strings\ConvertTypesDemo.dpr) на 呻ане появятся д^ такие строки:
123456
True
Форматирование строк
Для форматирования строки прш^няется функция Format:
Writeln(System.&String.Format(* Система программирования {0}*,
'Delphi 2005'));
В функции сначала указывается форматирующая строка, имеющая от одного до трех заполнителей ((0}, {1}, {2}), за ней через запятую располагается до трех заменителей1. Порядок следования цифр в заполнителях должен соответствовать порядку следования заменителей:
Writeln(System.&String.Format('{2} {1} (0}', 'ноль't *один', 1 два'));
Будет выведено:
два один ноль
Для каждого заполнителя можно указать количество символов, которое должен занимать соответствующий заменитель. Если длина поля вывода больше дл1шы заменителя, последний выравнивается вправо, если меньше, длина поля игнорируется. Если длш1а отрицательная, заменитель выравнивается влево. Длина поля ука* зывается в фигурных скобках заполнителя через запятую справа от его номера:
WritelnCSystem.&String.Format(*{0, 5}{1, -4}1, •ноль1r 1 один *));
Вьшод:
нольодин
Форматирование чисел
Платформа .NET Framework допускает использование спецификаторов для форматирования чисел. Эти спецификаторы можно указывать в методе ToString. Спецификатор представляет собой латинскую букву (строчную или прописную — не имеет значения).
В табл. Д.9 перечислены спецификаторы для форматирования чисел.
Таблица А9. Спецификаторы для форматирования чисел
Символ Влияние на формат
Е еПредставляет число в экспоненциальном формате, например 3,2 е+003
F fПредставляет число с фиксиро1шнной точкой (запятой), например 3200Д
G gПредставляет число в десятичном или экспоненциальном виде в зависимо
сти от размера
N пПредставляет число с разделителями тысяч, например 3 200,00
С сПредставляет число в денежном формате
Следующая программа, результат работы которой показан на рис. Д・5, иллюстрирует форматирование чисел (проект Add_5\Strings\NumericFormatsDemo.dpr):
program NmnericFormatsDemo;
($APPTYPE CONSOLE}
Точнее, заполнителей может быть сколько угодно, лишь бы цифры в них принадлежали диапазону 0…2, а вот заменителей может быть не более трех.
uses
SysUtils; var
D: Double; begin
D := 3141592.654;
D.ToString('e*));D.ToStringf'f'));D.ToString(*g'));D.ToString(ln'));D.ToString('c'));D.ToString('e*));D.ToStringf'f'));D.ToString(*g'));D.ToString(ln'));D.ToString('c'));end.end.Рис. Д.5. Форматирование чиселРис. Д.5. Форматирование чиселWriteLn('Формат E: WriteLn('Формат F: WriteLn('Формат G: WriteLn('Формат N: WriteLn('Формат C: Readln;
D.ToString('e*));
D.ToStringf'f'));
D.ToString(*g'));
D.ToString(ln'));
D.ToString('c'));
D.ToString('e*));
D.ToStringf'f'));
D.ToString(*g'));
D.ToString(ln'));
D.ToString('c'));
end.
end.
Рис. Д.5. Форматирование чисел
Рис. Д.5. Форматирование чисел
Замечу, что форматы N и С по умолчанию представляют дробную часть числа округленной до двух цифр. Если после спецификатора указать целое неотрицательное число, дробная часть будет округляться до указанного количества цифр:
Writeln(D.ToString('пб')); // Вывод 3 141 592t654000
Writein(D.TSstring(* сО')); // Вывод 3 141 593P.
Форматирование даты и времени
Спецификаторы для форматирования даты и времени представлены в табл. Д.10.
Таблица Д.10. Спецификаторы для форматирования даты и времени
Спецификатор
Влияние на формат
d
Дата в коротком формате
D
Дата в расширенном формате
Обработка строк 575
Спецификатор
Влияние на формат
f
Дата в расширенном формате и время и коротком (формате
F
Дата и время в расширенном формате
g
Дата и время в коротком формате
G
Дата в коротком (формате и время в расширенном формате
М m
Месяц н число
R г
Дата и время в формате RIC 1123
s
Дата и время в фо]7мите ICO 8601
Время в коротком формате
T
Время в расширенном формате
u
Дата и время в (формате ICO 8601 для всемирного времени
U
Всемирные дата и время
Yy
Месяц и год
Следующая программа, результат работы которой показан на рис. Д.6, иллюстрирует форматирование даты и времени (проект Add_5\Strings\DateTimeFormatesDemo.dpr):
program DataTimeFormat esDemo;
{$APPTYPE CONSOLE}
ивев
SysUtils;
var
N: System,DateTime;
鑑,皿矶居》& * 無:h 轲…Г 《 节 1^8^Ж)М5аШ#йС1Ш4Ш1 lffi^'M',btaf#ne>/» • Г 笃鑑,皿矶居》& * 無:h 轲…Г 《 节 1^8^Ж)М5аШ#йС1Ш4Ш1 lffi^'M',btaf#ne>/» • Г 笃Рис Д.6. Форматирование даты и времениРис Д.6. Форматирование даты и времени
鑑,皿矶居》& * 無:h 轲…Г 《 节 1^8^Ж)М5аШ#йС1Ш4Ш1 lffi^'M',btaf#ne>/» • Г 笃
鑑,皿矶居》& * 無:h 轲…Г 《 节 1^8^Ж)М5аШ#йС1Ш4Ш1 lffi^'M',btaf#ne>/» • Г 笃
Рис Д.6. Форматирование даты и времени
Рис Д.6. Форматирование даты и времени
beginN := Now;Wriueln(1 Формат d: Writein(* Формат D: Writein('Формат f: Writein('Формат F: Writein(* Формат g: Writein('Формат G: Writein(1 Формат t: Writein('Формат T: Writein(1 Формат M: Writein('Формат R: Writein('Формат s: Writein('Формат u: Writein{* Формат Y: Readln;end.beginN := Now;Wriueln(1 Формат d: Writein(* Формат D: Writein('Формат f: Writein('Формат F: Writein(* Формат g: Writein('Формат G: Writein(1 Формат t: Writein('Формат T: Writein(1 Формат M: Writein('Формат R: Writein('Формат s: Writein('Формат u: Writein{* Формат Y: Readln;end.,N.ToString('d')); ,N.ToString(*D')); ,N.ToString('f') 1 ; ,N.ToString('F')); ,N.ToString(* g1)}; ,N,ToString('G*)}; ,N.ToString(*t')); ,N.ToString{'T*)); ,N.ToString(*m')); ,N.ToString((r1)); ,N.ToString('s')); ,N.ToString('u*)); .N.ToString( 'у* H ;,N.ToString('d')); ,N.ToString(*D')); ,N.ToString('f') 1 ; ,N.ToString('F')); ,N.ToString(* g1)}; ,N,ToString('G*)}; ,N.ToString(*t')); ,N.ToString{'T*)); ,N.ToString(*m')); ,N.ToString((r1)); ,N.ToString('s')); ,N.ToString('u*)); .N.ToString( 'у* H ;
begin
N := Now;
Wriueln(1 Формат d: Writein(* Формат D: Writein('Формат f: Writein('Формат F: Writein(* Формат g: Writein('Формат G: Writein(1 Формат t: Writein('Формат T: Writein(1 Формат M: Writein('Формат R: Writein('Формат s: Writein('Формат u: Writein{* Формат Y: Readln;
end.
begin
N := Now;
Wriueln(1 Формат d: Writein(* Формат D: Writein('Формат f: Writein('Формат F: Writein(* Формат g: Writein('Формат G: Writein(1 Формат t: Writein('Формат T: Writein(1 Формат M: Writein('Формат R: Writein('Формат s: Writein('Формат u: Writein{* Формат Y: Readln;
end.
,N.ToString('d')); ,N.ToString(*D')); ,N.ToString('f') 1 ; ,N.ToString('F')); ,N.ToString(* g1)}; ,N,ToString('G*)}; ,N.ToString(*t')); ,N.ToString{'T*)); ,N.ToString(*m')); ,N.ToString((r1)); ,N.ToString('s')); ,N.ToString('u*)); .N.ToString( 'у* H ;
,N.ToString('d')); ,N.ToString(*D')); ,N.ToString('f') 1 ; ,N.ToString('F')); ,N.ToString(* g1)}; ,N,ToString('G*)}; ,N.ToString(*t')); ,N.ToString{'T*)); ,N.ToString(*m')); ,N.ToString((r1)); ,N.ToString('s')); ,N.ToString('u*)); .N.ToString( 'у* H ;
Использование методов и свойств строк
Класс System, &String имеет богатый набор свойств и методов, которые могут использоваться для работы со строками.
ПРИМЕЧАНИЕ
Индексация символов в классе System.&String начинается с нуля.
Сравнение строк
Наиболее простой способ сравнения двух строк — использование логического оператора равно (=):
var
, S2: System.&Stгing;
if SI = S2 then
Writein (*С1^)оки равны1) else Writein (* Строки не равны*);
В классе определен также метод Compare:
if System.bString.Compare(SIr SI) = 0 then
Writein(* Строки равны') else
Writein('Строки не равны1);
Несмотря на явную сложность» qb имеет свои преимущества. Дело в том, что в перегруженном варианте он может дополняться логическим выражением, указывающим, следует ли игнорировать жшкожную разницу в регистре букв (True — следует):
SI := 'DeLpHi *;
:= 'Delphi';
if System.^String.Compare(Si, S2, True) = 0 then
Writeln('Строки равны *) else // Зтот оператор сработает
Writein('Строки не равны');// Этот оператор будет пропущен
В еще одном перегруженном варианте метод принимает четвертый параметр в виде указания на язык (Cultureinfo), на котором написаны строки.
Во всех случаях метод возвращает 0» если строки идентичны, -1, если первая строка в алфавитном порядке меньше второй, и +1, если больше.
Удаление символов из строки
Для удаления символов используются методы Trim, TrimStart, TrimEnd и Remove. Методы Tri叫 TrimStart и TrimEnd удаляют пробелы, причем метод Trim — в начале и конце строки, метод TrimStart — только в начале, а метод TrimEnd — только в конце. Помимо пробелов удаляются также символы табуляции или любые другие непечатаемые символы (для которых метод Char. IsWhiteSpace возвращает True). В некоторых случаях могут пригодиться перегруженные варианты этих методов, в которых разрешается указывать, какие символы нужно удалять:
program TrimD^no;
{$APPTYPE CONSOLE}
ивев
SysUtils;
var
ArrChr: array of Char;
begin
SetLength(ArrChr, 4);
ArrChr[1] := *1';
ArrChr[2] := *2';
Writeln('1234567891.Trim(Arrchr)); // Вывод: 3456789
Readln; end.
Метод Remove принимает два целых параметра — индекс первого удаляемого символа (индексация начинается с 0) и количество удаляемых символов:
Writeln(* 123456789'.Remove(3, 2)); // Вывод: 1236789
Поиск символов в строке
Для поиска символов предусмотрен метод IndexOf:
Writeln('1234'.IndexOf('1'));// Вывод: О
Как и в случае методов TrimXXX, можно указать массив искомых символов, который рассматривается в этом случае как подстрока:
uses
SysUtils;
var
ArrChr: array of Char;
19 Зак. 449
begin
SetLength(ArrChr# 4);
ArrChr[1] := '11;
ArrChr[2] := 1 O';
Writein(* 1234567891.IndexOf(ArrChr)); // Вывод:-工
Readln; end.
Этот же результат дает и такой поиск:
Wrieln(1234567891.IndexOf('10'));
Изменение строки
Метод Replace заменяет часть строки:
Writeln('1234*.Replace{'34', '56')); // Вывод: 1256
Метод Insert вставляет часть строки. Первым параметром обращения к методу указывается индекс, который должен получить первый вставляемый символ. Если этот индекс превышает длину строки, возбуждается исключение:
Writeln(* 1234'- Insert(2, '56'В;// Вывод:工25634
Writeln('1234'.insert(5, '56'));// Ошибка/ Исключение
Метод Substring извлекает из строки подстроку. Он принимает два параметра: индекс первого символа и количество символов подстроки. Если подстрока выходит за границы строки, возбуждается исключение:
Writeln (' 1234' .SubStringll, 2));/ /Вывод: 23
Для изменения регистра букв строки используются методы ToUpper и ToLower:
Writelnlrpascal'.ToUpper);// Вывод: PASCAL
Разделение и объединение строк
Для разделения строки на подстроки используется метод Split, Этот метод в качестве входного параметра принимает массив символов, которые будут определять границы подстрок, и возвращает массив подстрок. Например (проект Add_5\Strings\SplitDemo.dpr):
program SplitDemo;
($APPTYPE CONSOLE}
uses
SysUtils;
var
ArrStr: array of System.&String;
System.^String;
ArrChr: array of Char;
begin
S : = ' -: *;// Строка с ограничителями подстрок
ArrChr := S.ToCharArray; // Преобразуем ее в массив символов
S := 'Система программирования:Пе1рЬ1-2005' ; // Строка для расщепления
ArrStr := S.Split(ArrChr); // Получаем массив подстрок for S in ArrStr do
Wrireln(S);// Печатаем подстроки
Readln; end.
Результат работы этой программы показан на рис. Д.7.
® Г Ш#<нтна aa^i i^1m^<й1ыШ®м^л^*нш1Ж 用g裔臘讎错皤亂藉賦鴨寫乳蝙旧仆事赠皤…^口窯
Рис Д.7. Результат работы программы
Метод ToCharArray преобразует строку в массив символов Unicode.
Объединение строк реализует метод Join. Он принимает два параметра: символ, который будет отделять объединяемые строки друг от друга, н массив строк.
Вставим в конце предыдущего примера такой оператор:
Writeln(System.^String.Join(' *, ArrStr));
Будет выведена такая строка:
Система программирования Delphi 2005
Класс StringBuilder
Класс StingBuilder (пространство имен System.Text) представляет собой модификацию класса &String для работы со строками большого размера — он более эффективно использует память. Во всем остальном он во многом похож на обычную строку и легко преобразуется к ней методом ToString. При обращении к этому методу можно указать начальный индекс и длину подстроки содержимого StringBuilder.
По умолчанию объекту класса выделяется память для хранения 16 символов. Ес” ли содержимое превышает начальный размер, этот объем удваивается. Начальный размер можно указать в конструкторе объекта:
var
StrBldr: StringBuilder;
StrBldr := StringBuilder.Create(rУказание начальной длины', 10000);
ПРИМЕЧАНИЕ
Объект ^String можно не создавать конструктором. В этом случае Delphi 2005 считает, что строка содержит неопределенное значение NIL (в предыдущих версиях неинициализированная строка String эквивалентна пустой строке). Объект StringBuilder всегда создается конструктором. Обращение к неинициализированному объекту StringBuilder вызывает исключение.
Главное различие объектов &String и StingBuilder заключается в способе доступа к содержимому объектов. Для размещения строки в первом используется оператор присваивания, в то время как в StringBuilder для этого предусмотрен метод Append. Чтобы передать содержимое строки строковому свойству другого объекта, снова требуется присваивание. Для аналогичных целей в объекте StringBuilder имеется метод ToString.
Методы Insert, Remove, Replace имеют такое же назначение, как и в классе ^String. Для доступа к отдельным символам объекта StringBuilder предназначено его свойство Chars. Свойство Capacity определяет текущую емкость объекта, а свойство Length — текущую длину его содержимого. Если этому свойству присвоить 0, содержимое объекта будет уничтожено, однако его текущая емкость останется прежней. Методом AppendFormat к содержимому объекта можно добавить форматированную строку.
Работа с файловой системой
В приложениях .NET Framework часто возникают две в общем случае схожие задачи: сохранить (прочитать) содержимое данных (файла) и сохранить (прочитать) текущее состояние объекта в файле или таблице базы данных. Несмотря на несомненную схожесть указанных задач, в рамках .NET Framework для решения каждой из них предусмотрены свои классы. Классы обработки файлов сосредоточены в пространстве имен System, 10. Работа с этими классами рассматривается в этом разделе. Процесс сохранения текущего состояния объекта в памяти или на носителе информации называется сериализацией объекта, а обратный процесс — десериализацией. Эти процессы управляются классами, находящимися в пространствах имен System. Runtime. Serialization, которые рассматриваются в следующем разделе.
Классы для работы с файловой системой
Работа с файловой системой подразумевает обработку как папок (каталогов), так и зарегистрированных в них файлов. Соответствующие классы определены в пространстве имен System. 10.
В табл. Д.11 перечислены классы, использующиеся для работы с файловой системой.
Таблица Д.11. Классы для работы с файловой системой
Класс
Назначение
Directory
Содержит статические методы для создания н использования папок. Эти методы можно вызывать без создания соответствующих объектов
DirectoryInfo
Содержит свойства и методы для создания и использования папок. Доступ к членам класса возможен только после создания его экземпляра
File
Содержит статические методы для работы с файлами. Эти методы можно вызывать без создания объекта
Fileinfo
Содержит методы для работы с классами, которые становятся доступными после создания объекта этого класса
Path
Вспомогательный класс для работы с маршрутами доступа (путями)
Статические классы Directory и File не требуют создания соответствующих объектов. Однако при обращении к их методам запускается система проверки безопасности доступа к коду (Code Access System, CAS), что замедляет работу этих методов. В связи с этим при обработке нескольких папок (файлов) удобнее использовать классы Directoryinfo и Fileinfo.
В 32-разрядных версиях Windows, как известно, для передачи данных между различными устройствами (оперативной памятью, дисковой памятью, сетью) используется концепция потоков данных (stream). Классы для работы с потоками данных также определены в пространстве имен System. 10 и представлены в табл. Д.12.
Таблица Д.12. Классы для работы с потоками данных
Класс
Назначение
MemoryStream NetworkStream Filestream BinaryReader Binarywriter StreamReader StreamWriter
Хранилище данных в оперативной памяти
Позволяет передавать поток по сетевому соединению
Представляет собой базовый класс потока для записи и чтения файлов
Считыаает данные из двоичных файлов
Записывает данные в двоичный файл
Считывает данные из текстовых файлов
Записывает данные в текстовый файл
Создание и уничтожение папок
Создание и уничтожение папки проще всего осуществлять методами Create- Directory и Delete класса Directory. Например:
const
DirPath = 'с:\D2005_proba1;
begin
if not Directory.Exists(DirPath} then
Directory.CreateDirectory(DirPath);// Создаем папку
if Directory.Exists(DirPath) then
DirDirectory.Delete(DirPath, True);// Уничтожаем папку
end.
Строка DirPath может содержать вложенные папки. Если они не существуют» то при выполнении метода CreateDirectory они будут созданы.
Метод Delete удаляет пустую папку. Если нужно уничтожить также пустые вложенные папки, ему передается параметр True.
Использовать методы класса Directory Info для тех же целей менее удобно:
program DirCreate;
{$APPTYPE CONSOLE}
uses
SysUtils, System.IO;
var
Dir: Directorylnfo;
begin
Dir := DirectoryInfo.Create(*c:\D2005.x>roba*);
if not Dir.Exists then
Dir.&Create;
if Dir.Exists then
Dir.Delete(True);
Readln;
end.
При обращении к конструктору Directoryinfo. Create ему передается маршрут доступа к создаваемой папке, но сама папка не создается. Лишь после проверки факта отсутствия папки она создается методом Create.
ПРИМЕЧАНИЕ
Обратите внимание — именем Create по принятой в Delphi практике называются конструкторы объектов (в CTS имя конструктора совпадает с именем класса). В классе Directoryinfo именем Create называется метод. Чтобы компилятор Delphi обратился к методу, а не к конструктору, перед именем метода Create стоит знак амперсанта (&).
Проверка существования папки необходима, так как попытка создать заново существующую папку или уничтожить несуществующую вызовет исключение.
При обращении к методу Delete ему передается логический параметр, указывающий на необходимость уничтожения вложенных папок.
Перемещение и копирование папок
Для перемещения папки используется метод Move класса Directory или метод MoveTo класса Di rectory Info. В качестве параметров первому передаются имена обеих папок, а второму — только имя папки назначения:
Directory. Move (' FroniMove 1 , ' ToMove1);
Dir := Directorylnfо.Create('FromMove');
Dir.&Create;
Dir.MoveTo('ToMove*);
Фактически методы Move и MoveTo не перемещают папку, а лишь переименовывают ее, причем обе папки должны находиться в одном и том же разделе одного и того же диска. После выполнения метода начальная папка исчезает, если ее имя отличается от имени папки назначения. Методы обычно используют для добавления вложенных папок в уже существующие. В этом случае имя папки назначения повторяет имя исходной папки и расширяет ее именами вложенных папок:
Directory.Move('FromMove'# 'FroraMove\SubFolderl\SubFolder2');
На практике значительно чаще возникает проблема физического изменения положения папки, например переноса её на другой дисковый носитель. Для этого необходимо скопировать содержимое исходной палки в папку назначения. Я не буду детально рассматривать эту в общем случае не тривиальную задачу. Скажу лишь, что она решается рекурсивным вызовом некоторой процедуры, которой передаются имена обеих папок. В процедуре просматривается содержимое исходной папки, и ее файлы копируются в палку назначения. Если среди файлов встречается вложенная папка, процедура вызывает сама себя (это и называется рекурсивным вызовом), но уже с другими именами папок.
При копировании нужно предусмотреть возможность отсутствия папки назначения} существование в ней копируемого файла и пр. Поскольку все это выходит за рамки обсуждаемой темы, в следующем примере возможность существования такого рода сопутствующих проблем игнорируется. Показанная далее программа (проект Add_5\Files\CopyDirectory.dpr) копирует файлы из одной поставляемой с Delphi 2005 папки в другую. В выбранной для копирования папке отсутствуют вложенные папки, что исключает необходимость рекурсии. Копируемые файлы заменяют одноименные файлы, существующие в папке назначения:
program CopyDirectory;
($APPTYPE CONSOLE}
usee
SysUtils #
System.10;
var
Files: Array o£ String;
k: Integer;
FromFile, ToFile: String;
FileAttr: FileAttributes;
const
FromDir 二'c:\Program Files\Coinmon Files\Borland ' +
'Shared\Images\GlyFX\Small•;
ToDir = 'c:\D2005_lmages\'; becrin
// Создаем папку назначения:
i£ not Directory.Exists(ToDir) then Directory.CreateDirectory (ToDir);
// Получаем содержимое исходной палки:
Files := Directory.GetFileSystemEntries(FromDir);
// Цикл копирования файлов;
£or k := Low(Files) to High(Files) do begin
// Имя очередного файла или вложенной папки:
FromFile := Files[k];
// Получаем атрибуты файла (папки):
FileAttr := &File.GetAttributes(FromFile);
// Блокируем рекурсивную обработку вложенной папки: i£ (FileAttr and FileAttributes.Directory) о
FileAttributes.Directory then begin
ToFile := ToDir + Path.GetFileName(FromFile);
Writein(ToFile);
&File.Copy(FromFile, ToFile, True);
end; end; Writein('Всего файлов: *, High(Files) + 1); Readln;
and.
Напомню, что практически во всех современных операционных системах (и в Windows в том числе) в файловой системе используются так называемые таблицы размещения файлов (File Allocation Tables, FAT). В этих таблицах указываются файлы корневого каталога и вложенные папки верхнего уровня. В FAT каждой вложенной папки, в свою очередь, указываются фа&хы и вложенные папки. В каждой строке FAT помимо имени файла (папки) указываются также дополнительные сведения — начальный кластер расположения файла (папки), дата создания и, в том числе, так называемые файловые атрибуты» которые задаются перечислением System. 10.FileAttributes. Значения этого перечисления указаны в табл. Д.13,
Таблица Д.13. Значения перечисления FileAttributes
Значение
Описание
Archived
Обычный файл, доступный для копирования и удаления
Compressed
Сжатый файл
Device
Зарезервировано для будущего использования
Directory
Вложенная папка
Encrypted
Файл зашифрован (если речь идет о файле) или все включенные в папку файлы зашифрованы (если речь идет о пайке)
Hidden
Скрытый файл
Normal
Обычный файл, для которого не могут быть установлены никакие другие атрибуты
NotContentIndexed
Файл не может быть индексирован службой нндексацни контекста операционной системы
Offline
Файл не подключен, и его данные в настоящее время недоступны
Readonly
Файл только для чтения
ReparsePoint
Файл содержит реперную точку» то есть блок данных, ассоциированных с другими файлом или папкой
SparseFile
«РыхлыА* файл, большая часть которого содержит нули
System
Системный файл, который может использовать только операционная система
Temporary
Временный файл
Хотя в справочной литературе Fil eAttributes называется перечислением (enumeration), с позиций Delphi это ^перечисление» является множеством, то есть файловым атрибутом может быть комбинация перечисленных значений. Используемая в примере проверка блокирует обработку любой папки:
if (FileAttr and FileAttributes.Directory) <>
FileAttributes.Directory then
Исследование информации о записи FAT
Информация о единичной строке FAT хранится в свойствах класса FileSysteminfo. В табл. Д.14 перечислены эти свойства.
Таблица Д.14. Свойства класса FileSystemInfo
Свойство
Описание
Attributes
Атрибуты
CreationTime
Время создания файла (папки)
CreationTimeUTC
Время создания в формате UTC (Universal Time Coordinated — всемирное координированное время). Время в формате UTC соответствует времени по гринвичскому меридиану и координируется с показаниями атомных часов
продолжение^^
Таблица Д.14 (продолжение)
Свойство
Описание.・.
Exists
Признак существования
Extension
Расширение файла
FullName
Полное имя (с маршрутом доступа)
LastAccessTime
Время последнего обращения к файлу (папке)
LastAccessTimeUTC
Время последнего обращения в формате UTC
LastWriteTime
Время последнего изменения
LastWriteTimeUTC
Время последнего изменения в формате UTC
Name
Имя файла (папки)
Классы Directory Info и Fileinfo являются наследниками базового класса FileSystemTnfo и получают все его свойства.
Следующий пример (проект Add_5\Rles\GetDirInfo.dpr) иллюстрирует использование класса Di rectory Info:
program GetDirlnfo;
{$APPTYPE CONSOLE}
uses
SysUtils, System.10;
const
i = 30; // Выравнивание правого края поясняющей надписи
var
Dirinfo: Directoryinfo;
begin
Dirinfo := DirectoryInfо.Create('C:\PrQgram Files1};
Writelh(1 Полное имя:*:i # Dirinfo.FullName);
Writelnl'Имя:':i, Dirlnfo.Name);
Writein(1 Время создания:':i, Dirinfo.CreationTime.ToString);
Writein('Время создания UTC:4:i f
Dirinfo.Creat ionTimeUtc.Tostring);
Writein(* Признак существования:r:i, Dirinfo.Exists.ToString);
WritelnC * Расширение;':i, Dirinfo.Extension);
Writein('Время последнего доступа:*:i,
DirInfo.LastAccessTime.ToString);
Writein('Время последнего обновления:':ir
DirTnfo,LastWri t eTime•Tostring);
Writelri('Атрибуты:•:i, Ehtun(Dirinfo.Attributes).Tostring);
Readln;
end.
Результат работы программы показан на рис. Д.8.
Рис. Д.8. Результат работы программы
Запись и чтение файлов
В этом разделе рассматривается обработка файлов на основе классов CTS.
Обработка текстовых файлов
При работе с текстовыми файлами сначала создается поток класса FileSteram. Данные записываются в файл с помощью вспомогательного объекта класса StreamWriter, а читаются объектом класса StreamReader. Например (проект
Add_5\Ales\StringAleDemo.dpr):
proffram Str ingF ileDemo;
{$APPTYPE CONSOLE)
usee SysUtils, System.IO;
var Stream: FileStream; Writer: StreamWriter; Reader: StreamReader; S: String;
begin // Запись в текстовый файл Stream := FileStream.Create('strings.dat *,
FileMode.Create, FileAccess.Write); tzy
Writer := StreamWriter.Create(Stream); tzy
Writer.WriteLine(*Мело, мело по всей Земле,');
Writer.WriteLine(*Во все пределы.*);
Writer.WriteLine('Свеча горела на столе.');
Writer.WriteLine('Свеча горела...');
finally
Writer.Close;
end; finally
Stream.Close;
end;
// Чтение из текстового фаЯяа
Stream : = Filestream. Create (1 strings., dat*,
FileMode.Opea, FileAccess.Read);
try
Reader s= Streaitfleader.Create (Stream);
try
repeatJ
S := Reader.ReadLine;
if S <> NIL then
Writein(S);
until S = NIL;
finally
Reader.Close;
end;
finally
Stream.Close;
end;
Readln
❷nd.
При создании объекта FileStream ему передаются имя файла и два параметра: FileMode» определяющий способ создания потока, и FileAccess» регулирующий доступ потока к данным. В табл. Д.15 и Д.16 указываются допустимые значения этих параметров.
Таблица Д.15. Значения параметра HleMode
Значение
Описание
Append
Добавляет записи в существующий файл или создает новый. Требует» чтобы параметр Fil eMode имел значение write
Create
Создает новый файл или переписывает существующий. Требует, чтобы параметр FileMode имел значение write
CreateNew
Создает новый файл, а если он уже существует, возникает исключение. Требует, чтобы параметр FileMode имел значение Write
Open
Открывает существующий файл. Если файла нет, возникает исключение
OpenOrCreate
Открывает существующий или создает новый файл, если он еще не
создан
Truncate
Открывает существующий файл и делает его размер равным нулю
Таблица Д.16. Значения параметра RleAccess
Значение
Описание
Read
Поток может читать данные
Readwrite
Поток может читать и записывать данные
Write
Поток может записывать данные
Для потока существует понятие текущей записи — в эту запись помещаются дан* ные, и из нее они считываются. Положением текущей записи можно управлять с помощью метода Seek, имеющего такую сигнатуру: function Seek(Offset: Long; Origin: SeekOrigin): Long;
Здесь Offset — смещение относительно позиции, указанной параметром Origin. Перечисление SeekOrigin может иметь значение, указанное в табл. Д.17.
Таким образом, указанный ниже вызов сделает текущей запись с индексом 10 от начала потока (индексация начинается с 0):
Stream.Seek(10, SeekOrigin.Begin);
Таблица Д.17. Значения перечисления SeekOrigin
Значение
Описание
Begin
Соответствует началу потока
Current
Соответствует текущей записи потока
End
Соответствует концу потока
Физическая запись данных в файл реализуется в момент закрытия потока методом Close или выталкивания записей из промежуточного буфера методом Flush. Во втором случае поток не закрывается и готов к продолжению операций.
При чтении строк из текстового файла нужно контролировать конец файла. Для этого переменная типа String в Delphi 2005 может принимать значение NIL, если из файла ничего не прочитано, то есть если файл исчерпан (см. показанный ранее пример). Другим способом контроля является обращение к методу StreamReader. Peek, который возвращает положительное число, если файл не исчерпан, или -1 — в противном случае. Таким образом, цикл чтения записей из текстового файла предельно упрощается:
while Reader.Peek <> -1 do
Writein(Reader.ReadLine);
Обработка двоичных данных
Обработка двоичных файлов во многом подобна обработке текстовых: сначала создается поток, затем — объекты Binarywriter или Binary Reader в зависимости от направления передачи данных (в файл или из файла).
Объект BinaryWrite имеет метод Write, с помощью которого данные передаются в файл. Метод Write имеет множество перегруженных вариантов, позволяющих записывать в файл любые данные (в том числе строки String, так что деление файлов на строковые и двоичные носит чисто условный характер).
Объект Binary Reader имеет метод Read, предназначенный для чтения из потока массива символов или байтов. Кроме того, он имеет многочисленные методы
ReadXXXX (ReadBoolean, ReadByte, ReadDouble, Readstring и т. д.) для чтения значений примитивных типов. Его метод Peekchar позволяет контролировать конец файла: подобно рассмотренному ранее методу StreamReader. Peek, он возвращает -1, если файл исчерпан.
Сериализация
Как уже говорилось в начале предыдущего раздела, .NET Framework поддерживает интересную технологию сохранения текущего состояния объекта на некотором носителе информации. Эта технология называется сериализацией объекта. Сериализованный объект может быть передан по сети на другой компьютер и там восстановлен в первоначальном состоянии — этот процесс называется десериализацией.
Техника сериализации
Особенностью сериализации является то, что ее можно применять только к классам, поддерживающим эту процедуру. Для этого класс должен объявляться с атрибутом [Serializable] или в его объявлении должно быть явное указание на то, что он исполняет интерфейс ISerializable. Например:
type
[Serializable]
Book 二 class(System.Object)
public
FName: String;
FAuthor: String;
FPublish: String;
FYear: Integer;
end;
Лишь относительно небольшое количество (менее 40) стандартных классов CTS реализуют интерфейс ISerializable. Это в основном классы, используемые как хранилища данных (DataSet, DataTable, TreeNode и некоторые другие). В интерфейсе ISerializable определен единственный метод GetObectData такого вида:
procedure GetObjectData(Info: Serializationinfo;
Context: Streamingcontext);
Параметр Info содержит данные, a Context — текущее состояние потока данных. На практике специальные классы, реализующие интерфейс ISerializable, создаются для обслуживания нестандартных типов данных. В большинстве случаев этого можно не делать — достаточно лишь вставить атрибут [Serializable] перед объявлением класса, как это сделано в предыдущем примере.
При сериализации среда CLR создает граф объекта и с помощью этого графа сохраняет объект вместе со связанными с ним объектами. Каждый связанный с ос-
новным объектом объект получает уникальный идентификатор. При десериализации может встретиться случай» когда объект ссылается на идентификатор еще не восстановленного объекта. В этом случае CLR корректирует порядок восстановления объектов.
Объявив тем или иным способом, что класс поддерживает сериализацию, мы должны выбрать формат представления его объекта. Технология .NET Framework предлагает для этой цели два формата: двоичный и SOAP (Simple Object Access Protocol — простой протокол доступа к объекту). В первом случае создается объект класса вinaryForma11er, принадлежащего пространству имен System. Runtime. Serialization. Formatters.Binary. Во втором — объект класса SoapFormatter (пространство имен System.Runtime.Serialization. Formatters. Soap).
ПРИМЕЧАНИЕ
Класс BinaryFormatter находится в сборке mscorlib.dll. Чтобы воспользоваться классом, достаточно его пространство имен поместить в предложение uses. Класс SoapFormatter включен в сборку System.Runtime.Serializatkm.FbrrnaU£rs.SOAP^ Чтобы воспользоваться клас- сомг перед вставкой имени его пространства имен в предложение uses следует добавить в проект ссылку, в которой описывается местонахождение библиотеки. Эта ссылка добавляется с помощью диалогового окна, открываемого командой Project > AddReference.
Пример
В этом разделе представлен простой пример, иллюстрирующий описанную технологию (проект Add_5\Rles\SerlalDemo.dpr):
proffram SerialDemo;
{$APPTYPE CONSOLE}
// Следующая строка вставлена в цроект с помощью диалогового
// окна, открываемого командой Project>AddReference.
// Она не «должна разрываться на части:
f %DelphiDotNetAsseniblyCompiler
• $ (SystemRoot) \mcrosoft .net \ framework
\vl. 1.4322 \ System. Rimtime. Serialization. ForTnatters. Soap. dll')
ueee
SysUtils,
System.IO,
System.Runtime•Serialization.Formatters.Soap;
type
[Serializable]
TBook = class(System.Object) // Класс для сериалязации
public
FName: String;
FAuthor: String;
FPublish: String;
FYear: Integer;
constructor Create(Name, Author, Publish: String; Year: Integer); end;
f TBook ,
TBooks = array[l. .3] of TBook;// Массив для трех о&ьехтов Вйок
constructor TBook.Create (Name, Author, Publish: String; Year : Integer); begin
inherited Create;
FName : = Name ;
FAuthor := Author;
FPublish := Publish;
FYear := Year;
end; var
Book: TBook;
Stream: Filestream;
Fmtr: SOAPFormatter;
Books: TBooks;
k: Integer;
begin
// Создаем зри книги и помещаем их в массив:
Book := TBook.Create(1C# и платформа .NET', *Троелсен Э.',
* Питер', 2005);
Books[1] := Book;
Book := TBook.Create(1 ASP.NET. Искусство содания web-сайтов1,
* Уолтер С.*, 'Диа-Софт*, 2002);
Books[2] := Book;
Book := TBook.Create('Грибной царь1, 'Поляков Ю.', 'РОСМЭН*, 2005);
Books[3] := Book;
// Создаем поток :
Stream := FileStream.Create('books.dat*, FileMode.Create#
FileAccess.Write);
// Создаем объект класса SaapForma11er;
Fmtr := SoapFormatter.Greate;
// Сериализацяя массива;
Fmtr.Serialize(Stream, Books);
Stream.Close;
H Создаем поток для десериализации:
Stream :- Filestream.Create('books.dat', Fi1eMode.Open, FileAccess.Read);
〃 Десериализация массива:
Books := Fmtr.Deserialize(Stream) as TBooks;
// Печать восстановленных объектов: for k := 1 to 3 do
begin
Writeln(* Автор: 1:15, Books[к].FAuthor);
Writeln('Название: 1:15, Books[к],FName);
Writeln('Изд-во: ':15, Books[k].FPublish);
Writeln(тГод: ':15, Books[k].FYear.ToString);
Writeln;
end;
Readln;
end.
При десериализации используется явное приведение получаемого массива объектов к типу Books:
Books i= Fmtr.Deserialize(Stream) as TBooks;
Если этого не сделать, компилятор сообщит о несовместимости типов TBooks и Object: метод Deserialize всегда возвращает данные как объекты класса Obj ect.
Ar-ZADO.NET, 57 ASP.NET, 455,468 BDE, 31 BDENET, 117 dbExpress.NET, 242 dbGo.NET, 211 IBX.NET, 268 ODBC, 31 SQL 515 URL, 360Ar-ZADO.NET, 57 ASP.NET, 455,468 BDE, 31 BDENET, 117 dbExpress.NET, 242 dbGo.NET, 211 IBX.NET, 268 ODBC, 31 SQL 515 URL, 360авторизация пользователя, 455агрегатные функции, 520 архитектурадвухзвенная, 20однозвенная, 20трехзвенная, 20аутентификацияWindows» 455на основе форм, 455по паспорту, 455пользователя, 455Ббаза данных нормализация, 25 определение, 20авторизация пользователя, 455агрегатные функции, 520 архитектурадвухзвенная, 20однозвенная, 20трехзвенная, 20аутентификацияWindows» 455на основе форм, 455по паспорту, 455пользователя, 455Ббаза данных нормализация, 25 определение, 20Ввеб-приложение, 358веб-сервер, 357модули расширения, 358обработка запроса, 361сетевое имя, 360веб*служба, 365, 436веб-форма, 362)369 визуализация данныхв BDE.NET, 185,197свойство DataBindings, 58внешний ключ, 484выборкаbBDE.NET, 174из связанных таблиц, 515простая, 514Ввеб-приложение, 358веб-сервер, 357модули расширения, 358обработка запроса, 361сетевое имя, 360веб*служба, 365, 436веб-форма, 362)369 визуализация данныхв BDE.NET, 185,197свойство DataBindings, 58внешний ключ, 484выборкаbBDE.NET, 174из связанных таблиц, 515простая, 514
Ar-Z
ADO.NET, 57 ASP.NET, 455,468 BDE, 31 BDENET, 117 dbExpress.NET, 242 dbGo.NET, 211 IBX.NET, 268 ODBC, 31 SQL 515 URL, 360
Ar-Z
ADO.NET, 57 ASP.NET, 455,468 BDE, 31 BDENET, 117 dbExpress.NET, 242 dbGo.NET, 211 IBX.NET, 268 ODBC, 31 SQL 515 URL, 360
авторизация пользователя, 455
агрегатные функции, 520 архитектура
двухзвенная, 20
однозвенная, 20
трехзвенная, 20
аутентификация
Windows» 455
на основе форм, 455
по паспорту, 455
пользователя, 455
Б
база данных нормализация, 25 определение, 20
авторизация пользователя, 455
агрегатные функции, 520 архитектура
двухзвенная, 20
однозвенная, 20
трехзвенная, 20
аутентификация
Windows» 455
на основе форм, 455
по паспорту, 455
пользователя, 455
Б
база данных нормализация, 25 определение, 20
В
веб-приложение, 358
веб-сервер, 357
модули расширения, 358
обработка запроса, 361
сетевое имя, 360
веб*служба, 365, 436
веб-форма, 362)369 визуализация данных
в BDE.NET, 185,197
свойство DataBindings, 58
внешний ключ, 484
выборка
bBDE.NET, 174
из связанных таблиц, 515
простая, 514
В
веб-приложение, 358
веб-сервер, 357
модули расширения, 358
обработка запроса, 361
сетевое имя, 360
веб*служба, 365, 436
веб-форма, 362)369 визуализация данных
в BDE.NET, 185,197
свойство DataBindings, 58
внешний ключ, 484
выборка
bBDE.NET, 174
из связанных таблиц, 515
простая, 514
Алфавитный указатель
база данных (продолжение') проектирование, 25 псевдоним» 44 реляционная, 23 сеанс связи, 139 система управления, 20 базовый объект, 222 баннер, 374 бизнес-правила, 54 блокировка таблиц, 165 браузер, 358
Г
генератор, 484,495
гиперссылка, 397, 528
графическая кнопка, 375
группировка 3anHceAt 520
зарезервированное слово (продолжение)
BOOLEAN, 523
BY, 517
CHAR, 523
CHARACTER, 523
CREATE, 523
д
данные
абстрактные, 122
двоично-десятичные, 121
отображение, 182
привязка, 410
двунаправленный курсор, 242, 259
десериализация, 580
документ
правильный, 544
состоятельный, 544
домен, 496
драйвер
ODBC, 213
языковый, 35, 39
DATE, 523 DELETE, 525 DROP, 523 FLOAT, 523 FROM, 515,525 GROUP, 521 IN, 519 INDEX, 523
INSERT, 524 INT, 523 INTEGER, 523 INTO, 524 KEY, 523 LIKE, 518 NOT, 517, 523 NULL, 523
3
закладка
в BDE.NET, 159
BdbGoNET, 237
запись
визуализация. 201
вставка, 524
выборка, 174
группировка, 520
поиск, 159, 173
программный доступ, 155 редактирование, 524 сортировка, 517
текущая, 157
удаление, 173, 524
фильтрация, 163
запрос
выборки, 514
изменяемый, 182
параметрический» 71,180 создание» 514
зарезервированное слово AND, 517
BLOB, 523
ON, 523
OR, 517
ORDER, 517 PRIMARY, 523
SELECT, 515
SET, 525
TABLE, 523
UNIQUE, 523 UPDATE, 525
VALUES, 524
WHERE, 516
знак равенства, 529
значащий тип данных, 554
И
изоляция транзакций, 146 индекс, 24
вторичный, 33 добавление, 171 смена, 171 создание, 523 составной, 34, 172 текущий, 171 удаление, 171, 523
интерфейс
IDataReader, 73
IDbConunand, 69
IDbConnectionr 66
IDbDataAdapter, 75
ISQLMetadata, 68 интранет, 355 источник данных
в ASP.NET, 412,415
bBDENET, 117, 185
в dbGo.NET. 212
класс {продолжение) TCustomADODataSet методы, 236 события, 238
TDatabase методы» 146 свойства, 145
TDataSource свойства, 185 события, 187
TDBCheckBox, 203 TDBComboBox, 203
К
календарь, 386 каскадные изменения, 166 класс
ArrayList, 566
BdpCommand, 69
Binding, 110
Connection, 66
DataAdapter, 75
DataColumn, 86, 87
DataGrid, 99 методы, 104 свойства, 99
DataRow, 95 методы, 97 свойства, 95
DataSet, 57, 80, 407 методы, 80 свойства, 80
DataTable, 83 методы, 83 свойства, 83
HashTable, 570
HttpServerUtility, 470 Page, 369,468 Queue, 565 Stack, 562 StringBuilder» 579 TADOCommand, 232 TADOConnection, 217 TADODataSet, 239 TBlobField методы, 138 свойства, 137
TColumn, 189
TDBCtrIGrid, 206
методы, 208
свойства, 207
события, 209
TDBDataSet, 149
методы, 152
свойства, 150
события, 154, 166
TDBEdit, 202
TDBGrid
методы, 190
свойства, 187
события, 191
TDBGridColumns, 189
TDBListBox, 203
TDBLookupComboBox, 203
TDBLookupListBox, 203
TDBMemo, 205
TDBNavigator, 209
TDBRadioGroup, 203
TDBRichEdit, 205
TDBText, 202
TField, 118
методы, 124
свойства, 118
события, 124
TIBBackupRestoreService, 504
TIBBase
методы, 272
свойства, 271
события, 272
TIBControlAndQueryService, 504
TIBControlService, 503
TIBCustomService, 503
TMemoField, 134
TParam, 178
класс (продолжение) TParamsметоды, 177 свойства, 177TQueryметоды, 178 свойства, 176TSession, 139 TSQLQuery, 257 TSQLTable. 257 TSQLTimeStamp, 137 TStringField, 134TTableметоды, 168 свойства, 167прокси, 443 разъединенный, 58 соединенный, 58 клиент, 242 клиентское место, 22 ключвнешний, 484 первичный, 23,484 кнопкаграфическая, 375 обычная, 375 с гиперссылкой, 375 коллекция, 559объектов, 75 ограничений, 83 параметров запроса, 69 полей таблицы, 83 таблиц, 59 комментарий, 520, 532 компонентCalcController, 353CalcText, 352CalcTotal, 352DataText, 328HTML, 362TADOConnection, 224TADOQuery, 241 TADOTable, 240 TADQStoredProc, 300 TDatabase, 47 TDataSource» 48TDQLClientDataSet, 259 TIBBackupService, 506класс (продолжение) TParamsметоды, 177 свойства, 177TQueryметоды, 178 свойства, 176TSession, 139 TSQLQuery, 257 TSQLTable. 257 TSQLTimeStamp, 137 TStringField, 134TTableметоды, 168 свойства, 167прокси, 443 разъединенный, 58 соединенный, 58 клиент, 242 клиентское место, 22 ключвнешний, 484 первичный, 23,484 кнопкаграфическая, 375 обычная, 375 с гиперссылкой, 375 коллекция, 559объектов, 75 ограничений, 83 параметров запроса, 69 полей таблицы, 83 таблиц, 59 комментарий, 520, 532 компонентCalcController, 353CalcText, 352CalcTotal, 352DataText, 328HTML, 362TADOConnection, 224TADOQuery, 241 TADOTable, 240 TADQStoredProc, 300 TDatabase, 47 TDataSource» 48TDQLClientDataSet, 259 TIBBackupService, 506компонент (продолжение) TIBConhgService, 505 TIBDatabase
класс (продолжение) TParams
методы, 177 свойства, 177
TQuery
методы, 178 свойства, 176
TSession, 139 TSQLQuery, 257 TSQLTable. 257 TSQLTimeStamp, 137 TStringField, 134
TTable
методы, 168 свойства, 167
прокси, 443 разъединенный, 58 соединенный, 58 клиент, 242 клиентское место, 22 ключ
внешний, 484 первичный, 23,484 кнопка
графическая, 375 обычная, 375 с гиперссылкой, 375 коллекция, 559
объектов, 75 ограничений, 83 параметров запроса, 69 полей таблицы, 83 таблиц, 59 комментарий, 520, 532 компонент
CalcController, 353
CalcText, 352
CalcTotal, 352
DataText, 328
HTML, 362
TADOConnection, 224
TADOQuery, 241 TADOTable, 240 TADQStoredProc, 300 TDatabase, 47 TDataSource» 48
TDQLClientDataSet, 259 TIBBackupService, 506
класс (продолжение) TParams
методы, 177 свойства, 177
TQuery
методы, 178 свойства, 176
TSession, 139 TSQLQuery, 257 TSQLTable. 257 TSQLTimeStamp, 137 TStringField, 134
TTable
методы, 168 свойства, 167
прокси, 443 разъединенный, 58 соединенный, 58 клиент, 242 клиентское место, 22 ключ
внешний, 484 первичный, 23,484 кнопка
графическая, 375 обычная, 375 с гиперссылкой, 375 коллекция, 559
объектов, 75 ограничений, 83 параметров запроса, 69 полей таблицы, 83 таблиц, 59 комментарий, 520, 532 компонент
CalcController, 353
CalcText, 352
CalcTotal, 352
DataText, 328
HTML, 362
TADOConnection, 224
TADOQuery, 241 TADOTable, 240 TADQStoredProc, 300 TDatabase, 47 TDataSource» 48
TDQLClientDataSet, 259 TIBBackupService, 506
методы, 274
свойства, 272
события, 275
TIBDatabaselnfo, 287
TIBDataSet, 281
методы, 284
свойства» 282
события, 285
TIBInstall, 511
TIBLicensingService, 510
TIBLogServic% 509
TIBQuery, 281
TIBRestoreService, 507
TIBSecurityService, 509
TIBServerProperties, 510
TIBSQL, 285
методы, 286
свойства* 285
события, 287
TIBSQLMonitor, 289
TIBStatisticalService, 508
TIBStoredProc, 301
TIBTable, 280
TIBTransaction
методы, 277
свойства, 276
TIBUnlnstall, 513
TQuery, 175
TRvCustomConnection, 339
TRvDataSetConnection, 336
TRvQueryConnection, 336
TRvTableConnection, 336
TSession
использование, 141
методы, 140
свойства, 139
события, Ml
TSimpleDataSet
методы, 261
свойства^ 259
события, 267
TSQLConnection, 248
методы, 250
свойства, 248
события, 254
компонент (продолжение) TSQLDataSet, 254 методы, 256 свойства, 254 события, 257
TSQLMonitor, 257 методы, 258 свойства, 258 события, 259
TSQLStoredProc, 301 TStoredProc, 297 TTable, 48 адаптер, 57 визуализации, 57, 105 связи, 57, 117 списочный, 203 управления сервером, 362 корневой элемент, 542 курсор
двунаправленный, 242 одаонаправленный, 242
кэширование, 235
м
набор данных (продолжение) навигация, 157 наполнение, 65 настройка, 63 открытие, 155 редактирование, 156 фильтрация, 163
О
обратная сортировка, 184 объект
Command, 223
Connection, 222
Error, 223
Field, 223
Page, 468
Parameter, 223
Property, 223
Recordset, 223
базовый, 222
данных, 335, 336
Data Lookup Security Control, 341
маска EditMask, 123 массив, 554 метаданные, 289 метод
Compute, 86
ExecuteNonQuery, 70
ExecuteReader, 73
ExecuteScalar, 72
Fffl, 77
Format, 73
GET, 359
HEAD, 359 POST, 359.440 PUT, 359
Update, 57, 79
Database Connection, 337
Direct Data View, 336
Driver Data View, 337
Simple Security Control, 341
поле, 50,125
стилевой, 102
столбец, 52,191
обычная кнопка, 375
ограничение, 484, 497
однонаправленный курсор, 242
оператор
DO, 558
EXCEPTION, 296
EXECUTE PROCEDURE, 295
EXIT, 295
FOR, 294,558
H
набор данных, 48, 75
в ADO.NET, 57t 80, 83, 407
в BDE.NET, 117, 149
в dbGo.NET, 234
закрытие, 155
курсор, 157
IF, 294
SELECT, 294
SUSPEND, 294
WHILE, 295,558 отчет библиотека, 333 главный—детальный, 344 группирующий, 349
отчет (продолжение)
защита, 341
машина генерации, 323
печать, 334
проект, 323
простой, 342
с агрегатными функциями, 351
список» 334
страница, 334
умалчиваемый, 334
экспорт, 353
пакет сообщения, 359 первичный ключ, 484 переключатель, 379 перехват сообщений, 257 подстановочное поле, 127 подтип, 494
поиск записей
в таблице, 173 неточный, 174 точный, 173 поле
BLOB, 137,485,494 вещественное, 136 вычисляемое, 51
в ADO.NET, 88
в BDE.NET, 128 даты и времени, 137,491 конструктор, 51 логическое, 136 массив, 490 мемо, 134 обращение к значению
bADO.NET, 112
bBDE.NET, 129
объект, 125 подстановочное, 50, 51, 434
в ADO.NET, 91
в BDE.NET, 127 проверка значения, 132 пустое, 129 редактор, 50 совместимость типов, 130, 496 строковое, 134,492 текстовое представление, 133
поле (продолжение) фиксированно-десятичное, 491 целочисленное, 134
пользователь
авторизация, 455
аутентификация, 455
роль, 455
учетная запись, 455
пользовательская функция, 485
пользовательский элемент
управления, 447
право доступа к данным, 220
представление, 485
нсобновляемое, 307
обновляемое, 307
определение! 306
удаление, 307
привязка, 106
примитивный тип данных, 554
провайдер
BDP, 61
OLE DB, 212, 219
выбор, 219
данных, 60
настройка, 220
состояний, 480
проверка данных
клиентская, 398
серверная, 398
прокси-класс, 443
протокол
HTTP, 358
SOAP, 440
процедура
кодирование, 293
объявление, 304
параметры» 291
создание, 291
псевдоним, 44, 520
локальный, 47
создание, 44, 45
Р
редактор
полей в BDE.NET, 125
столбцов, 191, 192
роль пользователя, 455
свойство
Connectionstring, 67
DataBindings, 105
связь
настройка, 214
реляционная, 64
с объектом ADO, 216
таблиц, 216
сеанс
как объект, 480
связи с базой данных, 139
сервер
InterBase, 248, 484,488
MS SQL Server, 225
Oracle, 248
базы данных, 21,22
приложений, 21
серверный элемент управления, 372 сериализация, 580, 589
сетка, 187
символ
Unicode, 30
национального алфавита, 30
словообразующий, 402
специальный, 527
условный» 35
сортировка
записей, 517
обратная, 184
составной индекс, 172
состояние вида, 371,478
список, 383
значений столбца, 194
полей таблицы, 50
типов, 32
ссылочная целостность, 38
ссылочный тип данных, 554 столбец
Массив, 490
объект, 191
пустой, 194
радактор, 52
сетки, 52
список значений, 194
страница
активная серверная, 361 глобальная, 334
отчета, 334
строка связи
структура, 217
формирование, 217
СУБД
архитектура, 20
заказная, 20
клиент-серверная, 21
локальная( 21 масштабирование, 22 промышленная, 20, 25 распределенная, 21 сетевая» 21
специализхфованная, 20
специального назначения, 20 типы, 20
универсальная, 20 файл'серверная, 21
сценарий, 368, 373, 540
таблица, 535
блокировка, 165
виртуальная, 306
главная, 23
детальная, 23
дочерняя, 23
запись, 23
индекс, 523
подстановки, 36
поиск записей, 173
поле, 23
псевдоним^ 520
родительская, 23
связи, 23
создание, 523
столбец, 23
строка, 23
удаление, 173,523
эксклюзивный доступ, 173
тег, 526
к 532
В, 529
BODY, 527
тег {продолжение)BR, 527CAPTION, 536CODE, 529DFN, 529DIV, 539EM, 529FONT, 529FORM, 533FRAME, 538FRAMESET, 538HTML, 526It 529IFRAME, 539IMG 531INPUT, 533LI, 529OL, 529P, 527STRONG, 529TABLE, 535TD, 535TR, 535TT, 529U, 529UL, 529A, 528 технологияADO.NET, 57ASP.NET, 372, 455, 468BDE.NET, 117dbExpress.NET, 242dbGo.NET, 211IBX, 268OLE DB, 212 тип данных значащий, 554 примитивный, 554 ссылочный, 554 транзакция, 47 изоляция, 55 eADONET, 68 в BDE.NET, 146 в dbGo.NET, 224определение, 55старт, 68, 112тег {продолжение)BR, 527CAPTION, 536CODE, 529DFN, 529DIV, 539EM, 529FONT, 529FORM, 533FRAME, 538FRAMESET, 538HTML, 526It 529IFRAME, 539IMG 531INPUT, 533LI, 529OL, 529P, 527STRONG, 529TABLE, 535TD, 535TR, 535TT, 529U, 529UL, 529A, 528 технологияADO.NET, 57ASP.NET, 372, 455, 468BDE.NET, 117dbExpress.NET, 242dbGo.NET, 211IBX, 268OLE DB, 212 тип данных значащий, 554 примитивный, 554 ссылочный, 554 транзакция, 47 изоляция, 55 eADONET, 68 в BDE.NET, 146 в dbGo.NET, 224определение, 55старт, 68, 112транзакция (продолжение)
тег {продолжение)
BR, 527
CAPTION, 536
CODE, 529
DFN, 529
DIV, 539
EM, 529
FONT, 529
FORM, 533
FRAME, 538
FRAMESET, 538
HTML, 526
It 529
IFRAME, 539
IMG 531
INPUT, 533
LI, 529
OL, 529
P, 527
STRONG, 529
TABLE, 535
TD, 535
TR, 535
TT, 529
U, 529
UL, 529
A, 528 технология
ADO.NET, 57
ASP.NET, 372, 455, 468
BDE.NET, 117
dbExpress.NET, 242
dbGo.NET, 211
IBX, 268
OLE DB, 212 тип данных значащий, 554 примитивный, 554 ссылочный, 554 транзакция, 47 изоляция, 55 eADONET, 68 в BDE.NET, 146 в dbGo.NET, 224
определение, 55
старт, 68, 112
тег {продолжение)
BR, 527
CAPTION, 536
CODE, 529
DFN, 529
DIV, 539
EM, 529
FONT, 529
FORM, 533
FRAME, 538
FRAMESET, 538
HTML, 526
It 529
IFRAME, 539
IMG 531
INPUT, 533
LI, 529
OL, 529
P, 527
STRONG, 529
TABLE, 535
TD, 535
TR, 535
TT, 529
U, 529
UL, 529
A, 528 технология
ADO.NET, 57
ASP.NET, 372, 455, 468
BDE.NET, 117
dbExpress.NET, 242
dbGo.NET, 211
IBX, 268
OLE DB, 212 тип данных значащий, 554 примитивный, 554 ссылочный, 554 транзакция, 47 изоляция, 55 eADONET, 68 в BDE.NET, 146 в dbGo.NET, 224
определение, 55
старт, 68, 112
управление, 55
в BDE.NET, 146
в dbExpress.NET, 252
в dbGo.NET, 224» 225
bIBX.NET, 278
триггер, 54
изменение, 306
кодирование, 293
объявление, 304
определение, 484
создание, 296, 302
удаление, 306
У
уведомление» 485
утилита DataExplorer, 61
учетная запись пользователя, 455
Ф
файл cookie, 457
файл-сервер, 21
фильтрация записей, 163
флажок, 381
форма
для визуализации данных, 201
для редактирования записей, 104
нормальная, 25
фрейм
определение, 537
плавающий, 538
положение на странице, 539
функция
alert, 535
агрегатная, 90, 520
пользовательская, 485
X
хеш-код, 464, 570
хранимая процедура, 485
изменение, 306
кодирование, 293
объявление, 304
параметры, 291
создание, 291
удаление, 306
Ш
шаблон преобразования, 543
э
эксклюзивный доступ к тафшце* 173
элемент, 542
AdRotator, 374
BDWebDataSource, 428
Calendar, 386
CheckBox» 381
CheckBoxList, 381
CompareValidator, 403
Custx>mValidator, 405
DataList, 415
DBWebGrid, 432
DBWebNavigator, 431
DropDownList, 383
HyperLink, 397
Image, 384
Label, 382
ListBox, 383
Literal, 389
Panel» 392
PlaceHolder, 396
RadioButton, 379
элемент (продолжение) RadioButtonList, 379 RangeValidator, 401 ReguIarExpressionValidator, 402 Repeater, 412
RequiredFieldValidator, 399 Table, 393
TextBox, 382
ValidationSunnary, 404 XML, 397 корневой, 542 пустой, 545 управления
пользовательский, 447 серверный, 372
язык
DDL, 232
HTML, 526
SGML, 541
Visual Basic .NET, 553
WSDL, 440
XML, 540
XSL 543
Валерий Васильевич ФароновDelphi 2005. Разработка придсмсенийдля баз данных и Интернета
Заведующий редакцией Рукомдаггежь про^пЪТ^дожник Иллюстрации、 Корректоры ВерсткаЗаведующий редакцией Рукомдаггежь про^пЪТ^дожник Иллюстрации、 Корректоры Верстка4 IQMM^pe 4 АдаменкоЛ. Жданов ЛАдуевскал Л Регионом " ?5倂第4场71弊呐“0 ” Р. Гршштов4 IQMM^pe 4 АдаменкоЛ. Жданов ЛАдуевскал Л Регионом " ?5倂第4场71弊呐“0 ” Р. Гршштов
Заведующий редакцией Рукомдаггежь про^пЪ
Т^дожник Иллюстрации、 Корректоры Верстка
Заведующий редакцией Рукомдаггежь про^пЪ
Т^дожник Иллюстрации、 Корректоры Верстка
4 IQMM^pe 4 Адаменко
Л. Жданов ЛАдуевскал Л Регионом " ?5倂第4场71弊呐“0 ” Р. Гршштов
4 IQMM^pe 4 Адаменко
Л. Жданов ЛАдуевскал Л Регионом " ?5倂第4场71弊呐“0 ” Р. Гршштов
ЛнцеижИДМ 05784 от O7.O9.OL
Подпмсаяо к печати 29.1 LOS. Формат 70x100/16. Усл. п. л. 49,02, Тираж 2500. Заказ 449ООО 41итф Х^яш%*,!94044, CaHio»rieTeptyprt Б. СампсониввскиЙ прм 29&g*E弊 ЛИ唔 Г ofeMB晔如哪階Хсифжйтрр прадукции OK 005-93, том 2; 95 3005 — mnepirrype учебная.
6唯唸咖 в^^нх диапоонтявов в ОАО m血в&ка^ Era»
1$Ьо嘴&шн<>11трбург, Измайловский лр” 砂;,
КЛУБКЛУБ
КЛУБ
КЛУБ
В1997 году по инициативе генерального директора Издательского дома «Питер» Валерия Степанова и при поддержке деловых кругов города в Санкт-Петербурге был основан «Книжный клуб Профессионал». Он собрал под флагом клуба профессионалов своего дела, которых объединяет постоянная тяга к знаниям и любовь к книгам. Членами клуба являются лучшие студенты и известные практики из разных сфер деятельности, которые хотят стать или уже стали профессионалами в той или инои области.
Как и все развивающиеся проекты, с течением времени книжный клуб вырос в «Клуб Профессионал». Идею клуба сегодня формируют три основные «клубные» функции;
неформальное общение и совместный досуг интересных людей;
участие в подготовке специалистов высокого класса (семинары, пакеты книг по специальной литературе);
формирование и высказывание мнений современного профессионала (при встречах и на страницах журнала).
КАК ВСТУПИТЬ В КЛУБ?
Для вступления в «Клуб Профессионал» вам необходимо:
ознакомиться с правилами вступления в «Ю|уб Профессионал» на страницах журнала или на сайте www.piter.com;
выразить свое желание вступить в «Клуб Профессионал»
по электронной почте postbook@piter.com или по тел. (812) 103-73-74;
заказать книги на сумму не менее 500 рублей в течение любого времени или приобрести комплект «Библиотека профессионала».
«БИБЛИОТЕКА ПРОФЕССИОНАЛА»
Мы предлагаем вам получить все необходимые знания, подписавшись на «Библиотеку профессионала». Она для тех, кто экономит не только время, но и деньги. Покупая комплект - книжную полку «Библиотека профессионала», вы получаете:
скидку 15% от розничной цены издания, без учета почтовых расходов;
при покупке двух или более комплектов - дополнительную скидку 3%;
членство в «Клубе Профессионал»;
подарок - журнал «КЬуб Профессионал».
Закажите бесплатный журнал «Клуб Профессионал».Закажите бесплатный журнал «Клуб Профессионал».пзалтепьскпА дом^ПКТЕР^7k WWW.PITER.COMпзалтепьскпА дом^ПКТЕР^7k WWW.PITER.COM
Закажите бесплатный журнал «Клуб Профессионал».
Закажите бесплатный журнал «Клуб Профессионал».
пзалтепьскпА дом^ПКТЕР^7k WWW.PITER.COM
пзалтепьскпА дом^ПКТЕР^7k WWW.PITER.COM
銀лмер*
Нет времени
ходить по магОйНам?
wwwi.piter.com
Здесь вы найдете:
Все книги издательства сразуНовые книги — в момент выхода из типографииИнформацию о книге — отзывы, рецензии, отрывкиСтарые книги — в библиотеке и на CD
И надднец, вы нигде но купитен^ши книги деига^Мв!
КНИГА-ПОЧТОЙКНИГА-ПОЧТОЙЗАКАЗАТЬ КНИГИ ИЩГЕЛЬСКОГО ДОМА «ПИТЕР» МОЖНО ЛЮБЫМ УДОБНЫМ ДЛЯ ВАС СПОСОБОМ:
КНИГА-ПОЧТОЙ
КНИГА-ПОЧТОЙ
по телефону: (812) 103-73-74;
по злеюронному адресу: postbook@piter.com;
на нашем сервере: www.piter.com;
по почте: 197198, Санкт-Петербург, а/я 619, ЗАО «Питер Пост».
ВЫ МОЖЕТЕ ВЫБРАТЬ ОДИН ИЗ ДВУХ СПОСОБОВ ДОСТАВКИ И ОПЛМЫ ИЗДАНИЙ:
® Наложенным платежом с оплатой заказа при получении посылки на ближайшем почтовом отдалении. Цены 鹽 издания приведены ориентировочно и включают в себя стоимость пересылки по почте (но без учета авиатарифа). Книги будут высланы нашей службой «Книга-почтой» в течение двух недель после получения заказа или выхода книги из печати.
會 Оплата наличными при к^зьерской доставке (для жителей Москвы и Санкт-Петербурга). Мьер доставит заказ по указанному адресу в удобное для вас время в течение трех дней.
ПРИ ОФОРМЛЕНИИ ЗАКАЗА УКАЖИТЕ:
фамилию, имя, отчество, телефон, факс, e-mail;
почтовый индекс, регион, район, населенный пункт, улицу, дом, корпус, квартиру;
название книги, автора, код, количество заказываемых экземпляров.
пзалтепьскил домпзалтепьскил домВы можете заказать бесплатный журнал .«Клуб Профессионал»
пзалтепьскил дом
пзалтепьскил дом