Книга
Книга
Анатолий Постолит
Visual
Studio .NET: Разработка приложений баз данных
Санкт-Петербург«БХВ-Петербург»2003
УДК 6S1.3.06
ББК 32.973.26
П63
Постолит А. В.
П63Visual Studio .NET: разработка приложений баз данных. —
СПб.: БХВ-Петербург, 2003. — 544 с.: ил.
ISBN 5-94157-309-Х
Книга посвящена технологии Microsoft .NET и базовому инструментальному средству этой технологии Visual Studio .NET. Разъясняется сущность новой модели доступа к данным ADO.NET, упрощающей создание как традиционных Windows- приложений, так и распределенных систем, работающих в сети Интернет, Представлены материалы, необходимые для практического программирования, пройдены все этапы создания приложений от формирования пустой формы до установки конечного продукта у клиента. Рассмотрены особенности базовых объектов доступа к данным и элементов управления. Основное внимание уделено взаимодействию различных типов приложений с базами данных. Все ситуации разбираются на конкретных примерах, реализованных на двух языках программирования: Visual Basic и С#. Книга может быть использована как лабораторный практикум для студентов вузов и слушателей компьютерных курсов при изучении практических приемов программирования в среде Visual Studio .NET.
Для программистов
УДК 681.3.06
ББК 32.973.26
Группа подготовки издания:
Главный редакторЗам. главного редактораЗав. редакциейРедакторКомпьютерная версткаКорректорОформление серииДизайн обложкиЗав. производствомГлавный редакторЗам. главного редактораЗав. редакциейРедакторКомпьютерная версткаКорректорОформление серииДизайн обложкиЗав. производствомЕкатерина Кондукова Анатолий АдаменкоГригорий ДобинДмитрий ЛещевТатьяна ВалерьяноваЕвгений КамскийVia DesignИгоря ЦырульниковаНиколай ТверскихЕкатерина Кондукова Анатолий АдаменкоГригорий ДобинДмитрий ЛещевТатьяна ВалерьяноваЕвгений КамскийVia DesignИгоря ЦырульниковаНиколай Тверских
Главный редактор
Зам. главного редактора
Зав. редакцией
Редактор
Компьютерная верстка
Корректор
Оформление серии
Дизайн обложки
Зав. производством
Главный редактор
Зам. главного редактора
Зав. редакцией
Редактор
Компьютерная верстка
Корректор
Оформление серии
Дизайн обложки
Зав. производством
Екатерина Кондукова Анатолий Адаменко
Григорий Добин
Дмитрий Лещев
Татьяна Валерьянова
Евгений Камский
Via Design
Игоря Цырульникова
Николай Тверских
Екатерина Кондукова Анатолий Адаменко
Григорий Добин
Дмитрий Лещев
Татьяна Валерьянова
Евгений Камский
Via Design
Игоря Цырульникова
Николай Тверских
Лицензии ИД № 02429 от 24.07.00. Подписано в печать 25.04.03.
Формат 70х1001/16. Печать офсетная. Усл. печ. л. 43,86.
Тираж 3000 экз. Заказ № 873"БХВ-Петербург", 198005, Санкт-Петербург, Измайловский пр., 29.
Гигиеническое заключение на продукцию, товар I* 77.99.02.Э53.Д.001537.03.02от 13.03.2002 г. выдано Департаментом ГСЭН Минздрава России.
Отпечатано с готовых диапозитивовв Академической типографии "Наука" РАН19Э034, Санкт-Петербург, 9 линия, 12.
ISBN 5-94157-309-ХISBN 5-94157-309-ХО Постолит А. В., 2003
ISBN 5-94157-309-Х
ISBN 5-94157-309-Х
О Оформление, издательство "БХВ-Петербург", 2003
Содержание
Об авторе10
Введение11
Глава 1. ADO.NET как базовый объект доступа к базам данных14
Структура компонента доступа к данным ADO.NET14
.1Л. Работа в отрыве от источника данных15
и .2. Взаимодействие с базой данных через команды17
• 1 .3. Взаимодействие с базой данных через объект DataSet18
.4. Независимость набора данных DataSet от источника данных20
.5. Обмен данными в формате XML21
.6. Схемы, определяющие структуру данных22
Сравнение ADO.NET и ADO22
Представление данных в памяти22
Навигация по данным и курсоры23
Минимизация открытых соединений,24
Разделение данных между приложениями24
Соединение с источником данных (объект Connection)25
Строка соединения25
Открытие и закрытие соединения26
Пул соединений26
Транзакции27
Конфигурирование свойств Connection27
Объект Connection и безопасность.27
Создание объекта Connection в режиме дизайнера с помощью
Server Explorer28
Инструменты Visual Studio для создания объектов Connection29
Создание объекта Connection в ADO.NET29
Адаптер данных (объект DataAdapter)32
Адаптеры данных и связанные таблицы33
Адаптеры данных и объекты Command34
Чтение и обновление данных с использованием объекта DataAdapter.36
Параметры команд объекта DataAdapter37
Свойство TableMappings объекта DataAdapter44
Создание объекта DataAdapter.48
Конфигурирование параметров объекта DataAdapter58
Связывание колонок таблиц источника данных и объекта DataSet через адаптер данных61
Предварительный просмотр данных, полученных объектом DataAdapter...65
Глава 2. Наборы данных DataSet 67
Отсоединенный набор данных67
Объект DataSet, схемы и XML68
Типизированные и нетипизированные объекты DataSet69
Чувствительность к регистру в DataSet71
Заполнение наборов данных72
Указатель текущей записи и перемещение по набору данных72
.6. Связанные таблицы и объект DataRelation73
.7. Ограничения в DataSet74
.8. Обновление DataSet и базы данных75
.9. Инструменты Visual Studio для создания объектов DataSet.75
Создание вычисляемых колонок объекта DataSet81
Добавление таблиц в сформированный объект DataSetS3
Добавление существующего типизированного объекта DataSet к форме или компоненту84
Добавление объектов DataSet без контроля типов данных к форме или компоненту87
Способы фильтрации и сортировки данных в DataSet96
Фильтрация и сортировки данных в DataSet с помощью объекта DataView.. 100
Фильтрация и сортировка таблиц данных в DataSet.104
Доступ к записям в объекте DataView106
Работа с коллекцией DataView через объект DataView Manager110
Реляционные отношения в DataSet111
Обновление набора данных в Visual Studio .NET118
Введение в обновление набора данных118
Поддержание информации об изменениях в записях таблиц набора данных 122
Проверка правильности данных127
Модификация, вставка и удаление записей в наборе данных128
События при обновлении данных132
Приостановка действия ограничений при изменении данных133
Слияние наборов данных135
Завершение изменений в наборе данных136
Передача изменений набора данных в источник данных137
Обновление баз данных из наборов данных137
Обновление связанных таблицI4i
Регенерация набора данных144
Контроль параллелизма145
Обработка ошибок модернизации источника данных145
Глава 3. Прямой доступ к базе данных и стратегии доступа к данным148
Прямой доступ к базе данных148
Общие сведения об объекте DataCommand149
Работа объектов DataCommand150
Использование DataCommand адаптером данных151
Использование объекта DataCommand152
Выполнение команд, которые возвращают наборы данных158
Выполнение обновления или модификации базы данных
с использованием DataCommand162
Задание команды Data Command, возвращающей одно значение166
Стратегии доступа к данным167
Работа с данными через объект DataSet168
Непосредственная работа с элементами базы данных169
Рекомендации по организации доступа к данным из приложений170
Глава 4. Построение Windows-приложений с доступом к данным через ADO.NET173
Создание Windows-приложения173
Windows-форма как основа интерфейса176
Доступ к данным в Windows-формах с использованием
элемента управления DataGrid177
Создание проекта и формы178
Создание набора данных DataSet179
Добавление элемента управления DataGrid для отображения данных186
Заполнение элемента управления DataGrid данными187
Обновление информации в базе данных189
Доступ к данным в Windows-формах с использованием текстовых полей ... 191
Связывание элементов TextBox с набором данных193
Отображение номера текущей записи196
Выборка и сортировка данных через запросы с параметрами198
Создание проекта и Windows-формы199
Создание и конфигурирование объектов DataConnection и DataAdapter 200
Создание набора данных203
Добавление элементов отображения данных204
Добавление кода для заполнения набора данных205
Связывание текстовых полей с набором данных207
Добавление навигации по записям208
Отображение номера текущей записи209
Тестирование работы приложения211
Работа со связанными таблицами в Windows-формах213
Создание проекта и Windows-формы214
Конфигурирование Data Connection и DataAdapter215
Создание набора данных DataSet217
Создание реляционных связей между таблицами набора данных218
Добавление элементов отображения данных220
Заполнение набора данных223
Тестирование приложения224
Представление связанных таблиц в элементе управления DataGrid225
Создание проекта и Windows-формы226
Конфигурирование объектов Data Connection и DataAdapter226
Добавление элементов управления228
Заполнение набора данных и создание реляционных связей229
Тестирование приложения231
Добавление, удаление и обновление записей в Windows-формах234
Создание проекта и формы235
Создание и конфигурирование элементов доступа к данным235
Формирование программного кода237
Глава 5. Построение ASP-приложений с доступом к данным через ADO .NET 243
Создание проекта и формы243
Структура Web-формы245
Добавление элементов управления и текста246
Создание обработчика события252
Построение Web-приложения и запуск Web-формы253
Работа с данными в Web-формах254
Создание проекта и формы255
Создание и конфигурирование набора данных255
Добавление объекта DataGrid для отображения данных259
Заполнение набора данных и отображение информации в DataGrid.261
Тестирования приложения262
Работа с данными, доступными только для чтения262
Создание проекта и формы263
Добавление компонент доступа к данным264
Добавление элементов отображения данных267
Добавление программного кода для выборки и отображения данных 269
Тестирование приложения270
Редактирование информации на уровне источника данных из Web-форм ... 271
Создание проекта и формы272
Добавление компонент для доступа к данным273
Добавление элементов управления278
Добавление программного кода для отображения и обновления данных279
Тестирование приложения285
Создание Web-приложения с доступом к данным
через компонент пользователя286
Создание Web-формы286
Создание и конфигурирование элементов доступа к данным288
Создание набора данных,290
Связывание объекта DataGrid с набором данных291
Фильтрация данных в Web-форме299
Создание объекта с бизнес-логикой304
Использование объекта с бизнес-логикой306
Глава 6. Дополнительные возможности ASP-приложений309
Проверка корректности вводимых данных на Web-формах309
Создание базовой формы310
Добавление элементов ввода данных311
Добавление контролей для проверки правильности данных312
Проверка заполнения обязательных полей313
Проверка формата текста314
Проверка соответствия паролей315
Отображение ошибок при проверке правильности данных316
Тестирование приложения317
Использование серверного элемента управления DataGrid
для просмотра и редактирования данных319
Создание проекта и формы320
Создание и конфигурирование набора данных320
Добавление элемента управления DataGrid для отображения данных324
Заполнение набора данных и отображение информации в DataGrid325
Добавление возможности редактирования данных327
Предварительная проверка работы созданных элементов331
Редактирование DataSet обновление базы данных 332
Тестирование приложения338
Усовершенствование примера339
Кэширование набора данных342
Создание постраничного доступа к данным с использованием DataGrid 344
Создание проекта и формы345
Добавление компонентов доступа к данным346
Добавление элемента управления DataGrid...348
Добавление программного кода для выборки и отображения данных 350
Тестирование приложения357
Добавление, удаление и обновление записей в Web-формах357
Создание проекта и формы358
Создание и конфигурирование элементов доступа к данным359
Формирование программного кода361
Глава 7. Основные понятия о Web-сервисах370
Структура и назначение Web-сервисов370
Создание простейшего Web-сервиса371
Создание проекта XML Web Service371
Формирование программного кода Web-сервиса372
Тестирование Web-сервиса374
Отладка Web-сервиса376
Развертывание Web-сервиса377
Доступ к Web-сервису из клиентского приложения381
Создание приложения клиента Web-сервиса381
Добавление ссылки на Web-сервис383
Доступ к Web-сервису из приложения клиента384
Использование общедоступных Web-сервисов через сеть Интернет385
Глава 8. Доступ к базам данных через Web-сервисы388
Распределенные приложения388
Этапы создания распределенных приложений390
Реализация бизнес-логики распределенных приложений
на основе Web-сервиса391
Создание проекта Web-сервиса392
Создание соединения с базой данных и адаптера данных393
Конфигурирование интегрированной идентификации396
Создание определения класса набора данных DataSet398
Представление набора данных другим приложениям:399
Виды приложений- клиентов Web-сервисов403
Доступ к Web-сервисам из Windows-приложений403
Создание Windows-приложения404
Добавление к форме элементов управления406
Программный код загрузки и обновления данных408
Тестирование приложения411
Доступ к Web-сервисам из Web-приложений411
Создание проекта и Web-формы412
Добавление к форме элементов управления413
Программный код загрузки и обновления данных416
Тестирование приложения421
Глава 9. Развертывание приложений423
Инсталляция Windows-приложений423
Создание и установка приложения423
Создание ярлыка установленного приложения
на рабочем столе Windows430
Модификация диалога с пользователем433
Задание дополнительных свойств установщика проекта439
Установка приложения MyWin на компьютере разработчика440
Инсталляция Web-приложений441
Создание проекта развертывания442
Развертывание приложения на Web-сервере локального компьютера 444
Развертывание приложения на Web-сервере сети446
Демонтаж Web-приложения447
Глава 10. Удаленная работа с базами данных через Интернет-сайты449
Постановка задачи449
Структура базы данных452
Создание Web-сервиса453
Функции регистрации и идентификации пользователей455
Функции работы с каталогом товаров465
Функции для работы с заказами клиентов471
Функции работы с содержимым заказов клиентов484
Разработка клиентской части приложения495
Разработка Web-формы для регистрации и идентификации пользователей 496
Разработка Web-формы для получения доступа к каталогу товаров 506
Разработка Web-формы для получения доступа к заказам клиентов 513
Разработка Web-формы для добавления товаров в заказ клиента 524
Тестирование приложения536
Послесловие•539
Список литературы540
Об авторе
Постолит Анатолий Владимирович — доктор технических наук, профессор Московского автомобильно-дорожного института (технического университета). Увлекся автомобилями, компьютерами и программированием еще будучи студентом. Создавал программные средства практически для всех типов компьютеров — от "Минск-32" и "Проминь" до современных ПЭВМ. Преподавал на кафедрах прикладной математики, вычислительной техники, эксплуатации автотранспорта и автосервиса. В настоящее время работает в крупной транспортной компании "Мострансавто" и занимается разработкой информационных систем для автотранспортного комплекса. Специализируется на создании региональных информационных систем на основе MS SQL Server, VB6, с использованием, в последнее время, Visual Studio .NET. Ваши пожелания, вопросы и предложения присылайте автору по адресу postolit@gupmta.ru.
Введение
Сегодня в мире насчитываются миллионы людей, использующих языки программирования Visual Basic и С для разработки прикладных систем. Причем подавляющее количество приложений обеспечивают взаимодействие пользователей с различными базами данных: бухгалтерские, торговые, складские, транспортные, банковские и прочие системы. Как правило, корпоративные пользователи нуждаются в распределенных приложениях, поскольку подразделения фирм и их клиенты могут быть рассредоточены на достаточно большой территории.
Традиционно для создания распределенных систем использовались динамические ASP (Active Server Pages, активные страницы сервера). Однако из-за больших трудозатрат и необходимости привлечения специалистов высокой квалификации стоимость таких систем остается высокой. Учитывая это обстоятельство, фирма Microsoft реализовала технологию .NET, которая обеспечивает значительное снижение трудозатрат на реализацию распределенных информационных систем. В .NET-технологии коренным образом изменилась модель доступа к данным, что привело в замешательство многих программистов, использовавших ADO (ActiveX Data Objects, объекты данных ActiveX). Новые неизвестные объекты, исчезнувшие свойства и методы традиционных объектов и элементов управления приводят сначала к растерянности, а затем к неудовлетворенности новым инструментальным средством и неприятию этой технологии.
Данная книга посвящена разрешению этой проблемы. Она призвана помочь программистам, привыкшим работать с ADO, понять сущность нового подхода к обработке данных, испытать новые возможности Visual Studio .NET на элементарных примерах, и, в конечном итоге, с минимальными потерями времени адаптироваться к одной из самых перспективных технологий — Microsoft .NET.
В книге рассмотрены практически все элементарные действия, которые выполняют программисты, работая над реализацией прикладных систем. Пройдены все этапы от создания шаблона приложения до установки конечного продукта у клиента. Рассмотрены особенности базовых объектов и элементов управления. Книга предназначена для программистов, знакомых с языками программирования Visual Basic и С, работавших с ADO, имею-
щих опыт взаимодействия с базами данных на основе языка SQL. В данном издании в малой степени освещены вопросы разработки интерфейса, а больше внимания уделено взаимодействию различных типов приложений (Windows-формы, Web-формы, Web-сервисы) с базами данных.
Первые три главы книги посвящены обзору ADO.NET — основному компоненту, обеспечивающему взаимодействие приложений с базами данных. Приводится структура этого компонента и его сравнение со знакомым большинству программистов компонентом доступа к данным — ADO. Подробно рассматриваются свойства и методы таких объектов как соединение с базами данных, адаптеров данных и наборов данных, особенности работы приложений в отсоединенном от базы данных состоянии. Рассматриваются вопросы возможности выполнения операций манипулирования данными непосредственно на уровне базы данных с удаленных компьютеров (в рамках локальной сети или через Интернет), а также различные стратегии взаимодействия с данными при построении тех или иных типов приложений.
В четвертой главе обсуждается построение традиционных Windows- приложений с доступом к данным через ADO.NET. Рассматриваются вопросы редактирования данных через элемент управления DataGrid и текстовые поля, выборка данных через запросы с параметрами, работа со связанными таблицами, добавление, удаление и редактирование записей.
Пятая и шестая глава раскрывают тему построения ASP приложений с доступом к данным через ADO.NET. Рассматривается процесс построения простейшей Web-формы, работа с данными удаленных пользователей через сеть Интернет, быстрая выборка информации из баз данных, доступных только для чтения, а также возможность редактирования информации непосредственно на уровне базы данных с удаленных компьютеров, не передавая их на рабочую станцию пользователя. Приводится пример взаимодействия приложения с базами данных через компонент пользователя, проверка корректности вводимой информации на стороне удаленного клиента. Разбираются вопросы модификации данных с помощью серверного элемента управления DataGrid (добавление, удаление и обновление записей).
В седьмой главе приводятся основные понятия о Web-сервисах, их назначение, создание, отладка и развертывание, а также показана технология доступа к методам Web-сервисов из приложений-клиентов.
В восьмой главе разбирается доступ к базам данных через Web-сервисы. Приводится структура многоуровневого распределенного приложения. Описана технология взаимодействия Web-сервисов с базами данных и передачи выбранной из баз данных информации приложениям-клиентам. Описаны виды приложений-клиентов, порядок взаимодействия Windows-приложений и Web-форм с Web-сервисами.
В девятой главе рассмотрены проблемы развертывания Windows-приложений на компьютерах конечных пользователей и Web-приложений на IIS (Web-серверах), описана последовательность создания инсталляционных пакетов.
Заключительная десятая глава посвящена созданию Интернет-сайтов, обеспечивающих взаимодействие его посетителей с базами данных (с использованием Web-сервисов). Описан полный цикл реализации распределенного приложения на примере торговой компании: постановка задачи, реализация модулей регистрации и идентификации пользователей, получение информации из каталога продаваемых товаров, формирование заказов, их просмотр и редактирование.
На протяжении всей книги раскрываемые вопросы сопровождаются достаточно упрощенными, но полностью законченными примерами. Ход решения той или иной задачи сопровождается большим количеством иллюстративного материала. Желательно изучение тех или иных разделов выполнять непосредственно сидя за компьютером — тогда вы сможете последовательно повторять выполнение тех шагов, которые описаны в примерах, и тут же видеть результаты своих действий. Это в значительной степени облегчает восприятие приведенных в книге материалов. Наилучший способ обучения — это практика. Все листинги программ приведены на двух языках: Visual Basic и С#. Это прекрасная возможность познакомится еще с одним языком программирования или хотя бы понять, насколько эти два языка стали близки друг к другу. Оба языка используют одни и те же объекты, методы и свойства этих объектов. Основные отличия выражаются некоторыми особенностями синтаксиса. Фактически из разных языков программирования идет обращение к одной и той же библиотеке классов .NET Framework Class Library.
Итак, если вас заинтересовали вопросы создания прикладных систем с использованием Visual Studio .NET и одной из самых перспективных технологий программирования, то самое время перейти к изучению материалов этой книги.
ГЛАВА 1
ADO.NET как базовый объект доступа к базам данных
ADO.NET — новый этап в технологии ActiveX Data Objects (ADO, объекты данных ActiveX). Эта модель доступа к данным создана специально для использования в Web-приложениях. Если раньше в ADO упор делался на постоянное соединение с базой данных, то в технологии использования ADO.NET изначально заложена возможность работы приложения в состоянии "разрыва" соединения с базой данных. В ADO.NET обеспечивается возможность работы со всеми совместимыми с OLE DB источниками данных как в локальных сетях в рамках традиционных Windows-приложений, так и в глобальных сетях (Интернет) в рамках Web-приложений.
Из материалов первой главы вы узнаете:
О структуру компонента доступа к данным ADO.NET;
О как создать соединение с источником данных — объект connection;
О что такое адаптер данных — объект DataAdapter, и для чего он нужен;
И первым делом вам предстоит узнать, как устроен доступ к данным в ADO .NET.
Структура компонента доступа к данным ADO.NET
Большинство приложений, которые создаются для конечных пользователей, обеспечивают обработку информации, хранящейся в базах данных (склад-
ские, бухгалтерские, торговые, информационно-поисковые системы и т. п.). Это может быть небольшая система, работающая на локальном компьютере, система среднего класса, состоящая из десятка рабочих мест, объединенных локальной сетью, распределенная система, обеспечивающая доступ к данным сотням и тысячам пользователей через сеть Интернет. С точки зрения разработчика желательно иметь единый механизм и единый набор объектов, обеспечивающих доступ к данным, независимо от масштабности решаемой задачи. К счастью в технологии Microsoft .NET создана достаточна гибкая и эффективная модель доступа к данным — ADO.NET, предоставляющая разработчикам набор объектов, на основе которых можно создавать приложения любого масштаба (от локальных до глобальных).
При разработке приложения с использованием ADO.NET существует несколько разных стратегий обработки данных. В некоторых случаях требуется просто отобразить в форме определенную информацию, хранящуюся на сервере локальной сети, в других случаях вам нужно обеспечить доступ к данным из разных офисов одной или нескольких компаний не только для чтения, но и для редактирования.
Независимо оттого, что будет происходить с данными, есть определенные фундаментальные понятия, которые вы должны знать и понимать, если собираетесь создавать приложения, обеспечивающие доступ к данным через компонент ADO.NET. Даже если вы лично никогда не будете выполнять некоторые специфические операции, например, редактировать файл XML, содержащий данные, вы должны понимать, как это происходит. Нужно знать архитектуру ADO.NET, составные элементы, их функции, свойства и методы. В данном разделе дается общий обзор наиболее важных понятий. В материале умышленно опускаются многочисленные детали для того, чтобы вы уловили принципиальные возможности новой модели работы приложений с базами данных.
Примечание j
Когда вы распространяете приложения, работающие с данными и созданные в Visual Studio, вы должны убедиться, что у пользователей, использующих ваше приложение, установлен компонент доступа к данным от фирмы Microsoft (MDAC) версии 2.6 и выше.
Работа в отрыве от источника данных
В традиционных системах клиент-сервер при запуске приложения пользователем автоматически устанавливается связь с базой данных, которая поддерживается в "активном" состоянии до тех пор, пока приложение не будет закрыто. Такой метод работы с данными становится непрактичным, поскольку подобные приложения трудно масштабируются. Например, такая прикладная система может работать достаточно быстро и эффективно при наличии 8—10 поль-
зователей, но она может стать полностью неработоспособной, если с ней начнут работать 100, 200 и более пользователей. Каждое открываемое соединение с базой данных "потребляет" достаточно много системных ресурсов сервера, они становятся занятыми поддержкой и обслуживанием открытых соединений, их не остается на процессы непосредственной обработки данных.
При разработке прикладных систем в сети Интернет (Web-приложения) необходимо добиваться максимальной масштабируемости. Система должна работать одинаково эффективно как с малым, так и с большим числом пользователей.
По этой причине, в ADO.NET используется модель работы пользователя в отрыве от источника данных. Приложения подключаются к базе данных только на небольшой промежуток времени. Соединение устанавливается только тогда, когда клиент с удаленного компьютера запрашивает на сервере данные. После того, как сервер подготовил необходимый набор данных, сформировал и отправил их клиенту в виде WEB-страницы, связь приложения с сервером сразу же обрывается, и клиент просматривает полученную информацию уже не в связи с сервером. При работе в сети Интернет нет необходимости поддерживать постоянную "жизнеспособность" открытых соединений, поскольку неизвестно, будет ли конкретный клиент вообще далее взаимодействовать с источником данных. В таком случае целесообразнее сразу освобождать занимаемые серверные ресурсы, что обеспечит обслуживание большего количества пользователей. Программистам, привыкшим работать с ADO, придется потрудиться над осмыслением новой модели доступа к данным, которая представлена на рис. 1.1.
Рис .1.1. Модель доступа к данным в ADO.NET
В объектной модели ADO.NET можно выделить несколько уровней.
Уровень данных. Это по сути дела базовый уровень, на котором располагаются сами данные (например, таблицы базы данных MS SQL Server). На данном уровне обеспечивается физическое хранение информации на магнитных носителях и манипуляция с данными на уровне исходных таблиц (выборка, сортировка, добавление, удаление, обновление и т. п.).
Уровень бизнес-логики. Это набор объектов, определяющих, с какой базой данных предстоит установить связь и какие действия необходимо будет выполнить с содержащейся в ней информацией. Для установления связи с базами данных используется объект DataConnection. Для хранения команд, выполняющих какие либо действия над данными, используется объект DataAdapter. И, наконец, если выполнялся процесс выборки информации из базы данных, для хранения результатов выборки используется объект DataSet. Объект DataSet, по сути дела, представляет собой набор данных, "вырезанных" из таблиц основного хранилища, который может быть передан любой программе-клиенту, способной либо отобразить эту информацию конечному пользователю, либо выполнить какие-либо манипуляции с полученными данными.
Уровень приложения. Это набор объектов, позволяющих хранить и отображать данные на компьютере конечного пользователя. Для хранения информации используется уже знакомый нам объект DataSet, а для отображения данных имеется довольно большой набор элементов управления (DataGrid, TextBox, ComboBox, Label и т. д.). В Visual Studio .Net можно вести разработку двух типов приложений. В первую очередь это традиционные Windows-приложения (на основе Windows-форм), которые реализованы в виде ехе-файлов, запускаемых на компьютере пользователя. Ну и конечно, Web-приложения (на основе Web-форм), которые работают в оболочке браузера. Как видно из рис. 1.1, для хранения данных на уровне обоих типов приложений используется объект DataSet.
Обмен данными между приложениями и уровнем бизнес-логики происходит с использованием формата XML, а средой передачи данных служат либо локальная сеть (Интранет), либо глобальная сеть (Интернет).
Взаимодействие с базой данных через команды
В ADO.NET для манипуляции с данными могут использоваться команды, реализованные в виде SQL-запросов или хранимых процедур (DataCommand). Например, если вы хотите получить некий набор информации базы данных, вы формируете команду SELECT или вызываете хранимую процедуру по ее
имени.
Когда требуется получить набор строк из базы данных, необходимо выполнить следующую последовательность действий: открыть соединение (connection) с базой данных, вызвать на исполнение метод или команду, указав ей в качестве параметра текст SQL-запроса или имя хранимой процедуры, закрыть соединение с базой данных. Связь с базой данных остается активной только на достаточно короткий срок — на период выполнения запроса или хранимой процедуры.
Когда команда вызывается на исполнение, она возвращает либо данные, либо код ошибки. Если в команде содержался SQL-запрос на выборку - SELECT, то команда может вернуть набор данных. Вы можете выбрать из базы данных только определенные строки и колонки, используя объект DataReader, который работает достаточно быстро, поскольку использует курсоры read-only, forward-only.
Если требуется выполнить более чем одну операцию с данными — например, получить некоторый набор данных, а затем скорректировать его, — то необходимо выполнить последовательность команд. Каждая команда выполняется отдельно, последовательно одна за другой. Между выполняемыми командами соединение с базой отсутствует. Например, чтобы получить данные из базы — открывается связь, выбираются данные, затем связь закрывается. Когда выполняется обновление базы после корректировки информации пользователем, снова открывается связь, выполняется обновление данных в исходных таблицах и связь снова закрывается.
Команды работы с данными могут содержать параметры, т. е. могут использоваться параметризированные запросы, как, например, следующий запрос:
SELECT * FROM customers WHERE (custcmer_id=@custoinerid)
Значения параметров могут задаваться динамически, во время выполнения приложения.
Взаимодействие с базой данных через объект DataSet
Как правило, в приложениях необходимо извлечь информацию из базы данных и выполнить с ней некоторые действия: показать пользователю на экране монитора, сделать нужные расчеты или послать данные в другой компонент. Очень часто, в приложении нужно обработать не одну запись, а их набор: список клиентов, перечень заказов, набор элементов заказа и т. п. Как правило, в приложениях требуется одновременная работа с более чем одной таблицей: клиенты и все их заказы; автор и все его книги, заказ и его элементы, т. е. с набором связанных данных. Причем для удобства пользователя данные требуется группировать и сортировать то по одному, то по другому признаку. При этом нерационально каждый раз возвращаться к ис-
ходной базе данных и заново считывать данные. Более практично работать с некой временной "вырезкой" информации, хранящейся в оперативной памяти компьютера.
Эту роль выполняет набор данных — DataSet, который представляет собой своеобразный кэш записей, извлеченных из базового источника. В отличие от привычного Recordset, DataSet может состоять из одной или более таблиц, он имеет дело с копиями таблиц из базы данных источника. Кроме того, в данном объекте могут содержаться связи между таблицами и некоторые ограничения на выбираемые данные. Структура объекта DataSet приведена на рис. 1.2.
DataSet
Data RelationData RelationI Table 0
Data Relation
Data Relation
j Jable 1
Data Relation Table 2
* Table...
Рис. 1,2. Структура объекта DataSet
Данные в DataSet — это некий уменьшенный вариант основной базы данных. Тем не менее, вы можете работать с такой "вырезкой" точно так же, как и с реальной базой. Поскольку каждый пользователь манипулирует с полученной порцией информации, оставаясь отсоединенными от основной базы данных, последняя может в это время решать другие задачи.
Конечно, практически в любой задаче обработки данных требуется корректировать информацию в базе данных (хотя и не так часто, как извлекать данные из нее). Вы можете выполнить операции коррекции непосредственно в DataSet, а потом все внесенные изменения будут переданы в основную базу данных.
Важно отметить то, что DataSet — пассивный контейнер для данных, который обеспечивает только их хранение. Что же нужно поместить в этот контейнер, определяется в другом объекте — адаптере данных DataAdapter. В адаптере данных содержатся одна или более команд, которые определяют, какую информацию нужно поместить в таблицы объекта DataSet, по каким правилам нужно синхронизировать информацию в конкретной таблице DataSet и соответствующей таблицей основной базы данных и т. п. Адаптер данных обычно содержит четыре команды SELECT, INSERT, UPDATE, DELETE для выборки, добавления, корректировки и удаления записей (рис. 1.3).
DataAdapter
SelectCommandInsertcommandUpdateCommandDeleteCommand
Рис. 1.3. Набор команд объекта DataAdapter
Например, метод Fill объекта DataAdapter, заполняющего данными контейнер DataSet, может использовать в элементе SelectCommand следующий запрос:
SELECT au_id, au_lname, au_fname FROM authors
Набор данных DataSet — "независимая" копия фрагмента базы данных, расположенная на компьютере пользователя. Причем в этой копии могут быть не отражены те изменения, которые могли внести в основную базу данных другие пользователи. Если требуется увидеть самые последние изменения, сделанные другими пользователями, то необходимо "освежить" DataSet, повторно вызвав метод Fill адаптера данных.
Независимость набора данных DataSet от источника данных
Несмотря на то, что DataSet является фрагментом (кэшем) базы данных, он не имеет постоянной фактической связи с первоисточником. Объект DataSet — это контейнер, заполняемый информацией другим объектом — адаптером , данных - DataAdapter, который взаимодействует с первоисточником через SQL-запросы или хранимые процедуры. Один объект DataSet может взаимодействовать с несколькими объектами DataAdapter, каждый из которых обеспечивает наполнение данными таблиц контейнера,
Поскольку объект DataSet непосредственно не связан с источником данных, существует хорошая предпосылка для интеграции (объединения) данных, которые поступают из разных источников. Например, часть информации в DataSet может поступить из базы данных центрального офиса компании, часть из базы данных удаленного филиала, или вообще не из базы данных, а из другого источника, например, из электронной таблицы. Как только данные поступят в контейнер DataSet, пользователь может работать с ними как с единым информационным массивом, используя свойства и методы одного объекта, и абсолютно независимо от оригинального источ-
ника данных. Схема взаимодействия отсоединенного набора данных DataSet с базой данных приведена на рис. 1.4.
DataSetDataSet■► DataAdapterl [♦■► DataAdapterl [♦-*1 ТаЫеО-Клиенты-*1 ТаЫеО-Клиенты> DataAdapter2 -♦> DataAdapter2 -♦► Tablet-Заказы► Tablet-ЗаказыTable-Клиенты *Table-Клиенты *Table-Товары -<■Table-Товары -<■База данных
DataSet
DataSet
■► DataAdapterl [♦
■► DataAdapterl [♦
-*1 ТаЫеО-Клиенты
-*1 ТаЫеО-Клиенты
> DataAdapter2 -♦
> DataAdapter2 -♦
► Tablet-Заказы
► Tablet-Заказы
Table-Клиенты *
Table-Клиенты *
Table-Товары -<■
Table-Товары -<■
•> DataAdapter3 -«► ТаЫе2-Товары
Рис. 1.4. Схема взаимодействия отсоединенногонабора данных DataSet с базой данных
Обмен данными в формате XML
При работе приложений данные должны перемещаться между исходной базой данных и объектом DataSet. В ADO.NET в качестве единого формата для передачи данных используется XML-формат. Аналогично, если данные записать в некий внешний файл, то они будут записаны в XML-формате. Таким образом, файл с данными в формате XML является точно таким же источником, как и любая база данных, и из него можно поместить данные в объект DataSet. Фактически в ADO.NET XML является фундаментальным форматом для данных. В ADO.NET автоматически создают XML-файлы при передаче информации между объектами и компонентами.
Использование обмена данных в едином, формате XML имеет следующие преимущества:
О XML — единый промышленный стандарт, что обеспечивает разработанным вами прикладным компонентам обмениваться данными с любыми другими компонентами в любых других приложениях, поскольку все они понимают и используют формат XML;
О XML — обычный текстовый формат. При представлении данных в XML не используется двоичное кодирование, а это обеспечивает возможность передачи данных через любой протокол, например, через HTTP.
При разработке информационных систем вам, как программистам, не понадобиться знание структуры формата XML. ADO.NET автоматически выполнит преобразование данных в XML и из XML-формата так, как потребуется в текущий момент. Вы же будете взаимодействовать с данными пу-
тем использования обычных приемов программирования (через свойства и методы объектов).
Схемы, определяющие структуру данных
Хотя для манипулирования данными (извлекать, записывать, обновлять информацию в базах данных) вам не нужно знать структуру XML-файлов, все же могут возникнуть ситуации, когда необходимо напрямую работать с XML-форматом. Это обычно ситуации, в которых вы не извлекаете и не модифицируете сами данные, а работаете над проектированием структуры набора данных.
Описание набора данных в DataSet представлено с использованием формата XML. Для определения количества таблиц, перечня колонок каждой таблицы, задания типов данных, ограничений и тому подобного используется XML-схема, которая строится с использованием языка XML Schema Definition Language (XSD). Подобно тому, как данные могут быть загружены в объект DataSet из внешнего XML-источника, так и структура DataSet может быть загружена из XML-схемы.
При разработке большинства приложений нет необходимости углубляться в XML-схемы. Инструментальные средства Visual Studio .NET сами сгенерируют и скорректируют XML-схемы так, как требуется в текущей ситуации, основываясь на тех действиях, которые делает разработчик в режиме визуального дизайнера проекта. Например, когда вы используете окно дизайнера для создания объекта DataSet, где представлена одна из таблиц вашей базы данных, то Visual Studio .NET автоматически генерирует XML-схему, описывающую Структуру ЭТОГО DataSet.
Тем не менее, может настать время, когда вы захотите создать новые или отредактировать существующие схемы самостоятельно. В таком случае, конечно, понадобятся более глубокие знания по данному вопросу. Однако в данной книге обсуждать их нет необходимости.
Сравнение ADO.NET и ADO
Чтобы лучше понять особенности ADO.NET, сравним этот объект с уже известным нам объектом доступа к данным — ADO.
Представление данных в памяти
В ADO в памяти компьютера данные представлены в виде набора записей Recordset. В ADO.NET ДЛЯ ЭТОЙ Цели СЛУЖИТ набор Данных DataSet. ЕСТЬ
достаточно много важных различий между этими объектами. Остановимся на этих различиях более подробно.
Объект Recordset содержит всего одну таблицу. Если требуется поместить в объекте Recordset информацию из нескольких таблиц базы данных, то предварительно необходимо построить объединяющий SQL-запрос, который соберет информацию из нескольких таблиц в одну, и данные этой результирующей таблицы будут помещены в объект Recordset. Часто в результате объединения нескольких таблиц результирующая таблица доступна только для чтения, и через построенный объект Recordset невозможно обновлять информацию в исходной базе данных.
В отличие от вышесказанного, объект DataSet представляет собой коллекцию (одну или множество) таблиц. Таблицы в пределах набора данных DataSet представляют собой самостоятельные объекты — DataTabie. Если DataSet заполняется информацией из набора таблиц исходной базы данных, то в нем будет сформировано и множество объектов DataTabie. To есть, каждый объект DataTabie обычно соответствует единственной таблице исходной базы данных. Таким образом, DataSet как бы имитирует структуру основной базы данных.
В объекте DataSet также могут храниться и реляционные связи между таблицами. Реляционные отношения в пределах DataSet полностью аналогичны отношениям, построенным по ключевым полям, в исходной базе данных. Например, если объект DataSet содержит таблицы с заказчиками и заказами, то в нем можно сохранить и реляционную связь между заказчиками и сделанными ими заказами. Однако реляционные связи между таблицами не переносятся автоматически из основной базы данных, их необходимо создать принудительно (либо на этапе разработки приложения, либо в ходе выполнения приложения). Разработчик имеет возможность либо повторить существующую схему связей между таблицами, либо сформировать иное взаимоотношение между таблицами, чем было в исходной базе данных.
Поскольку DataSet может хранить набор таблиц и набор связей между ними, он является более гибким инструментом, позволяющим представлять пользователям более сложные, иерархические наборы данных, чем объект Recordset.
Навигация по данным и курсоры
В ADO можно получить доступ к требуемым данным, переместившись на нужную запись объекта Recordset (например, посредством метода MoveNext) и указав номер или имя поля. В ADO.NET представлена коллекция таблиц, а каждая таблица, в свою очередь, состоит из коллекции строк
(записей) и столбцов (полей). Получить доступ к требуемой информации можно путем указания номера (имени) таблицы, номера строки, номера (имени) столбца, В объектах DataRelation содержится информация о родительских и дочерних таблицах и имеется набор методов, обеспечивающих возможность получить доступ к записям дочерней таблицы на основании активного ключа в родительской таблице.
Курсор является элементом базы данных, который определяет способ навигации по записям, возможность (или невозможность) корректировки данных, и видимость изменений, которые были сделаны в базе данных другими пользователями. ADO.NET не имеет объекта, подобного курсору, но взамен этого представлены элементы, которые имеют то же функциональное назначение, что и традиционные курсоры в ADO. Например, функциональное назначение одностороннего просмотра данных и доступа только на чтение (forward-only, read-only) обеспечивает объект DataReader.
Минимизация открытых соединений
В ADO.NET связь с базой данных создается только на короткий период времени, достаточный для того, чтобы выполнять такие операции с базой данных, как, например, SELECT или UPDATE. Вы можете за короткий период времени заполнить данными объект DataSet, а затем работать с ними в состоянии "отрыва" от источника данных. В ADO объект Recordset так же может обеспечить работу с информацией в состоянии разрыва соединения с источником данных, но ADO изначально оптимизирован для работы в режиме связанного доступа.
Есть одно очень значимое различие между разъединенной обработкой в ADO и ADO.NET. В ADO происходит взаимодействие с основной базой данных через OLE DB провайдера. В ADO.NET происходит взаимодействие с базой через некого посредника — адаптера данных (OleDbDataAdapter или SqiDataAdapter). Адаптер данных позволяет контролировать процессы передачи информации из DataSet в исходную базу данных. Например, можно выполнить проверку правильности введенной информации до того, как эти изменения будут переданы источнику данных.
Разделение данных между приложениями
Передача набора данных DataSet между приложениями значительно легче, чем передача набора записей Recordset. Чтобы передавать разъединенный набор Recordset от одного компонента до другого, необходимо использовать COM marshalling. Для того чтобы передавать данные в ADO.NET, используется DataSet, который передается как XML-файл. Передача данных
через XML-файлы имеет ряд преимуществ перед COM marshalling, на которых мы пока останавливаться не будем.
Соединение с источником данных
(объект Connection)
Для перемещения данных между их постоянным хранилищем и приложением, в первую очередь необходимо создать соединение с источником данных (connection). В арсенале ADO.NET для этих целей имеется два объекта:
О SqlConnection — объект, позволяющий создать соединения с базами данных MS SQL Server версии 7.0 и выше;
O OleDbConnection — объект, позволяющий создать соединения с любыми источниками данных через OLE DB.
Объект SqlConnection создан и оптимизирован для работы с базами данных MS SQL Server версии 7.0 и выше. Объект OleDbConnection взаимодействует с OLE DB и позволяет подключиться к любым источникам данных — простые текстовые файлы, электронные таблицы, базы данных (включая и SQL Server).
Строка соединения
Первое свойство, которое необходимо определить для установления связи с базой данных — ConnectionString. Это текстовая строка, которая содержит набор элементов типа атрибут=значение атрибута и служит для определения типа провайдера, имени источника данных (DataSource), имени базы данных (Database), идентификатора пользователя (UserId), пароля доступа (Password), используемой системы безопасности и т. п. Эта строка может выглядеть, например, следующим образом:
MyConnection="Provider=SQLOLEDB.l;DataSource=MySQLServer; InitialCata- log=NORTHWIND; Integrated Security=SSPI"
Перечисленные атрибуты задаются в свойстве ConnectionString объекта, обеспечивающего связь с базой данных (SqlConnection или OleDbConnection). Кроме того, можно также установить свойство ConnectonString в не связанном с приложением udl-файле (Microsoft Data Link file, файл связи данных от Microsoft).
Примечание
Объект SQLConnection не поддерживает атрибут Provider, поскольку он работает только с одним провайдером данных.
Открытие и закрытие соединения
Объекты connection имеют два базовых метода для открытия и закрытия соединения (open и close). Метод open использует информацию из свойства ConnectionString, чтобы обратиться к источнику данных и открыть (установить) связь. Метод close закрывает открытое соединение. Закрытие связи приложения с базой данных является очень важным событием. В этот момент освобождаются ценные системные ресурсы, и база данных может обслуживать нового пользователя (количество обслуживаемых пользователей ограничено). Такая экономия особо актуальна для Интернет- приложений, где количество обслуживаемых клиентов может достигать нескольких сотен и тысяч.
Если ВЫ используете объекты DataAdapter или DataCommand, то нет необходимости явно открывать и закрывать соединение. Когда вызываются методы этих объектов (например, Fill или update), то автоматически делается проверка — открыто ли соединение. Если нет, DataAdapter сам откроет соединение, выполнит свои функции и снова закроет соединение.
Методы, такие как Fill, открывают и закрывают соединение автоматически только в том случае, если оно не было открыто. Если при вызове подобных методов соединение уже открыто, то оно используется и не закрывается после отработки методов. Такая стратегия дает возможность разработчикам самостоятельно управлять состоянием соединения. Это требуется в тех случаях, когда несколько объектов DataAdapter используют один объект Connection. Тогда более эффективно принудительно открыть соединение и оставлять его открытым, пока не отработают методы всех объектов DataAdapter, после чего принудительно закрыть соединение.
Пул соединений
В Web-приложениях часто множество различных пользователей могут обращаться к одной и той же базе и запрашивать одни и те же данные. В этих случаях исполняемое приложение может создать пул соединений к источнику данных.
Примечание
Пул — объект или физическое устройство, обеспечивающее доступ множества клиентов к одному источнику данных или к другому физическому устройству. В результате пул, как один объект соединения, обслуживающий множество клиентов, занимает в памяти сервера значительно меньше места, чем если бы было создано отдельное соединение для каждого клиента.
Если используется класс OleDbConnection, то пул соединений формируется автоматически провайдером, так что разработчик освобождается от управ-
ления этим процессом. Если используется класс SqlConnection, то создание пула соединений также обеспечивается, но программист имеет возможность вмешиваться в его управление.
Транзакции
Объекты connection поддерживают транзакции с помощью метода BeginTransaction, который создает объект OleDbTransaction ИЛИ SqlTransaction. Объекты Transaction в свою очередь поддерживают методы, которые позволяют вам завершить транзакцию (Commit) или сделать "откат" назад (RollBack).
Конфигурирование свойств Connection
Во многих приложениях содержимое объекта connection не может быть однозначно определено на этапе разработки проекта. Например, в приложении, которое будет распространяться среди множества клиентов, в connection не могут быть жестко прописаны такие параметры, как имя сервера, имя пользователя или пароль пользователя. У каждого потребителя программного продукта значения этих атрибутов будут свои. Следовательно, содержимое свойства ConnectionString должно формироваться динамически при запуске приложения. Поскольку динамические свойства соединения заносятся и хранятся в отдельном конфигурационном файле, который не компилируется, то они могут быть впоследствии изменены без перекомпиляции приложения. Динамические свойства автоматически получают значения из конфигурационного файла во время выполнения приложения. За работу этого механизма отвечает среда .NET Framework.
Сохранение элементов строки ConnectonString (таких как, например, имя сервера, имя пользователя и пароль) как динамических свойств может иметь смысл и для повышения безопасности вашего приложения.
Объект Connection и безопасность
Поскольку открытие соединения дает доступ к очень важному ресурсу сервера — базе данных, то становятся актуальными вопросы обеспечения безопасности и конфигурирования уровня безопасности.
Как вы будете обеспечивать безопасность приложения и порядок доступа из него к источнику данных зависит от архитектуры разрабатываемой системы. В Web-приложениях, например, пользователи обычно получают анонимный доступ к Internet Information Services (IIS), и поэтому не предоставляют никаких "сертификатов" на право пользования информацией. В этом случае,
ваше приложение должно обеспечивать собственную проверку прав входа в систему, чтобы дать "добро" на открытие соединения и обращения к базе данных. Имя пользователя и пароль могут быть или "прошиты" в откомпилированном приложении (в виде значения свойства, установленного во время разработки), или могут быть определены как динамические свойства, которые установлены в файле конфигурации Web-приложения.
Двоичные файлы Web-приложения и файл конфигурации защищены от доступа из сети Интернет собственными средствами защиты ASP.NET, которые предотвращают доступ к этим файлам через любой Интернет- протокол (гипертекстовый транспортный протокол — HTTP, протокол передачи файлов — FTP, и так далее). Чтобы предотвратить доступ к Web- серверу из вашей внутренней сети, необходимо использовать возможности защиты Windows.
В Интранет или в двухуровневых приложениях вы можете использовать интегрированную защиту — средствами Windows, IIS и SQL-сервером. В такой модели защиты для обращения к ресурсам базы данных используются параметры идентификации пользователя в сети, а не имя и пароль, заданные в строке соединения. При этом права доступа к информации устанавливаются на сервере базы данных через группы пользователей, так что нет необходимости установить индивидуальные параметры разрешения для каждого пользователя, который мог бы обратиться к базе данных. В данной модели вообще не нужно сохранять параметры соединения, и нет необходимости в принятии дополнительных мер по защите параметров строки соединения.
Создание объекта Connection в режиме дизайнера с помощью Server Explorer
Проводник Server Explorer обеспечивает наиболее простой путь создания соединения с источниками данных в режиме дизайнера на этапе проектирования приложения. Здесь программист имеет возможность просмотреть все доступные источники (базы) данных; увидеть таблицы, столбцы и многие другие элементы, а также редактировать и создавать новые элементы базы данных.
Ваше приложение непосредственно не использует соединения, созданные этим путем. И вообще информация, поставляемая соединением в режиме дизайнера при проектировании приложения, используется для того, чтобы задать свойства нового объекта Connection, который вы добавите к вашему приложению. Иными словами объекты connection, с которыми вы работаете в окне Server Explorer, являются элементами Server Explorer и служат шаблонами для создания объекта connection, который будет являться элементом формы и реально работать в вашем приложении.
Например, во время разработки вы задействовали Server Explorer для создания связи (объекта Connection) с SQL-сервером с именем MyServer и базой данных Northwind, которая поставляется вместе с SQL Server. Затем, при проектировании формы, через это соединение вы можете просмотреть структуру базы данных Northwind, выбирать таблицы, выделять нужные вам столбцы и перетаскивать их на форму. Как раз в момент "перетаскивания" элементов из базы данных на проектируемую форму будут автоматически сформированы объекты Connection и DataAdapter. В новое соединение скопируется информация из ConnectionString соединения-шаблона проводника Server Explorer. Когда разработанное приложение будет запущено на выполнение, то объект connection, расположенный на форме (а не в Server Explorer) будет реально обеспечивать соединение вашего приложения с источником данных.
Информация о соединениях в режиме проектирования приложений храниться на вашем локальном компьютере и не зависит от загруженного в данный момент проекта. Поэтому, как только вы загрузили в Visual Studio какой-либо проект, активизируется объект connection режима проектирования приложений — и вы видите доступные базы данных в проводнике Server Explorer.
Инструменты Visual Studio для создания объектов Connection
Программистам при работе с Visual Studio нет необходимости "руками" формировать свойства объектов connection. Для этого есть соответствующие инструментальные средства — например, Мастер Адаптера Данных, который запрашивает у разработчика информацию относительно источника данных и автоматически создает объект connection на форме или на другом компоненте, с которым вы работаете. Однако при желании разработчик можете сам добавить объект connection на форму или другой компонент и задать нужный набор свойств.
Создание объекта Connection в ADO.NET
Для создания объекта Connection можно использовать следующие возможности:
О Мастера Visual Studio:
Мастер конфигурации объекта DataAdapter. Этот мастер создает connection, как элемент, необходимый для формирования DataAdapter;
Мастер форм данных — данный мастер создает connection как часть формы, которую он формирует.
O Путь переноса таблицы, выбранных столбцов таблицы или хранимой процедуры из Server Explorer на форму. При перемещении одного из этих элементов на форму будут автоматически созданы объекты Connection ИDataAdapter.
O Создание автономного объекта connection. В этом варианте создается объект connection на форме или компоненте, свойства которого вы конфигурируете вручную. Данный способ можно использовать и тогда, когда вы предпочитаете устанавливать свойства объекта в окне Properties.
O Создание объекта connection во время работы программы.
Для создания автономного объекта Connection нужно выполнить следующие действия.
Создайте Windows- или Web-приложение (см. соответствующие разделы глав 2 и 3).
Из вкладки Data панели инструментов Toolbox поместите объект Connection на вашу форму или компонент. Для этого левой кнопкой мыши выделите объект OleDbConnection или SqlConnection (рис. 1.5), затем щелкните левой кнопкой мыши в любом месте формы.
lootbox-н X
Data1
l( Pointer
У DataSet
^ OleDbDataAdapter
tX; OleDbComection
'p OteDbiommand
^ SqlDataAdapter
| f^ SqlConnectlon
^ SqlCommand
5r DataVie1*
Рис. 1.5. Объекты Connection на вкладке Data окна Toolbox
Используйте объект SqlConnection, если вы будете работать с базой данных SQL Server версии 7.0 и выше. При этом будет создан объект Connection с именем SqlConnection, где N— последовательный номер (например, SqlConnectionl).
Используйте объект OleDbConnection, если вы будете работать с лю
бым другим источником данных, или если тип источника данных в последствии может измениться. При этом будет создан объект
Connection с именем OleDbConnectionN, где N — последовательный номер (например, OleDbConnection) .
Выделите объект Connection в окне дизайнера, затем в окне Properties модифицируйте значение свойства ConnectionString. Здесь вы можете установить или изменить такие свойства как DataSource, Database, UserName и так далее (вы не сможете переопределить атрибут provider ДЛЯ ОбъектаSqlConnection).
Если вы хотите переименовать объект Connection — измените его свойство Нате.
Если параметры объекта Connection должны быть переустановлены во время выполнения приложения, то необходимо сконфигурировать свойства объекта connection как динамические. Для этого в окне Properties раскройте узел DynamicProperties и щелкните в поле в правой части строки ConnectionString (рис 1.6).
Properties9 X
I OleDbCoimectionl System.Data.OteDb.OleObCi • |_S (DynamicProperties)*
(Advanced) Connectionstring (None) (Name)OleDbConnectionl
Рис. 1.6. Установление свойств объекта Connection в окне Properties
В открывшемся дополнительном окне Dynamic Propertys установите флажок Map property to a key in configuration file и нажмите кнопку OK (рис. 1.7).
Рис. 1.7. Установление динамических свойств объекта Connection в окне Dynamic Properly
В результате свойства строки соединения будут помещены во внешний конфигурационный файл, и их впоследствии можно будет менять без перекомпиляции приложения.
Адаптер данных (объект DataAdapter)
Объект DataAdapter — один из важнейших элементов ADO.NET. Этот объект является посредником между источником данных и набором данных DataSet. В приложениях DataAdapter обеспечивает считывание информации их базы данных и пересылку ее в DataSet, возврат изменений, сделанных пользователем, в исходную базу данных. Объект DataAdapter может работать не только с базами данных, он способен связать объект DataSet с любым источником и набором данных.
Вообще, DataAdapter является объектом с перестраиваемой конфигурацией, что позволяет разработчикам задавать, откуда и какую информацию перемещать в объект DataSet и из него. Задача перемещения данных решается через использование команд на основе SQL-запросов или хранимых процедур.
В Visual Studio имеется два типа адаптера данных:
O Объект OleDbDataAdapter, который используется для работы с любым источником данных, доступных через OLE DB-провайдера;
O Объект SqlDataAdapter, который используется для работы с данными, хранящимися в SQL Server версии 7.0 и выше. Поскольку SqlDataAdapter оптимизирован для работы именно с этим источником данных, то он работает с ним более эффективно и быстрее чем OleDbDataAdapter.
Вы можете создать и управлять адаптерами, используя части .NET Framework, указанные на рис. 1.8.
OleDb Managed ProviderSqlClient Managed Provider
SystemSystemDataDataNamespaceNamespace
System
System
Data
Data
■ SqlClient
|SqlCom mand
SqlConnection
- OleDbParameter- OleDbParameterOleDbDataAdapler
- OleDbParameter
- OleDbParameter
Рис. 1.8. Наборы объектов для OleDB-провайдера и SqlClient-провайдера
Каждый объект DataAdapter обеспечивает обмен данными между одной таблицей источника данных (базы данных) и одним объектом DataTabie в наборе данных DataSet. Если DataSet сдержит несколько таблиц (объектов DataTabie), то необходимо иметь и несколько адаптеров данных (рис.1.9).
Рис. 1.9. Взаимодействие адаптеров данных с таблицами базы данных и таблицами объекта DataSet
Когда требуется заполнить данными таблицу в DataSet, вызывается соответствующий метод (Fill) объекта DataAdapter, который по сути дела выполняет SQL-запрос или хранимую процедуру. Также DataAdapter создает объект чтения данных (OleDbDataReader ИЛИ SqlDataReader), чтобы считать данные из источника в DataSet. Точно так же, когда необходимо модифицировать базу данных, вызывается соответствующий метод (update) объекта DataAdapter, который вызывает на исполнение соответствующий SQL- запрос или хранимую процедуру (рис. 1.9). В результате этого все изменения, внесенные пользователем в таблицы набора данных, будут возвращены в соответствующие таблицы базы данных.
Адаптеры данных и связанные таблицы
Несмотря на то, что в объекте DataSet может быть несколько связанных таблиц, DataAdapter не имеет в SQL-запросах или хранимых процедурах команд (параметров), отражающих эти реляционные связи. Да это и физи-
>4nv R73
чески невозможно — ведь, как мы уже раньше отмечали, DataAdapter работает только с одной таблицей в базе данных и с одной таблицей в наборе данных DataSet. Для создания и хранения реляционных связей в DataSet используется другой объект — DataRelation. Кроме возможности создавать и хранить реляционные связи данный объект позволяет управлять ограничениями на работу с таблицами набора данных (например, реализовать каскадное обновление или удаление), а также обеспечивает навигацию в дочерней таблице при перемещении по записям в родительской таблице.
Например, представьте, что вам нужно получить данные из двух связанных таблиц базы данных Northwind: Customers и orders ("Клиенты" и "Заказы") и показать их в одном объекте DataGrid. Раньше для этого понадобилось бы выполнить объединение этих двух таблиц в одну, например, с использованием оператора join в SQL-запросе, чтобы получить единственный набор записей Recordset и затем его связать с DataGrid. Теперь достаточно определить два Объекта DataAdapter один, чтобы заполнить таблицу Customers ("Клиенты") в DataSet и второй, чтобы заполнить таблицу Orders ("Заказы"). В DataSet с использованием объекта DataRelation можно указать, что записи таблицы orders связаны с записями таблицы Customers полем CustomerId, после чего связать DataSet с объектом DataGrid. Теперь, имея заполненный объект DataSet и отключившись от исходной базы данных, вы по своему желанию можете работать как с каждой таблицей отдельно, так и, вызвав необходимые свойства и методы объекта DataRelation, со связанной парой таблиц. Этого в принципе невозможно было сделать с объектом Recordset, так как он заполнялся информацией из уже объединенного набора записей. Такая возможность является неоспоримым преимуществом Объекта DataSet над объектом Recordset.
Объекту DataAdapter для работы нужно иметь открытое соединение с источником данных, чтобы читать и записывать. информацию. Поэтому DataAdapter использует объекты OleDbConnection ИЛИ SqlConnection, ЧТОбы связаться с источником данных. DataAdapter может одновременно поддерживать до четырех открытых соединений, по одному для каждого типа действия, которое он может выполнить: SELECT, UPDATE, INSERT и DELETE. Объект OleDbConnection обеспечивает соединение с любым источником данных OLE DB-провайдера. Объект SqlConnection обеспечивает соединение с SQL Sewer 7.0 и выше. В обоих случаях, объект Connection представляет уникальный сеанс соединения с источником данных.
Адаптеры данных и объекты Command
Используя объект DataAdapter, можно читать, добавлять, модифицировать и удалять записи в источнике данных. Чтобы определить, как каждая из
этих операций должна произойти, DataAdapter поддерживает следующие четыре свойства:
O SelectCommand — описание команды, которая обеспечивает выборку нужной информации из базы данных;
O InsertCommand — описание команды, которая обеспечивает добавление записей в базу данных;
O UpdateCommand — описание команды, которая обеспечивает обновление записей в базе данных;
O DeleteCommand — описание команды, которая обеспечивает удаление записей из базы данных.
Каждая из этих команд реализована в виде SQL-запроса или хранимой процедуры.
Эти свойства являются самостоятельными объектами и относятся к элементам класса OleDbCommand или SqlCommand. Данные объекты поддерживают свойство CommandText, содержащее описание SQL-запроса или хранимой процедуры.
Примечание
Класс объекта Command должен согласовываться с классом объекта Connection. Например, если вы используете объект SqlConnection, чтобы связаться с SQL-сервером, то нужно использовать команды, которые происходят от класса SqlCommand.
Разработчик приложения может самостоятельно сформировать текст OleDbCommand или SqlCommand, хотя чаще в этом нет необходимости, поскольку Visual Studio автоматически генерирует необходимые инструкции SQL при создании объекта DataAdapter. Кроме того, DataAdapter может автоматически генерировать SQL-запросы во время выполнения приложения, если объекты UpdateCommand, InsertCommand ИЛИ DeleteCommand не определены на этапе проектирования приложения. Например, вы можете создать или изменить содержимое команды выборки данных, связанной объектом SelectCommand, непосредственно перед тем, как она будет запущена на выполнение.
В Visual Studio также имеется возможность выполнять команды независимо от объекта DataAdapter. Например, когда нет необходимости возвращать набор данных (проверка прав доступа пользователя к базе данных) или когда требуется изменить структуру некоторых таблиц. В этом случае обеспечивается возможность прямой работы с таблицами базы данных на уровне •SQL-сервера с удаленных компьютеров, как через локальную сеть, так и через Интернет.
Команды в DataAdapter могут иметь параметры. Например, команда выборки информации (SelectCommand), обычно имеет параметры в предложении WHERE, для того, чтобы получить из базы данных содержимое не всей таблицы, а только записей, соответствующих определенным критериям. Другие команды (например, UpdateCommand) используют параметры для выделения только тех записей в базе данных, которые необходимо модифицировать.
Чтение и обновление данных
с использованием объекта DataAdapter
Основная задача, которую должен решать объект DataAdapter — это перемещение информации между основным хранилищем данных на сервере и набором данных DataSet в памяти компьютера пользователя. Объект DataAdapter имеет методы, позволяющие переместить данные между этими двумя компонентами в прямом и обратном направлениях.
L Примечание j
Если в приложении требуется только прочитать данные из базы для просмотра (не модифицируя их), то нет необходимости помещать их в объект DataSet. Для этого случая имеется возможность считать информацию в режиме read only непосредственно из базы данных в приложение с помощью объекта DataReader, о чем более подробно будет сказано ниже.
Вы можете использовать DataAdapter для выполнения следующих операций.
O Перемещение записей из таблицы базы данных в соответствующую таблицу объекта DataSet;
Для этих целей используется метод Fin объектов SqlDataAdapter или OleDbDataAdapter. Когда вызывается этот метод, происходит обращение к базе данных с использованием SQL-запроса на основе инструкции SELECT;
O Передача изменений, сделанных пользователем в таблице объекта DataSet, исходной таблице базы данных.
для этих целей используется метод Update объектов SqlDataAdapter ИЛИ OleDbDataAdapter. Когда вызывается такой метод, происходит обращение к базе данных с использованием SQL-запроса на основе инструкций INSERT, UPDATE или DELETE, в зависимости оттого, что сделал пользователь — добавил, изменил или удалил некоторые записи.
Если в приложении необходимо только получить данные для последовательного просмотра (в режиме read-only), то можно использовать объект DataReader вместо объекта DataSet. Объект DataReader выбирает информа-
цию из источника (базы) данных и передает ее непосредственно вашему приложению. Как правило, объекты DataReader используются для быстрого просмотра данных в режиме read-only, forward-only, когда не требуется корректирование информации. Например, имеется страница Web-формы, которая просто отображает информацию, полученную из базы данных. Поскольку на Web-форме страница будет обновляться при каждом обращении к источнику данных, то нет необходимости помещать информацию в объект DataSet. Следует отметить, что объект DataAdapter тоже обращается к объекту DataReader для заполнения набора данных DataSet. В Visual Studio Имеется Два объекта чтения данных — OleDbDataReader И SqlDataReader, используемых соответственно для OLE DB-источников данных и для SQL Server версии 7.0 и выше.
В Visual Studio при создании набора данных имя результирующей таблицы в объекте DataSet (как и имена колонок) формируется на основе соответствующих имен исходной таблицы источника (базы) данных. Это может быть не совсем удобно как для разработчика, так и для конечного пользователя, поскольку названия колонок может быть слишком длинным или наоборот коротким и малоинформативным. В таком случае естественно возникает желание сменить соответствующие имена и сделать их более понятными и удобными в работе. В Visual Studio разработчики имеют возможность задать новое имя таблицы, создаваемой в DataSet, и новые имена колонок в команде формирования набора данных, а также привести их в соответствие с теми именами, которые используются в базе данных. В объекте DataAdapter имеется коллекция свойств TableMappings, которые обеспечивают поддержку соответствия между названиями элементов (таблиц и колонок) в DataSet и именами соответствующих элементов основного хранилища данных.
Параметры команд объекта DataAdapter
Команды адаптера данных DataAdapter определены в свойстве CommandText Объектов SelectCommand, InsertCommand, UpdateCommand И DeleteCommand. Обычно в этих командах содержится такие элементы, как параметры. Ведь заранее неизвестно, например, какие записи будет удалять или обновлять пользователь, это станет ясно только в процессе работы приложения. Причем в каждом сеансе набор этих записей будет различным.
Можно выделить два типа параметров.
O Параметры выборки. В реальных приложениях обычно требуется выбрать только некоторое подмножество записей из базы данных. Чтобы осуществить это, используется SQL-запрос или хранимая процедура, которые включают предложение WHERE с параметрами — критериями выборки. Кроме того, когда пользователь модифицирует или удаляет запись, используется предложение WHERE, в котором параметры определя-
ют, какие записи необходимо модифицировать или удалить. Значения параметров становятся известными только во время выполнения приложения, поэтому разработчик не может их заранее однозначно задать в программе.
O Параметры обновления. Когда в приложении модифицируются существующие записи или добавляются новые, то колонки (поля) в модифицируемых или добавляемых записях, должны получить новые значения. Чаще величина этих значений также становится известной только во время выполнения приложения.
Параметры выборки
Когда требуется выбрать ограниченное подмножество записей, чтобы заполнить таблицу в объекте DataSet, в предложение WHERE SQL-запроса включается один или более параметров, значения которых определяются только во время выполнения приложения. Например, пользователь хочет найтивбазеданныхкнигу,названиекоторойонввелв текстовомполе
Web-формы. Для этого вы должны в свойстве CommandText объекта SelectCommand написать SQL-запрос. Параметры запроса можно определить следующими способами: вопросительным знаком (?) или переменной с именем параметра (перед именем параметра должен стоять знак @). Для обозначения параметров в запросах на основе объектов OleDbCommand используются вопросительные знаки; в запросах на основе объектов SqlCommand использует переменные с именем параметра.
Текст запроса для объекта OleDbCommand может выглядеть следующим образом:
SELECT BookId, Title, Author, Price FROM BOOKS WHERE (Title LIKE ?)
Соответственно текст запроса для объекта SqlCommand:
SELECT BookId, Title, Author, Price FROM BOOKS WHERE (Title LIKE @title)
В приложении вы даете возможность пользователю ввести значение параметра запроса (наименование книги — title), например, в текстовом поле, затем присваиваете полученное значение параметру:
OleDbDataAdapterl.SelectCommand.Parameters("title").Value=txtTitle.Text
После этого запускаете команду на выполнение.
В Visual Studio можно формировать SQL-запросы с параметрами, используя встроенное средство Query Builder (построитель запросов).
Параметры обновления
Если объект SelectCommand адаптера данных может иметь или не иметь параметры, ТО объектыUpdateCommand,InsertCommand ИDeleteCommandвсегда имеют параметры.
Такие команды как UpdateCommand И InsertCommand всегда требуют наличия параметра для каждого столбца, который будет модифицирован. Кроме того, UpdateCommand и DeleteCommand требуют наличия параметра и в предложения WHERE, который будет идентифицировать те записи, в которые будут вноситься изменения.
Представим приложение, с помощью которого пользователи могут заказывать и покупать книги. Как и обычные покупатели в магазине, они имеют тележку для выбранных книг, которая в приложении реализована в виде таблицы данных — ShoppingCart. В таблице ShoppingCart пользователи заводят новые записи под каждую книгу, которую они хотят купить, с атрибутами: идентификатором книги (BookId) и идентификатором клиента (CustId), которые совместно выступают в роли ключа, однозначно идентифицирующего каждую запись в таблице ShoppingCart.
Когда пользователь кладет новую книгу в тележку для покупок, он фактически добавляет запись в таблицу ShoppingCart. В приложении эту процедуру можно реализовать с помощью SQL-запроса с инструкцией INSERT. В этом случае SQL-запрос выглядит следующим образом:
INSERT INTO ShoppingCart (BookId, CustId, Quantity) Values (?, ?, ?}
Три вопросительных знака в тексте запроса представляют собой параметры, значения которым будут присвоены во время выполнения приложения, соответственно после отработки запроса значения параметров будут переданы в колонки BookId, CustId, Quantity новой записи таблицы ShoppingCart. Если использовать переменные с именами параметров, тот же самый запрос будет иметь вид:
INSERT INTO ShoppingCart (BookId, CustId, Quantity) Values (@bookid, @custid, @quantity)
Если пользователь решает что-нибудь изменить в уже сделанной покупке, например, количество книг, то эту процедуру можно реализовать в приложении с помощью SQL-запроса на обновление, содержащего инструкцию UPDATE. Такой запрос может иметь следующий вид:
UPDATE ShoppingCart
SET (BookId=?, CustId=?, Quantity=?)
WHERE (BookId=? AND CustId=?)
Или, при использовании переменных с именем параметра:
UPDATE ShoppingCart
SET(BookId=@bookid, CustId=@custid, Quantity=@quantity)
WHERE (BookId=@bookid AND CustId=@custid)
В этом SQL-запросе параметры в предложении SET используются для заполнения новыми данными соответствующих колонок в таблице
ShoppingCart. Параметры в предложении WHERE выделяют тот набор записей, в которых произойдет обновление данных.
Пользователь может также удалить книгу из тележки для покупок. В том случае приложение могло бы вызвать SQL-запрос на удаление с предложением DELETE следующего типа:
DELETE FROM ShoppingCart WHERE (BookId=? AND CustId=?)
Или для переменных с именем параметра:
DELETE FROM ShoppingCart WHERE (BookId=@bookid AND CustId =@custid)
Коллекция параметров
Для обеспечения возможности передачи значений параметров из приложения в запрос во время выполнения программы, каждый из четырех объектов (SelectCommand, InsertCommand, UpdateCommand И DeleteCommand) объекта DataAdapter поддерживает свойство Parameters, которое содержит коллекцию параметров, соответствующих параметрам SQL-запроса. В командах для объекта OleDbDataAdapter индивидуальные параметры обозначаются, как OleDbParameter В Коллекции параметров OleDbParameterCollection. По аналогии команды в объекте SqlDataAdapter имеют обозначение параметров SqlParameter в коллекции SqlParameterCollection.
Если вы используете мастера конфигурации адаптера данных (Data Adapter Configuration Wizard), чтобы сконфигурировать объект DataAdapter, то коллекция параметров создается автоматически для всех четырех команд (SelectCommand, InsertCommand, UpdateCommand И DeleteCommand). Если ВЫ перетаскиваете элементы из Server Explorer на форму или компонент, то Visual Studio может выполнить следующие действия:
O Если вы перетаскиваете таблицу или некоторые колонки таблицы в окно дизайнера формы, то Visual Studio генерирует объект SelectCommand (SQL-запрос с инструкцией SELECT) без параметров и параметризованные объекты UpdateCommand, InsertCommand И DeleteCommand. Если ВЫ хотите, чтобы SQL-запрос объекта SelectCommand имел параметры, вы должны конфигурировать их вручную.
O Если вы перемещаете хранимую процедуру в окно дизайнера формы, то Visual Studio генерирует объект SelectCommand с параметрами, как и требуется для хранимой процедуры. Однако если вы нуждаетесь в других Объектах (UpdateCommand, InsertCommand И DeleteCommand), ВЫ ДОЛЖНЫ сконфигурировать их самостоятельно, вручную задав их параметры.
Наиболее рациональный путь создания параметризированных запросов для объекта DataAdapter — использование мастера Data Adapter Configuration Wizard. После работы мастера, если необходимо, можно изменить конфигурацию параметров вручную в окне Properties.
Структура коллекции Parameters
Каждый элемент коллекции параметров в объектах Command (SelectCommand, UpdateCommand, InsertCommand И DeleteCommand) соответствуют параметру SQL-запроса, записанного в свойство CommandText. Если объект command представляет собой SQL-запрос с параметрами в виде знаков вопроса, то каждый элемент в коллекции параметров будет соответствовать одному вопросительному знаку в SQL-запросе. Например, следующая инструкция запроса на обновление UPDATE требует коллекции из пяти параметров:
UPDATE ShoppingCart
SET (BookId=?, CustId=?, Quantity=?)
WHERE (BookId=? AND CustId=?)
Аналогично для именованных параметров:
UPDATE ShoppingCart
SET (BookId=@bookid, CustId=@custid, Quantity=@quantity)
WHERE (BookId=@bookid AND CustId=@custid)
Если объект command ссылается на хранимую процедуру, то номер элемента параметра в коллекции определяется процедурой. В хранимых процедурах параметры могут также иметь имена. В этом случае позиция параметра в коллекции не имеет значения. Каждый элемент параметра в коллекции имеет свойство ParameterName, которое используется для согласования с соответствующим параметром в хранимой процедуре.
Если вы формируете коллекцию параметров вручную, то необходимо точно знать, какие параметры требуются для корректной работы хранимой процедуры. Многие хранимые процедуры возвращают значение. В таком случае возвращаемое значение передается назад вашему приложению через коллекцию параметров, и вы должны учесть это. Кроме того, часто хранимые процедуры состоят из множества SQL-запросов, и вы должны убедиться, что коллекция параметров содержит все значения, которые необходимы всем запросам в процедуре.
Если параметры не имеют имен (в хранимых процедурах), то элементы коллекции имеют такую же нумерацию и расположение, как и параметры в хранимой процедуре. Если хранимая процедура возвращает значение, то первый элемент в коллекции параметров (нулевой элемент) зарезервирован для этого возвращаемого значения.
Поэтому для доступа к индивидуальному параметру коллекции можно сослаться на его индекс (номер) в коллекции. Однако если в объекте поддерживается свойство имя параметра (ParameterName), то возможен доступ к параметру по его имени. В листинге 1.1 приведен пример SQL-запроса на Visual Basic и С#. Вторая и третья строка запроса эквивалентны при условии, что второй параметр в коллекции имеет имя Title_Keyword.
Листинг 1.1
' Visual Basic
titleKeyword="%" & txtTitleKeyword.Text & "%"
OleDbDataAdapter1.SelectCommand.Parameters(1).Value=titleKeyword
OleDbDataAdapter1.SelectCommand.Parameters("TitleKeyword").Value = titleKeyword
// C#
string title Keyword="%"+txtTitle Key word. Text+" %";
this.OleDbDataAdapter1.SelectCommand.Parameters[1],Value=titleKeyword;
this.OleDbDataAdapter1.SelectCommand.Parameters["TitleKeyword"].Value= titleKeyword;
Здесь в первом случае программа присваивает значение параметру, ссылаясь на его номер в коллекции — 1, во втором случае — на его имя. Использование имени параметра в практике программирования более предпочтительно, чем индекса. При использовании имени уменьшается потребность в переписывании кода, если в ходе работы над проектом вдруг меняется количество параметров, а также отпадает необходимость помнить, возвращает ли хранимая процедура значение.
Для того чтобы получить доступ к имеющейся коллекции параметров, нужно в окне Properties найти свойство Parameters для интересующей вас команды. Например, на рис. 1.10 представлена строка доступа к параметрам команды адаптера данных InsertCommand для таблицы customers базы данных Northwind.
Рис. 1.10. Строка доступа к коллекции параметров команды InsertCommand
Если щелкнуть кнопку на поле (Collection) в строке Parameters, то откроется диалоговое окно редактирования свойств коллекции параметров
(рис. 1.11). В этом окне разработчик приложения имеет возможность изменить перечень параметров и их атрибуты. В левой части окна представлена созданная по умолчанию коллекция параметров с указанием их имен и индексов, в правой части окна — свойства каждого параметра.
Рис. 1.11. Окно редактирования свойств параметров команды InsertCommand
Установление значений параметров
Есть два способа, с помощью которых можно задать значения параметров:
O явным заданием значений параметрам через свойство value;
O располагая (добавляя) параметры в колонки таблицы объекта DataSet.
Вы устанавливаете значения параметров явно, когда заполняете набор данных или вызываете команду (для параметров выбора). Например, в примере поиска книг, приведенного выше, в приложении есть текстовое поле, в которое пользователь вводит ключевое слово (название книги). В этом случае можно явно установить значение параметра, привязав его к свойству Text текстового поля перед вызовом метода Fill объекта DataAdapter. Пример программного кода такого способа приведен в листинге 1.2.
|Листинг1.2
' Visual Basic
titleKeyword="%" a txtTitleKeyword.Text & "%"
OleDbDataAdapter1.SelectCommand.Parameters("TitleKeyword").Value=ъ
titleKeyword
OleDbDataAdapter1.Fill(dsAuthors1)
// C#
titleKeyword="%"+txtTitleKeyword.Text+"|";
this.OleDbDataAdapter1.SelectCommand.Parameters["TitleKeyword"].Value=^> titleKeyword;
this.OleDbDataAdapter1.Fill(dsAuthors1);
Параметры должны получить значения и в случаях обновления данных. Когда вызывается метода update объекта DataAdapter, то осуществляется просмотр всех записей таблицы набора данных DataSet, и модификация записей базовой таблицы (update, insert, delete) происходит на основе значений,полученныхизсоответствующих.колоноккаждойзаписи.Тоесть
параметры получают свои значения из колонок записи набора данных DataSet. Например, если в таблице объекта DataSet была добавлена новая запись и активизирована команда InsertCommand на вставку строки в основную таблицу базы данных, то значения параметров для предложения INSERT этой команды будут считаны из колонок той записи, которая была добавлена в таблицу объекта DataSet. Таков типичный сценарий работы команд обновления данных, но не единственный. Хранимые процедуры тоже могут возвращать данные через коллекцию параметров или через возвращаемое значение. В этом случае возвращенные значения должны быть "привязаны" к соответствующим колонкам таблицы набора данных DataSet.
Параметры обновления также возможно задать явно. Объект DataAdapter поддерживает событие RowUpdating, которое вызывается каждый раз, когда происходит обновление записи. Вы можете создать обработчик данного события и в нем явно присвоить параметрам нужные значения. Это обеспечивает жесткий контроль, над значениями параметров и позволяет переназначать их динамически в ходе работы программы непосредственно перед обновлением записи в таблице исходной базы данных.
Свойство TableMappings объекта DataAdapter
Когда DataAdapter считывает записи из источника данных, должно быть определено, как, разместить полученную информацию в соответствующей
таблице объекта DataSet. Это определяется схемой таблицы (table mapping). В такой схеме связываются между собой имена колонок таблицы источника данных с именами колонок таблицы набора данных DataSet. Например, информация из колонки с именем au_id в таблице источника данных может принадлежать колонке с именем author_id_number в таблице объекта DataSet.
По умолчанию, когда Visual Studio генерирует объект DataSet, элементы набора данных (таблицы и колонки) имеют те же самые имена, что и в источнике данных. Однако в некоторых ситуациях имена в источнике данных и наборе данных DataSet могут не совпадать.
O Набор данных был создан на основе существующей схемы, в которой использовались различные имена.
O Разработчик изменил имена элементов набора данных для удобочитаемости, для перевода наименований с одного языка на другой или по другой причине.
Сформировать или модифицировать структуру таблицы можно, используя свойство TableMappings адаптера данных, которое включает в себя коллекцию элементов DataTableMapping. Есть только один объект DataTableMapping для каждой отображаемой таблицы, потому что DataAdapter связывает только единственную исходную таблицу и единственную таблицу набора данных. Доступ к этому свойству можно получить из окна Properties объекта DataAdapter (рис. 1.12).
Properties9 X
SqlDataAdapterisysteirLData^ioienLS^DataAc^j
0 (Dynamicproperties)
(Name)SqlDataAdapterl
AcceptChangesDuringFillTrue
ContlnueUpdateOnErrorFake
0 DeleteCommandSqlDeleteCommaodl
0 InsertCommandSqllnsertCommandl
MissingMappingActionPassthrough
MIssingSchemaActlonAdd
ModifiersFriend
0 SelectCommandSqlSelectConwnandl
TableMappngs(Collection)
Рис. 1,12. Строка доступа к свойству TableMappings
При нажатии на кнопку в поле (Collection) свойства TableMappings появляется диалоговое окно, позволяющее редактировать элементы коллекции DataTableMapping (рис. 1.13). Здесь содержатся свойства для идентификации таблицы источника данных и таблицы набора данных, а так же свойст-
во ColumnMappings, содержащее элементы, которые представляют колонки соответствующих таблиц.
Рис. 1.13. Диалоговое окно Table Mappings
Когда происходит вызов метода Fin объекта DataAdapter, то выполняются следующие действия, в результате которых таблица объекта DataSet заполняется данными.
Адаптер данных ищет название каждого столбца исходной таблицы в объекте TableMappings.
Когда адаптер данных находит название столбца исходной таблицы, то получает название соответствующего ему столбца таблицы набора данных.
Получив имена этих двух столбцов, DataAdapter переносит данные от исходного столбца базовой таблицы в соответствующий столбец таблицы набора данных DataSet.
Есть две причины, которые могут воспрепятствовать данному процессу.
O Не найдена информация об исходном столбце. Это может произойти потому, что он не описан в схеме таблицы (например, разработчик из-
менил структуру исходной таблицы базы данных после того, как был Сформирован Объект DataAdapter).
O Столбец, в который нужно переместить данные, не определен в схеме набора данных.
Возникновение описанных выше ситуаций не приводит к критической ошибке, и адаптер может заполнять набор данных. Однако это уже некорректная работа с данными и на нее программа должна реагировать должным образом. Для этих целей адаптер данных поддерживает два свойства, которые позволяют запрограммировать действия, которые нужно выполнить, когда возникнет любая из этих двух ситуаций.
Свойство MissingMappingAction позволяет определить, какое действие адаптер должен выполнить, если в схеме данных отсутствуют некоторые параметры. Данное свойство имеет следующие значения:
O Passthrough — адаптер пытается загрузить данные исходного столбца в столбец с тем же именем набора данных. Если в наборе данных нет столбца с аналогичным именем, поведение программы в дальнейшем будет зависеть от параметров свойства MissingSchemaAction (см. ниже);
O Ignore — столбцы, которые должным образом не описаны в схеме, не загружаются данными и остаются пустыми;
O Error - генерируется ошибка.
Свойство MissingSchemaAction позволяет определять действия, которые должны быть выполнены в случае, когда адаптер не находит соответствующий столбец для записи данных. Возможные следующие значения:
O Add — таблица или столбец добавляются к схеме и к набору данных;
O AddWithKey— таблица или столбец добавляются к набору данных и к схеме, причем добавленный столбец делается ключевым;
O Ignore — таблица или столбец, не представленные в схеме набора данных не добавляются к набору данных;
O Error — генерируется ошибка.
Необходимо установить оба этих свойства, чтобы обеспечить устойчивость работы приложения. Например присвоение свойству MissingMappingAction значения Passthrough И свойству MissingSchemaAction значения Add обеспечит эффект автоматического дублирования таблицы источника в наборе данных DataSet.
Можно настроить свойства таким образом, что приложение будет генерировать ошибку, если есть какое-то несоответствие между базовой таблицей и схемой набора данных, что предотвратит некорректную обработку информации.
Если задается режим игнорирования ошибки, то обеспечивается гарантированная загрузка тех данных, которые явно определены в схеме или отображены в свойстве TableMappings. Это полезно использовать тогда, когда адаптер данных обращается к хранимой процедуре или SQL-запросу, которые возвращают больше столбцов, чем определено в наборе данных DataSet.
Создание объекта DataAdapter
Объект DataAdapter может быть создан следующими способами:
O с использованием Server Explorer;
O с использованием мастера;
O вручную.
Рассмотрим все эти возможности.
Создание объекта DataAdapter
с использованием Server Explorer
Для создания объекта DataAdapter с использованием Server Explorer постройте Windows или Web-приложение (см. соответствующие разделы глав 2 и 3), а затем выполните следующие действия.
Создайте или откройте форму в соответствующем приложении, активизируйте окно дизайнера формы и перейдите в окно Server Explorer.
Если нужный вам объект Connection отсутствует, то создайте его.
Откройте объект Connection и войдите в нужный вам элемент этого объекта (Tables, Stored Procedures, Views или Functions). Если, например, вам нужна не вся таблица, а только некоторые колонки, то раскройте следующий уровень и получите доступ к набору колонок таблицы. '
Примечание
Если вы выбрали хранимые процедуры, то затем вам необходимо будете вручную сформировать команды UpdateCommand, InsertCommand И DeleteCommand после создания объекта DataAdapter.
Выберите одну или более колонок таблицы или хранимой процедуры и перетащите их мышью в окно дизайнера формы (рис. 1.14).
Примечание
Вместо колонок можно перетащить всю таблицу, при этом будет сформирован запрос типа SELECT * FROM имя_таблицы. С точки зрения разработчика
такой путь, конечно, проще. Однако если для конкретной формы требуются не все колонки таблицы, то отбор индивидуальных колонок более предпочтителен и эффективен, потому что уменьшается объем данных, передаваемых по каналу связи.
Рис. 1.14. Таблица Customers в окне Server Explorer
После этого Visual Studio автоматически создаст два объекта connection И DataAdapter (рис. 1.15).
Рис. 1.15. Объекты SqlConnectionl и SqlDataAdapter1, созданные из окна Server Explorer
Если в качестве источника информации использовалась таблица базы данных, то в объекте DataAdapter будут сформированы команды для чтения и обновления данных. Если в качестве источника была взята хранимая процедура, то будут сформированы команды только для чтения данных.
Перетаскивание элементов данных из окна Server Explorer на проектируемую форму наиболее легкий путь создания объекта DataAdapter, однако он не дает возможности создать параметризованный запрос или новые хранимые процедуры. Для этого можно использовать мастер Data Adapter Configuration Wizard.
Создание объекта DataAdapter с использованием мастера
Мастер Data Adapter Configuration Wizard обеспечивает достаточно простой и самый гибкий способ создания адаптера данных.
Для создания объекта Data Adapter с помощью мастера постройте Windows или Web-приложение (см. соответствующие разделы глав 2 и 3) и выполните следующие действия.
Создайте или откройте форму в соответствующем приложении и активизируйте окно дизайнера формы.
Из вкладки Data окна Toolbox перенесите объект OleDbDataAdapter или SqlDataAdapter в область дизайнера формы (рис. 1.16).
Рис. 1.16. Выбор объекта DataAdapter в окне Toolbox
После этого Visual Studio добавит соответствующий объект DataAdapter к форме и запустит мастер Data Adapter Configuration Wizard.
В мастере последовательно выполняются следующие шаги:
На второй странице (рис. 1.17) создайте или выберите существующий объект Connection.
Рис. 1.17. Выбор или создание объекта Connection в мастере конфигурации объекта DataAdapter
На третьей странице (рис. 1.18) определите, должен ли адаптер данных использовать SQL-запрос или хранимую процедуру (значения переключателей приведены в табл. 1.1).
Рис. 1.18. Выбор способа получения записей из базы данных объектом DataAdapter
Таблица 1.1. Значения положений переключателя способа получения записей из базы данных объектом DataAdapter
Переключатель
Описание
Use SQL statement
Создается SQL-запрос на основе предложения SELECT, который DataAdapter будет использовать для заполнения данными результирующей таблицы объекта DataSet, а также мастер сгенерирует запросы на основе предложений UPDATE, INSERT и DELETE для обновления данных в исходной таблице базы данных
Use newly created stored procedures
Определяется запрос на основе предложения SELECT, и мастер создает хранимую процедуру для чтения и обновления источника данных. Если поставщик данных не поддерживает этот параметр, то он будет недоступен
Use existing stored procedures
Определяется существующая хранимая процедура, которую DataAdapter будет использовать для чтения и обновления источника данных
Что появится в следующей странице мастера, будет зависеть от сделанного выбора (в данном случае мы выберем переключатель Use SQL statement).
На четвертой странице (рис. 1.19) создается запрос на выборку данных с предложением SELECT.
Рис. 1.19. Создание запроса к базе данных в мастере конфигурации объекта DataAdapter
На этой странице можно либо просто набрать текст SQL-запроса, либо использовать мастер построения запросов, для запуска которого необходимо нажать кнопку Query Builder. При вызове мастера построения запросов появится дополнительное окно (рис. 1.20) с предложением выбрать одну из таблиц базы данных.
Рис. 1.20. Окно Add Table построителя запросов в мастере конфигурации объекта DataAdapter
В построителе запросов можно выбрать требуемую таблицу, указать перечень необходимых колонок, сконфигурировать параметры запроса, задать условия сортировки. Можно также выполнить запрос и посмотреть возвращаемые им данные (рис. 1.21).
После нажатия кнопки ОК мастер завершит свою работу, а текст построенного запроса будет передан мастеру конфигурирования адаптера данных (рис. 1.22).
Нажав на кнопку Next, мы перейдем на информационную страницу мастера (рис. 1.23), где выведен перечень элементов, созданных в результате работы мастера. Если мастеру, по каким-либо причинам не удалось создать некоторые элементы, они будут помечены соответствующими
Рис. 1.21. Работа в окне мастера построения запросов
Рис. 1.22. Текст созданного SQL запроса в мастере конфигурации объекта DataAdapter
View Wizard ResultsReview the list of tasks the wizard has performed. Click Finish to complete or Back to make changes.View Wizard ResultsReview the list of tasks the wizard has performed. Click Finish to complete or Back to make changes.
View Wizard Results
Review the list of tasks the wizard has performed. Click Finish to complete or Back to make changes.
View Wizard Results
Review the list of tasks the wizard has performed. Click Finish to complete or Back to make changes.
, The data adapter "SqlDataAdapterl" was configured successfully.
Details:
✓ Generated SELECT statement.
* Generated table mappings.
V Generated INSERT statement.
v Generated UPDATE statement.
v Generated DELETE statement.
To apply these settings to your adapter, click Finish.To apply these settings to your adapter, click Finish.< Back< Back
To apply these settings to your adapter, click Finish.
To apply these settings to your adapter, click Finish.
< Back
< Back
Рис, 1.23. Перечень элементов, созданных в результате работы мастераконфигурации объекта DataAdapter
предупреждающими значками. В нашем случае против каждого элемента стоит отметка о его успешном создании.
Когда мастер закончит свою работу кроме объекта DataAdapter будет построен и объект connection, который был определен на второй странице мастера.
Если вы хотите изменить название объектов DataAdapter и connection, выберите мышью нужный объект и задайте удобное для вас имя в окне Properties.
Если вы хотите посмотреть, какие данные DataAdapter перенесет в набор данных DataSet, то можно запустить мастера предварительного просмотра данных. Для этого нужно в меню Data выбрать пункт Preview Data и в открывшемся диалоговом окне Data Adapter Preview нажать кнопку Fill DataSet (рис. 1.24).
Вы также имеете возможность переконфигурировать адаптер DataAdapter вручную. Для этого нужно модифицировать схему данных. Выполнение такой процедуры рассматривается в следующем разделе.
Рис. 1.24. Предварительный просмотр данных, представляемых объектом DataAdapter
Создание и конфигурирование объекта DataAdapter вручную
Бы можете создать объект DataAdapter вручную, без использования соответствующего мастера. Независимо от того, когда и каким способом был создан DataAdapter, всегда имеется возможность изменить его конфигурацию.
Для создания объекта DataAdapter вручную вам необходимо выполнить следующие действия.
Убедитесь, что объект connection создан и расположен на проектируемой форме или компоненте.
Из вкладки Data окна Toolbox перенесите объект OleDbDataAdapter или SqlDataAdapter в область дизайнера формы. Visual Studio добавит соответствующий объект DataAdapter к форме и запустит мастер Data Adapter Configuration Wizard. .
Закройте мастера Data Adapter Configuration Wizard.
Процесс ручного конфигурирования объекта DataAdapter заключается в следующем.
Выделите мышью объект DataAdapter и перейдите в окно Properties, где можно сформировать команды, позволяющие читать и обновлять данные. В первую очередь необходимо сформировать объект SelectCommand (рис. 1.25). Если DataAdapter будет использоваться И для модернизации таблицы источника данных, то также необходимо Сформировать объекты UpdateCommand, DeleteCommand, InsertCommand.
Рис. 1.25. Ручное формирование свойств команды SelectCommand в окне Properties адаптера данных
Для каждого объекта Command необходимо задать следующие свойства (табл. 1.2).
Таблица 1.2, Свойства объекта Command
Свойство
Описание
ActiveConnection
Устанавливает ссылку на объект Connection. Кроме того, можно создать новый объект Connection в свойстве ActiveConnection окна Properties. Как правило, все объекты Command используют один и тот же объект Connection. Однако вы имеете возможность использования различных объектов Connection для каждого из объектов Command
CommandText
Содержит текст SQL-запроса или имя хранимой процедуры. Для некоторых провайдеров возможно создание мультизапроса или хранимой процедуры с несколькими инструкциями, разделенными точкой с запятой (;). Эти инструкции выполняются последовательно. Это полезно для ситуаций, когда после добавления или удаления записей нужно повторно получить из базы данных обновленную информацию
Таблица 1.2. (окончание)
Свойство
Описание
CommandType
Тип команды в свойстве CommandText. Может принимать следующее значения:
O Text — текст SQL-запроса
O StoredProcedure — хранимая процедура
О TableDirect - ИМЯ Таблицы
Parameters
Коллекция объектов Parameter , через которые значения параметров передаются команде. 8 объекте SelectCommand создается коллекция параметров только в том случае, если команда возвращает не все записи исходной таблицы. Объекты UpdateCommand, InsertCommand И DeleteCommand всегда требуют определения параметров
Определите свойство MissingMappingAction. По умолчанию это свойство имеет значение Passthrough, при котором именам таблиц и колонок результирующего набора данных автоматически присваиваются имена соответствующих элементов источника данных. Если вы не хотите иметь одинаковые имена столбцов в таблице источника данных и таблице набора данных нужно задать желаемую схему соответствия данных.
В меню Data выберите пункт Generate DataSet.
Если отсутствует меню Data, то нужно щелкнуть мышью в любом месте формы, этот пункт доступен только тогда, когда фокус установлен в окне дизайнера формы.
Если вы хотите увидеть, какими данными DataAdapter заполнил набор данных DataSet, вызовите окно предварительного просмотра данных.
4.7. Конфигурирование параметров объекта DataAdapter
В большинстве случаев команды адаптера данных (SelectCommand, InsertCommand, UpdateCommand И DeleteCommand) построены на основе SQL- запросов с параметрами. Если для создания объекта DataAdapter использовать мастер Data Adapter Configuration Wizard, то параметры для этих команд будут сконфигурированы автоматически. Однако вы можете сконфигурировать параметры вручную, или сделать необходимые изменения в уже существующей коллекции параметров.
Примечание
Для конфигурирования параметров после изменения текста SQL-запроса объекта Command необходимо установить флажок Regenerate parameters collection for this command в построителе запросов Query Builder.
Для конфигурации параметров объекта DataAdapter необходимо.
Создать объект DataAdapter.
В форме мышью выделить объект DataAdapter и открыть окно свойств Properties (рис. 1.26).
Рис. 1.26. Доступ к коллекции параметров команды UpdateCommand в окне свойств объекта SqlDataAdapterРис. 1.26. Доступ к коллекции параметров команды UpdateCommand в окне свойств объекта SqlDataAdapter
Рис. 1.26. Доступ к коллекции параметров команды UpdateCommand в окне свойств объекта SqlDataAdapter
Рис. 1.26. Доступ к коллекции параметров команды UpdateCommand в окне свойств объекта SqlDataAdapter
Раскройте объект Command, для которого вы хотите сконфигурировать параметры (например, UpdateCommand) и затем в свойстве Parameters нажмите кнопку, чтобы открыть окно SqlParameter Collection Editor (рис. 1.27).
Members:Members:©Customer ID©Customer ID_1 ©CompanyName2 ©ContactName~3_ ©ContactTitte4_ ©Address5_ ©Qty©Region©PostalCode©Country©PhoneAddRemove_1 ©CompanyName2 ©ContactName~3_ ©ContactTitte4_ ©Address5_ ©Qty©Region©PostalCode©Country©PhoneAddRemove©CustomerlD Properties: 0Direction Precision Scale SizeSourceCoicmn SoirceVersion©CustomerlD Properties: 0Direction Precision Scale SizeSourceCoicmn SoirceVersion000055Customer IDCustomer IDCurrentCurrentSqDbType NVarChar Value0ParameterName ©CustomerlDSqDbType NVarChar Value0ParameterName ©CustomerlDOKCancelOKCancelHelpHelp
Members:
Members:
©Customer ID
©Customer ID
_1 ©CompanyName
2 ©ContactName
~3_ ©ContactTitte
4_ ©Address
5_ ©Qty
©Region
©PostalCode
©Country
©Phone
AddRemove
_1 ©CompanyName
2 ©ContactName
~3_ ©ContactTitte
4_ ©Address
5_ ©Qty
©Region
©PostalCode
©Country
©Phone
AddRemove
©CustomerlD Properties: 0
Direction Precision Scale Size
SourceCoicmn SoirceVersion
©CustomerlD Properties: 0
Direction Precision Scale Size
SourceCoicmn SoirceVersion
0
0
0
0
5
5
Customer ID
Customer ID
Current
Current
SqDbType NVarChar Value
0
ParameterName ©CustomerlD
SqDbType NVarChar Value
0
ParameterName ©CustomerlD
OKCancel
OKCancel
Help
Help
Рис. 1,27. Окно конфигурирования параметров команды UpdateCommand
Для создания нового параметра щелкните на кнопке Add.
Переместите новый параметр в нужное место коллекции, используя кнопки со стрелками для перемещения его вверх или вниз.
Чтобы установить требуемое свойства параметра, выберите его в списке Members и затем назначьте ему нужное свойство. В табл. 1.3. перечислены типовые свойства, которые вы можете установить.
Таблица 1.3. Свойства параметров объектов DataCommand адаптера данных
СвойствоОписание
SourceColumnИмя столбца в таблице набора данных, из которого будет читаться
значение параметра. Это свойство используется с параметрами, которые заполняются значениями в запросах UPDATE, INSERT или DELETE (то же в хранимых процедурах)
SourceVersionЕсли параметр получает значение из свойства SourceColumn, то
SourceVersion определяет, какая версия записи набора данных будет использоваться, как источник значения параметра;
O Original — значение столбца, которое было получено из базы данных. Вы можете использовать данное значение тогда, когда вам необходимо иметь то значение столбца, которое было до его изменения. Например, было изменено значение ключевого поля, но вам необходимо иметь старое значение этого поля, чтобы найти нужную запись в базе данных
O Current — значение столбца после того, как запись была изменена. Это обычно то значение, которое будет записано в базу данных
O Default — значение, которое будет присвоено столбцу, если никакое другое значение явно не задано
ValueЗначение, присвоенное параметру. Это свойство обычно устанав
ливается динамически (во время выполнения программы), а не статически во время ее разработки
Свойство Value имеет приоритет по отношению к свойству SourceColumn, если они оба установлены
NamedParameter Поименованный параметр. Булево значение, указывающее, что параметр является переменной с именем (@parametername) или меткой (?). Если вы работаете с объектом SqlConnection и используете поименованные параметры, то установите значение NamedParameter равным true
DBType, Preci- Информация о типе значения параметра (в источнике данных), sion,Scale, Значение параметра будет конвертировано в тип данных, который
Sizeвы определили, или из него
Таблица 1.3. (окончание)
Свойство
Описание
Direction
Указание направления: передается ли значение параметра к команде или от команды:
Input — значение передается к команде. Это значение установлено по умолчанию
Output — значение передается к хранимой процедуре (не используется с SQL-запросами)
InputOutput — значение передаются к хранимым процедурам и возвращаются назад, обычно в измененном виде
ReturnValue — явно возвращаемое значение. По умолчанию возвращаемое значение — первый элемент в коллекции параметров (с индексом 0)
ParameterName
Имя, по которому можно обратиться к параметру вместо его номера в коллекции. Для простоты последующего сопровождения приложения рекомендуется использовать имя параметра, а не его номер
Нажмите кнопку ОК для закрытия окна SqlParameter Collection Editor.
Повторите шаги с 3-го по 7-й для задания конфигурации параметров ДРУГИХ Объектов Command.
Связывание колонок таблиц источника данных и объекта DataSet через адаптер данных
В Visual Studio в объекте DataAdapter имеется возможность установить соответствие между колонками таблицы базы данных (источника данных) и колонками таблицы объекта DataSet. Это обеспечивает возможность сменить наименование колонок и сделать их удобочитаемыми как для разработчика, так и для конечного пользователя приложения.
Для установления соответствия между колонками таблиц выполните следующие действия.
Создайте объект DataAdapter.
Мышью установите фокус на объекте DataAdapter в окне дизайнера формы и откройте окно Properties этого объекта.
3. Далее (рис.3. Далее (рис.в строке свойства TableMappings нажмите кнопку (Collection) 1.28).
3. Далее (рис.
3. Далее (рис.
^ X^ XII Properties
^ X
^ X
шшInsertcommandInsertcommandSqllnsertCommand 1SqllnsertCommand 1MtssngMappingAction PassthroughMtssngMappingAction Passthrough00MissingSchema ActionModfiersSelectCornmandTableMappinqsMissingSchema ActionModfiersSelectCornmandTableMappinqs0 UpdateCommand0 UpdateCommandAddFriend SqlSelectCommand 1 (Collection) SqlUpdateCommandl.AddFriend SqlSelectCommand 1 (Collection) SqlUpdateCommandl.SqlDataAdapterl System.Data.SqiOient.SqlDat
ш
ш
Insertcommand
Insertcommand
SqllnsertCommand 1
SqllnsertCommand 1
MtssngMappingAction Passthrough
MtssngMappingAction Passthrough
0
0
MissingSchema Action
Modfiers
SelectCornmand
TableMappinqs
MissingSchema Action
Modfiers
SelectCornmand
TableMappinqs
0 UpdateCommand
0 UpdateCommand
Add
Friend SqlSelectCommand 1 (Collection) SqlUpdateCommandl.
Add
Friend SqlSelectCommand 1 (Collection) SqlUpdateCommandl.
Рис. 1.28. Доступ к коллекции колонокчерез свойство TableMappings
После этого откроется диалоговое окно TableMappings (рис. 1.29).
Рис. 1.29. Диалоговое окно TableMappingsРис. 1.29. Диалоговое окно TableMappings
Рис. 1.29. Диалоговое окно TableMappings
Рис. 1.29. Диалоговое окно TableMappings
Если вы хотите использовать имена колонок из таблицы источника данных в колонках таблицы созданного объекта DataSet, установите
флажок Use a dataset to suggest table and column names, и затем из списка Dataset выберите интересующий вас набор данных.
Далее вы можете выбрать нужную таблицу из источника данных - Sourse table, и нужную таблицу из результирующего набора данных - Dataset table. Имена колонок этих таблиц будут представлены соответственно в левой и правой части сетки Column mappings.
В столбце Source table, выберите таблицу в источнике данных. Если там присутствует только одна таблица, то вместо ее имени будет стоять значение Table.
В столбце Dataset table выберите таблицу из набора данных. Если вы уже определили набор данных на шаге 4, то имя таблицы будет уже заполнено (по умолчанию первая таблица набора данных будет отмечена как Table).
На основе вашего выбора (или того, что было установлено по умолчанию), имена колонок будут внесены в список разделов Source Columns и Dataset Columns. Иными словами, будет установлено соответствие между колонками: каждому названию колонки в левой части сетки Column mappings будет сопоставлено название соответствующей колонки в правой части.
Далее модифицируйте это сопоставление так, как вам необходимо. С помощью таблицы можно выполнить следующие действия.
Изменить связи между колонками — к колонке объекта DataSet можно "привязать" любую другую колонку источника данных.
Удалить колонки. Это можно сделать в тех случаях, когда адаптер данных возвращает большее число колонок из источника данных, чем необходимо данному приложению.
Добавитьколонки.Этонеобходимовтехслучаях,когдаизвестно,
что колонки будут заполнены данными динамически во время работы приложения, или если вы удалили колонку по ошибке и ее необходимо вернуть назад, или если вы полностью очистили адаптер данных и желаете сформировать его вручную.
Для примера изменим наименования колонок в DataSet и введем наименования колонок на русском языке (рис. 1.30).
Когда закончен процесс взаимной привязки колонок, нажмите кнопку ОК.
Если вы хотите определить, как должно вести себя приложение в случаях возникновения ошибок, в окне Properties выберите нужное значение СВОЙСТВ MissingMappingAction И MissingSchemaAction. В табл. 1.4 ОПИсаны возможные варианты и получаемый эффект.
Рис. 1.30. Изменение наименований колонок в диалоговом окне TableMappings
Таблица 1.4. Возможные значения свойств MissingMappingAction и MissingSchemaAction и получаемый эффект
MissingMappingAction
MissingSchemaAction
Эффект
Passthrough
Add or AddWithKey
Если колонка существует в таблице источника данных, но ее нет в таблице приемника данных, то эта колонка будет создана динамически во время заполненияданнымиобъекта
DataSet. Эти значения установлены по умолчанию, и такое задание полезно тогда, когда необходимо копировать в набор данных все колонки, доступные в источнике
Ignore
Ignore
Если колонка не определена в схеме набора данных, или нет никакой привязки ее к источнику данных, то информация от источника данных не будет перенесена в объект DataSet. Эта установка полезна, если адаптер возвращает больше колонок, чем описано в приемнике данных DataSet
Таблица 1.4. (окончание)
MissingMappingAction
MissingSchemaActionЭффект
Error
ErrorБудет сгенерирована ошибка во
время выполнения приложения, если
адаптер не сможет сопоставить исходную колонку с колонкой набора данных. Эта установка полезна тогда, когда вам необходимо строгое соблюдение описанной схемы обмена информацией между источником и приемником данных
Предварительныйпросмотрданных, полученных объектом DataAdapter
После того, как был сконфигурирован объект DataAdapter, есть возможность проверить, какой информацией адаптер данных заполнит объект DataSet.
Для предварительного просмотра результатов работы объекта DataAdapter выполните описанные ниже действия.
Создайте объект DataAdapter.
В форме выделите мышью объект DataAdapter и откройте окно свойств Properties.
В нижней части окна щелкните мышью на ссылке Preview Data (рис. 1.31).
| Properties"9 X ||
SqlDataAdapter I System.Data SqlOentSqDat *•
- s®
(Name)*SqlOata Adapter IjJ
! ' Accept ChangesDurlngF True- J
ContnueUpdeteOnEirc False
0 DdeteCcmmand SqlDelctrCommandl _2J^иг/кдигераи Adap'.ei .-, fiRMrflhip^*....
preview D-sta...
Рис. 1.31. Окно свойств объекта DataAdapter
При этом откроется окно предварительного просмотра данных.
Выберите нужный адаптер данных из списка Data Adapter или выберите пункт All DataAdapters.
Если команда, на которую ссылается объект SelectCommand, требует параметров, то введите значения параметров в поля в таблице Parameters.
3 Зак. 873
НажмитекнопкуFillDataset длязапускакомандывыборкиданныхна
исполнение (рис. 1.32).
Dataset Size 34904 bytes (34.0 Kb)Dataset Size 34904 bytes (34.0 Kb)Customers 91 Row($)Customers 91 Row($)Target dataset: |whdowsApplKdtion2 Dat.jJData tables:Target dataset: |whdowsApplKdtion2 Dat.jJData tables:CustomersCustomersКомпания Alfreds Putter Ana TrujiBo E Antonio More Around the H Berglunds sn Blauer See D Blondesddsl p Bohdo Comid Bon app*Bottom-DolarКомпания Alfreds Putter Ana TrujiBo E Antonio More Around the H Berglunds sn Blauer See D Blondesddsl p Bohdo Comid Bon app*Bottom-DolarФИОMarla Anders Ana Truilo Antorto More Thomas HardChristina Berg Hanna MoosFred^tique Ct Martin Somm Laurence Lett Elizabeth LineФИОMarla Anders Ana Truilo Antorto More Thomas HardChristina Berg Hanna MoosFred^tique Ct Martin Somm Laurence Lett Elizabeth LineДолжность Sales Represe OwnerSales Represe Order Admire Sales Represe Marketrig Ma Owner Owner Accounting MДолжность Sales Represe OwnerSales Represe Order Admire Sales Represe Marketrig Ma Owner Owner Accounting MАдресObere Str. 57 Avda. de la C Mataderos 2 120 Hanover Bet guvsvager Forster str. 57 24, place Kle С/ Araqui, 67 12, rue des В 23 TsawassenАдресObere Str. 57 Avda. de la C Mataderos 2 120 Hanover Bet guvsvager Forster str. 57 24, place Kle С/ Araqui, 67 12, rue des В 23 TsawassenГород*|Berk IMexico D.F.Mexico D.F.LondonLuleSMannheimStrasbourg MadridMar seileГород*|Berk IMexico D.F.Mexico D.F.LondonLuleSMannheimStrasbourg MadridMar seile
Dataset Size 34904 bytes (34.0 Kb)
Dataset Size 34904 bytes (34.0 Kb)
Customers 91 Row($)
Customers 91 Row($)
Target dataset: |whdowsApplKdtion2 Dat.jJ
Data tables:
Target dataset: |whdowsApplKdtion2 Dat.jJ
Data tables:
Customers
Customers
Компания Alfreds Putter Ana TrujiBo E Antonio More Around the H Berglunds sn Blauer See D Blondesddsl p Bohdo Comid Bon app*
Bottom-Dolar
Компания Alfreds Putter Ana TrujiBo E Antonio More Around the H Berglunds sn Blauer See D Blondesddsl p Bohdo Comid Bon app*
Bottom-Dolar
ФИО
Marla Anders Ana Truilo Antorto More Thomas Hard
Christina Berg Hanna Moos
Fred^tique Ct Martin Somm Laurence Lett Elizabeth Line
ФИО
Marla Anders Ana Truilo Antorto More Thomas Hard
Christina Berg Hanna Moos
Fred^tique Ct Martin Somm Laurence Lett Elizabeth Line
Должность Sales Represe Owner
Sales Represe Order Admire Sales Represe Marketrig Ma Owner Owner Accounting M
Должность Sales Represe Owner
Sales Represe Order Admire Sales Represe Marketrig Ma Owner Owner Accounting M
Адрес
Obere Str. 57 Avda. de la C Mataderos 2 120 Hanover Bet guvsvager Forster str. 57 24, place Kle С/ Araqui, 67 12, rue des В 23 Tsawassen
Адрес
Obere Str. 57 Avda. de la C Mataderos 2 120 Hanover Bet guvsvager Forster str. 57 24, place Kle С/ Araqui, 67 12, rue des В 23 Tsawassen
Город*|
Berk I
Mexico D.F.
Mexico D.F.
London
LuleS
Mannheim
Strasbourg Madrid
Mar seile
Город*|
Berk I
Mexico D.F.
Mexico D.F.
London
LuleS
Mannheim
Strasbourg Madrid
Mar seile
Clear Results
Рис. 1.32. Окно предварительного просмотра данных объекта DataAdapter
Результаты работы команды SelectCommand будут показаны в области Results. Если адаптер получает данные больше чем от одной таблицы источника данных (так может произойти при вызове хранимой процедуры), то в списке таблиц будет несколько имен таблиц. Вы можете выбрать необходимую таблицу, вызвав этим ее содержимое для предварительного просмотра. Обратите внимание, на рис. 1.32 колонки таблицы, полученные от адаптера данных, имеют русские названия, несмотря на то, что мы не изменяли их в исходной таблице базы данных. Это результаты нашей работы, проделанной при конфигурирования свойства TableMappings.
Повторите эти действия для других адаптеров данных или с другими значениями параметра. По умолчанию, каждый новый результат выборки добавляется к предыдущему. Чтобы очистить данные в окне предварительного просмотра данных щелкните на кнопку Clear Results.
После общего знакомства с ADO.NET в следующей главе мы приступим к работе с основным объектом — DataSet.
ГЛАВА 2
Наборы данных DataSet
В прошлой главе мы познакомились с ADO.NET и его отличиями от обычного ADO. Основа возможностей ADO.NET и его специфика заключены в создании отсоединенных наборов данных и работе с ними.
Из материалов данной главы вы узнаете:
O что такое отсоединенный набор данных — объект DataSet;
O как в Visual Studio .NET выполняется обновление набора данных;
O как изменения, сделанные пользователем в наборе данных, передаются источнику данных;
И начнем мы с ответа на вопрос: "Что такое объект DataSet?"
Отсоединенный набор данных
Наборы данных DataSet -- это своеобразная копия (вырезка) основного хранилища информации, которая перемещена на компьютер пользователя и существует в отрыве от основной базы данных. Структура набора данных полностью повторяет структуру основного хранилища: набора таблиц, записей и колонок со всеми иерархическими связями и ограничениями.
Примечание
Набор данных DataSet существует в отрыве от основной базы данных. Такое решение не всегда оптимально при работе с данными, особенно для Web- приложений, когда нет необходимости в модификации записей.
Вы можете создавать и управлять наборами данных, используя следующие элементы (пространство имен) .NET Framework (рис. 2.1).
Рис. 2.1. Пространство имен для работы с данными .NET Framework
Основные элементы объекта DataSet представлены входящими в него объектами, наборами свойств и коллекций.
O Класс DataSet включает коллекцию таблиц DataTabie и коллекцию реляционных связей между таблицами DataRelation.
O Класс DataTabie включает коллекцию строк таблицы, коллекцию колонок с данными и коллекцию реляционных отношений ChidRelations и ParentRelations.
O Класс DataRow включает свойство Rowstate, значения которого указывают, было ли изменение данных в строке таблицы после загрузки данных из основного хранилища. Возможные состояния для RowState: Deleted, Modified, New И Unchanged.
Объект DataSet, схемы и XML
В ADO.NET DataSet — это набор данных (реляционных данных), которые могут быть представлены в формате XML. В Visual Studio и в .NET Framework XML является базовым форматом для хранения и передачи данных всех видов. Наборы данных очень близки к XML. Приведем несколько аргументов.
O Структура DataSet — таблицы, столбцы, отношения между таблицами и ограничения могут быть определены в XML-схеме. XML-схема — формат на основе стандартов W3C (World Wide Web Consortium) для описания (задания) структуры данных. Объект DataSet может читать и записывать схемы, которые содержат структурную информацию, используя
методыReadXmlSchemaиWriteXmlSchema.Если схема не задана, набор данных может вывести ее (через методInferXmlSchema)на основе данных XML-документа.
O Вы можете сгенерировать класс DataSet, который будет содержать схему, определяющую структуру данных (таких как таблицы и столбцы) как элементы класса.
O Вы можете прочитать данные из XML-документа в DataSet, используя его метод ReadXML, или вывести данные из DataSet в XML-документ, используя его методWriteXML. Поскольку XML — стандартный формат обмена данными между различными приложениями, то это обеспечивает возможность загрузки данных в DataSet из XML-файла, сформированного другим приложением. Точно так же DataSet может вывести данные в виде XML-документа, который может быть переслан другому приложению или просто сохранен в данном стандартном формате.
О Вы можете создавать XML-представления (объект XMLDataDocument) в виде набора данных, а затем просматривать и изменять данные, используя любые методы объекта DataSet или методы XML.
Типизированные и нетипизированные объекты DataSet
Наборы данных DataSet могут быть типизированными и нетипизирован- ными. Типизированный DataSet — набор данных, который получен из базового класса DataSet с использованием информации из XML-схемы (xsd- файл) для генерирования этого нового класса. Информация из схемы (таблицы, столбцы и так далее) сгенерирована и откомпилирована в новый класс DataSet как набор объектов и свойств, присущих базовому классу.
Поскольку типизированный класс DataSet наследовался от основного класса DataSet, то он имеет все функциональные возможности основного класса и может использовать его методы.
Нетипизированный объект DataSet, напротив, не имеет никакой соответствующей встроенной схемы. Он, как и типизированный DataSet, содержит таблицы, столбцы и так далее — но те представлены только как коллекции. Однако, после ручного создания таблиц и других элементов данных в нети- пизированном DataSet, вы можете экспортировать структуру набора данных как схему, используя метод WriteXmlSchema.
Вы можете использовать любой тип набора данных в ваших приложениях. Однако Visual Studio имеет большой набор инструментов, поддерживающих типизированные наборы данных, которые делает работу с DataSet проще и позволяют допускать меньше ошибок.
Отличия типизированных и нетипизированных объектов DataSet
Данные для типизированного DataSet имеют те же типы, которые заданы в таблицах и столбцах базового класса. Например, если вы работаете с типизированным набором данных, вы можете ссылаться на столбец, используя следующий код (листинг 2.1) — получение значения колонки CustomerId из первой строки таблицы customers.
| Листинг 2.1
' Visual Basic
Dim s As String
s=dsCustomersOrders1.Customers(0).CustomerID
// C#
string s;
s=dsCustomersOrders1.Customers[0].CustomerID;
В следующем коде (листинг 2.2) выполняются те же действия при работе с нетипизированным набором данных:
i Листинг 2.2
' Visual Basic
Dim s As String
s = ь
CType(dsCustomersOrders1.Tables("Customers").Rows(0).Item("CustomerId"),^ String)
// C#
string s=(string) ъdsCustomersOr-
ders1 .Tables ["Customers"] .Rows[0]["CustomerID"];
Типизированный доступ является не только более легким и удобным для чтения, но и полностью поддерживается IntelliSense в редакторе кода Visual Studio. С таким кодом работать проще, синтаксис типизированного набора данных проверяется во время компиляции, что сокращает возможность появления ошибок при присвоении значений элементам набора данных. Обращение к таблицам и столбцы в типизированном наборе данных при выполнении приложения происходит быстрее, потому что типы данных определены уже во время компиляции приложения.
Несмотря на то, что типизированные наборы данных имеют много преимуществ, есть некоторые обстоятельства, при которых набор данных без контроля типов является более полезным (например, когда отсутствует схема набора данных). Так может быть в тех случаях, когда ваше приложение взаимодействует с компонентом, который возвращает набор данных с неизвестной заранее структурой. Аналогичная ситуация возникает, когда вы работаете с данными, которые не имеют статичной, предсказуемой структуры. Тогда нерационально использовать типизированный набор данных, потому что вам придется каждый раз перестраивать типизированный набор данных при изменении структуры данных первоисточника.
Более важно то, что во многих ситуациях вы имеете возможность создавать набор данных динамически, не имея схему данных. Тогда случае DataSet — просто некая структура, в которой вы можете временно сохранять информацию до тех пор, пока данные могут быть представлены в ре- ляционномвиде.
Чувствительность к регистру в DataSet
В пределах набора данных, ссылки на имена таблиц и столбцов (по умолчанию) пишутся без учета регистра символов. Например, к таблице в наборе данных можно обратиться по имени customers или customers, что будет понято равнозначно. Это соответствует соглашениям об именах во многих базах данных, включая SQL-сервер, где в именах элементов данных не учитывается регистр букв.
Примечание
В отличие от наборов данных Dataset, в XML-документах учитывается регистр букв, так что в схемах имена элементов данных определенны с учетом регистра. Например, описание схемы позволяет определить две разные таблицы с именами "Customers" и "customers". Это может привести к некоторым противоречиям имен, когда схема используется для генерации класса DataSet.
Фактор того, как данные интерпретируются в пределах набора данных (с учетом или без учета регистра символов) во многих случаях необходимо обязательно учитывать. Например, если вы фильтруете данные в таблице DataSet, критерий поиска может возвратить совершенно разные результаты в зависимости от того, учли ли вы регистр в операторе сравнения или нет. Вы можете управлять чувствительностью к регистру букв в операторах фильтрации, поиска и сортировки, устанавливая нужное значение свойства CaseSensitive набора данных. Можно назначить это свойство индивидуально для каждой таблицы.
Заполнение наборов данных
Набор данных DataSet — пустой контейнер, который нуждается в заполнении данными. Когда происходит заполнение данными объекта DataSet, этот процесс контролируется различными событиями. Например, делается проверка различных ограничений, соблюдения условий целостности данных и так далее.
Набор данных может быть заполнен несколькими способами.
O Вызов метода Fill адаптера данных. Адаптер данных выполняет SQL- запрос или хранимую процедуру и заполняет выбранными данными таблицу объекта DataSet. Если в наборе данных содержится несколько таблиц, то каждая из них имеет свой адаптер данных. В этом случае необходимо вызвать метод пи каждого адаптера данных и последовательно заполнить данными все таблицы.
O Ручное заполнение таблицы в наборе данных, создание объектов DataRow и добавка их к коллекции Rows таблицы. Так можно сделать только во время выполнения программы, поскольку вы не имеете возможности задать коллекцию ROWS во времени разработки приложения.
O Копирование содержания другого набора данных. Такой способ может быть полезен, если ваше приложение получает наборы данных из различных источников (например, из XML Web-services), но должно объединить их в один набор данных.
Указатель текущей записи и перемещение по набору данных
Объект DataSet -- полностью разъединенный контейнер, оторванный от источника данных (в отличие от ADO Recordset). В связи с этим он не нуждается в поддержке понятия текущая запись. Наоборот, все записи в наборе данных доступны.
Поскольку понятие текущей записи отсутствует, то нет никакого свойства, которое указывало бы на текущую запись и нет никаких методов или свойств для того, чтобы двигаться от одной записи к другой. Это несколько сбивает с толку программистов, привыкших работать с ADO, где поддерживается указатель текущей записи и есть методы навигации по записям. В DataSet вы можете обратиться к любой таблице в наборе данных как к объекту (по имени таблицы или по ее номеру в коллекции таблиц). Каждая таблица имеет коллекцию строк — вы можете обрабатывать строки подобно тому, как обрабатываются элементы любой коллекции, обращаясь к строкам через их индекс в коллекции.
Примечание
Если вы связываете DataSet с элементом отображения данных (например, с DataGrid), то можно использовать свойства и методы этого элемента для доступа к записям (строкам) таблицы.
Связанные таблицы и объект DataRelation
Если в наборе данных имеется несколько таблиц, то они могут быть связаны между собой. Объект DataSet не имеет никаких средств для задания реляционных отношений, это можно сделать с помощью объектов DataRelation, которые и описывают отношения между таблицами в наборе данных. Объекты DataRelation можно использовать в приложении, чтобы выбрать связанные дочерние записи на основе родительской или найти родительские записи по известным дочерним.
Например, в базе данных Northwind, которая поставляется вместе с SQL Server, такими связанными таблицами являются Customers (Клиенты) и Orders (Заказы). Таблица Customers могла бы содержать следующее записи, как указано в табл. 2.1.
Таблица 2.1. Содержимое записей таблицы Customers
CustomerID
CompanyName
City
ALFKI
Alfreds Futterkiste
Berlin
ANTON
Antonio Moreno Taquerias
Mexico D.F.
AROUT
Around the Horn
London
Набор данных может также содержать другую таблицу orders с информацией о заказах каждого клиента. Таблица Orders содержит столбец CustomerID (идентификатор клиента) как внешний ключ. Таблица orders может содержать, например, записи, указанные в табл. 2.2.
Таблица 2.2. Содержимое записей таблицы Orders
OrderId ICustomerIDOrderDate
10692
ALFKI
10/03/1997
10702
ALFKI
10/13/1997
10365
ANTON
11/27/1996
10507
ANTON
4/15/1997
Поскольку каждый клиент может иметь не один заказ, то в этом случае между клиентами и заказами существует отношение "один ко многим". Например, в вышеприведенных таблицах, клиент ALFKI имеет два заказа. Если, например, в базе данных эти таблицы помещаются в объект DataSet с именем ds, то связать их в программном коде можно следующим образом (листинг 2.3).
SqlDataAdapter1.Fill(ds, "Customers")
SqlDataAdapter2.Fill (ds, "Orders")
ds.Relations.Add("Заказы", ds.Tables("customers").Columns("CustomerID"),ъ ds.Tables("Orders").Columns("CustomerID"))
Вы можете использовать объект DataRelation, чтобы получить связанные записи от дочерней или родительской таблицы. Например, по родительской записи клиента ANTON, вы можете получить коллекцию записей, описывающих его заказы. Точно так же, если вы имеете дочернюю запись заказа номер 10507, можно использовать объект DataRelation, чтобы получить родительскую запись этого заказа (ANTON).
Ограничения в DataSet
Как и большинство баз данных, наборы данных DataSet поддерживают ограничения, которые гарантируют целостность данных. Ограничения — это правила, которые применяются, когда записи в таблице добавляются, модифицируются или удаляются. Можно определить два типа ограничений.
O Уникальное ограничение. Данное правило, которое проверяет, является ли новое значение в столбце таблицы уникальным.
О Ограничение внешнего ключа. Это правило, которое определяет, что нужно сделать с записями в дочерней таблице, когда записи родительской таблицы модифицированы или удалены.
Ограничения в наборе данных реализованы как объекты UniqueConstraint или ForeignKeyConstraint и существуют в виде коллекций ограничений таблицы. Уникальное ограничение может также быть установлено путем установки значения свойства столбца unique равным true.
Сам набор данных поддерживает булево свойство EnforceConstraints, которое определяет, будут ли ограничения предписаны объекту Dataset или нет. По умолчанию данное свойство имеет значение true. Однако в некоторых случаях есть смысл временно отключать такое ограничение. Например, когда вы изменяете содержимое записи таким образом, что это временно
вызовет недопустимое состояние (дублирование ключа). После завершения корректировки записи и приведения ключевого поля к корректному состоянию можно вновь установить ограничение.
В Visual Studio вы создаете ограничения неявно, когда определяете сам набор данных. Например, добавляя первичный ключ, вы неявно создаете уникальное ограничение для ключевого столбца. Вы можете определить уникальное ограничение для других столбцов, присваивая их свойству Unique значение true. Или, создавая объект DataRelation в наборе данных, вы создаете ограничения внешнего ключа.
Обновление DataSet и базы данных
Когда в записях набора данных сделаны изменения, они должны быть возвращены в базу данных. Чтобы передать все изменения, сделанные в объекте DataSet в исходную базу данных, необходимо вызвать метод update адаптера данных, который является связующим звеном между набором данных и источником данных.
Класс DataRow обычно манипулирует индивидуальными записями, используя свойство RowState, значение которого указывает, была ли запись изменена и каким образом — с того момента, когда таблица была загружена из базы данных. Это свойство может иметь следующие значения Deleted, Modified, New и Unchanged. Метод Update проверяет значение свойства RowState, чтобы определить, какая запись требует обновления в базе данных, и какая команда (add, edit, delete) должна быть вызвана на выполнение,
Инструменты Visual Studio
для создания объектов DataSet
В Visual Studio имеется 2 основных способа создания наборов данных.
O В окне дизайнера (Component Designer) путем перетаскивания элементов данных на форму или компонент из окна Toolbox или Server Explorer. Visual Studio может создать объекты, в которых вы нуждаетесь для вашего набора данных, включая схему, основанную на структуре источника данных. Когда вы создаете форму, Component Designer появляется в нижней части окна вашего проекта. Этот метод позволяет создавать типизированные и нетипизированные наборы данных.
Q В XML-дизайнере (XML Designer), который позволяет создать схему и получить на ее основе типизированный набор данных.
Также имеется возможность создать набор данных динамически (в программном коде). В таком случае будет создан нетипизированный набор данных.
Примечание j
Когда приложение, которое содержит компоненты доступа данных Visual Studio, устанавливается на компьютер конечного пользователя, необходимо удостовериться, что на этом компьютере установлен компонент Microsoft Data Access Components (MDAC) версии 2.6 и выше.
Последовательность создания
типизированного объекта DataSet
Когда создается типизированный набор данных, фактически исполняется последовательность следующих шагов.
Получение XML-схемы (xsd-файл). Схема может быть добавлена к проекту следующими способами:
на основе структуры источника данных. Если используется Component Designer для добавления адаптера данных к вашей форме или компоненту, то DataAdapter считывает структуру исходных данных и на ее основе формирует xsd-файл;
создание схемы вручную с использованием XML-дизайнера (XML Designer);
создание ссылки на XML Web-service или другой компонент, который возвращает набор данных. Используя эту ссылку, Visual Studio создает копию схемы для разрабатываемого приложения.
Создание класса DataSet. На этом шаге Visual Studio создает класс набора данных на основе базового класса DataSet из пространства имен System. Data. На основе информации, полученной из схемы данных, формируется типизированный набор данных, который состоит из набора таблиц и набора колонок каждой таблицы.
В большинстве случаях Visual Studio создает такой класс набора данных автоматически, когда схема данных добавляется к проекту.
Создание экземпляра класса набора данных, сформированного в шаге 2, который будет непосредственно использоваться на форме или компоненте.
Когда вы работаете с набором данных в вашем приложении, вы фактически работаете с экземпляром класса набора данных, созданным на шаге 3.
Использование Component Designer
Обычно разработчик использует Component Designer когда необходимо, чтобы Visual Studio сформировала схему и типизированный класс набора данных для разрабатываемого приложения. В Component Designer вы добавляете
один или более адаптеров данных к вашей форме или компоненте. Адаптер данных передает информацию в набор данных о его структуре через метод FillSchema. После этого набор данных может записать свою структуру во внешний XML-файл проекта (xsd-файл) и на его основе сгенерировать экземпляр класса типизированного набора данных, который и будет добавлен к вашей форме или компоненту.
Исходя из вышесказанного, можно сформулировать, что Component Designer создает набор данных косвенным способом. Вы явно не определяете перечень таблиц и колонок в наборе данных, они задаются автоматически во время создания адаптера данных. Вы можете и явно задать нужную структуру данных, изменяя SQL-запросы или хранимые процедуры, которые адаптер использует для обмена между DataSet и источником данных. Можно также использовать свойство адаптера данных TableMappings для определения перечня колонок, которые необходимо включить в набор данных, и задания их имен.
После конфигурирования адаптера данных разработчик (на основе адаптера данных) может создать объект DataSet. Если вы внесли какие-либо изменения в адаптер данных после того, как объект DataSet уже был создан, последний нужно заново пересоздать, чтобы отразить в нем все ваши изменения.
Использование Component Designer имеет ряд недостатков.
Q Первоначально разработчик не имеет никакого прямого контроля над процессом формирования схемы данных. Управлять определением структуры набора данных можно только после конфигурирования адаптера данных, на основе которого Visual Studio формирует схему. После формирования схемы, разработчик может ее редактировать с использованием XML Designer.
Q Разработчик должен вручную пересоздать схему данных (и соответствующий этому классу файл) после любых изменений в адаптере данных. Например, если вы изменили SQL-запрос, заполняющий набор данных, то необходимо не забыть изменить и схему набора данных.
Q Есть некоторые функции набора данных, которыми нельзя воспользоваться при использовании Component Designer, например, определение реляционных связей с помощью объекта DataRelation. В этом случае необходимо задействовать XML Designer.
Использование XML Designer
Использование XML Designer оправдано тогда, когда есть необходимость более точно управлять структурой создаваемой схемы данных, или если нужно сформировать схему при отсутствии источника данных. Есть два варианта использования XML-дизайнера для создания схемы.
Q Перенос выделенных элементов базы данных (например, имен колонок) из окна Server Explorer на окно дизайнера формы. При этом формируется схема на основе имеющейся структуры базы данных, из которой вы черпаете только те данные, которые необходимы для работы данного приложения.
Q Создание файла схемы вручную. Такой вариант полезен тогда, когда разработка схемы делается независимо от внешнего источника данных.
В обоих случаях будет создан экземпляр класса типизированного объекта DataSet, на основе сформированной схемы, который вы будете использовать на форме или компоненте.
Компонент XML Designer позволяет вам добавлять, удалять и изменять элементы схемы данных. Кроме того, с его помощью можно задействовать такие функции, как установление реляционных связей между таблицами (добавление объектов DataRelation), которые недоступны в Component Designer,
С помощью XML-дизайнера по сути дела редактируется xsd-файл. Достаточно часто в разрабатываемых проектах используются классы нетипизиро- ванных наборов данных, основанных на xsd-файле. Если вы записываете изменения в xsd-схемы данных, то соответствующий файл класса изменяется автоматически, чтобы отразить внесенные в схему изменения. Таким образом, Visual Studio постоянно поддерживает xsd-файл и соответствующий файл класса в синхронизированном состоянии. Вы можете выключить эту поддержку, если для редактируемого файла схемы нет соответствующего файла класса.
Недостатки использования XML Designer:
О как инструмент XML-дизайнер имеет достаточно низкий уровень интеграции с другими инструментами Visual Studio;
Q файл xsd не имеет никакой связи с внешним источником данных. Например, если вы используете XML-дизайнер, чтобы изменить схему набора данных, необходимо обязательно внести эти изменения в адаптеры данных, которые взаимодействуют с набором данных DataSet.
Создание типизированных объектов DataSet
с использованием Component Designer
Когда в приложении требуется создать набор данных, то можно использовать Component Designer для того, чтобы определить схему набора данных и файл соответствующего класса. После этого можно добавить экземпляр класса DataSet к форме или компоненту, с которыми вы работаете.
При редактировании формы Component Designer расположен в нижней части окна дизайнера формы. Эта своеобразное окно открывается автоматически, как только вы добавляете компоненты работы с данными на форму. На ней располагаются все объекты, связанные с DataSet. На данной вкладке можно мышью выделить любой объект, чтобы затем в окне Properties определить его свойства.
Для создания объекта DataSet в Component Designer выполните следующие действия.
Добавьте один или более адаптеров данных (DataAdapter) на форму или компонент.
В Component Designer выделите один из адаптеров данных, который является связующим звеном между источником данных и объектом DataSet (рис. 2.2).
Star t Pace Forml.vb [Design]* ]
.^ SqlDataAdapterl^ SqlConoectionl
Рис. 2.2. Объекты доступа к данным в окне Component Designer
Как правило, каждый адаптер данных связан с единственной таблицей источника (базы) данных. Поэтому, чтобы создать набор данных, содержащий несколько таблиц, необходимо выделить все адаптеры данных для таблиц, которые вы хотите поместить в DataSet.
Примечание
Добавление нескольких таблиц к набору данных не создает автоматически реляционные отношения между ними, это необходимо сделать вручную после создания набора данных.
В меню Data выберите пункт Generate Dataset.
Появится диалоговое окно Generate DataSet (рис. 2.3).
Рис. 2.З. Диалоговое окно Generate DataSet
Выберите переключатель New и затем определите имя для создаваемого набора данных. Если вы хотите добавить набор данных к вашей форме или компоненту, установите флажок Add an instance of this DataSet to the designer.
После этого Visual Studio, используя информацию адаптеров данных, создаст файл с XML-схемой данных (xsd), который добавиться к проекту. Для него будет взято имя, которое вы определили для DataSet. Кроме того, Visual Studio создаст новый файл класса набора данных, основанный на XML схеме.
Примечание
Новый файл класса набора данных будет виден в окне Solution Explorer, только если в в верхней панели окна будет нажата кнопка Show All Files.
Если вы указали, что хотите добавить экземпляр DataSet к форме или компоненту, то он будет помещен на форму, а к его имени будет добавлен числовой суффикс. Например, если вы назвали набор данных dsAuthors, то экземпляр этого объекта на форме получит имя dsAuthorsl.
Примечание
По умолчанию объекту "набор данных" присваивается имя DataSet1. Если вы не изменили его, то экземпляр этого объекта при помещении на форму получит имя DataSetll (из-за числового суффикса, который добавляется автоматически).
После добавления набора данных к форме или компоненту он не содержит никаких данных (пустой контейнер для данных). Для заполнения его данными необходимо написать программный код. Обычно для этого используется метод Fill адаптеров данных.
Если вы хотите редактировать информацию в наборе данных DataSet и возвращать эти изменения в источник (базу) данных, то нужно добавить соответствующий программный код к разрабатываемой форме или компоненту.
Создание вычисляемых колонок объекта DataSet
Как и в некоторых базах данных, таблицы в наборе данных могут содержать колонки, значения которых получаются расчетным путем, а не считыванием из источника данных. Например, в записях элементов заказа имеет смысл вычислять колонку "Стоимость" (произведение количества на иену) вместо того, чтобы постоянно хранить этот показатель. Вычисляемые колонки могут также содержаться в дочерних записях. Для создания вычисляемых колонок используются выражения (expressions).
Синтаксис выражений состоит из стандартных арифметических операций, булевых и строковых операторов, а также констант. Вы можете сослаться на значения некоторых данных, используя имена колонок и таблиц (как в SQL-запросах), включать агрегирующие функции типа count.
Например, выражение для колонки "Стоимость", рассчитываемой на основании значений колонок цена (UnitPrice) и количество (Quantity) текущей записи может быть следующим:
UnitPrice * Quantity
Чтобы обратиться к колонкам в дочерних таблицах, необходимо использовать зарезервированное слово Child, перед именем колонки. Например, следующее выражение возвращает среднее значение колонки цены (Prise) во всех записях связанной дочерней таблицы:
Avg(Child.Price)
Вычисляемые колонки в типизированных объектах DataSet
Вычисляемые колонки для типизированных наборов данных можно создавать в XML Designer.
Для создания вычисляемых колонок в типизированном наборе данных необходимо выполнить следующие шаги.
Если схема еще не открыта в XML-дизайнере, щелкните два раза на XML-схеме (xsd-файл) в Solution Explorer. Откроется окно XML Designer (рис. 2.4).
В сетке (grid), представляющей таблицу, с которой вы хотите работать, добавьте новую колонку, выполняя следующие шаги:
в нижней первой пустой строке в первой колонке таблицы выберите значение Element из выпадающего списка;
в следующем столбце той же строки введите имя колонки;
в последнем столбце выберите соответствующий тип данных для результатов вычисления.
На рис. 2.5 представлена добавленная колонка, в которой будет вычисляться стоимость товара.
:"jrt'■>;■. ] P'tml .vr |Гтшзп)* DataSetl.xsd* ]:"jrt'■>;■. ] P'tml .vr |Гтшзп)* DataSetl.xsd* ]■ • P>y* ' Fon'. 'h [ I?»- "k^t * DataSet 1 .xsd* |■ • P>y* ' Fon'. 'h [ I?»- "k^t * DataSet 1 .xsd* |
:"jrt'■>;■. ] P'tml .vr |Гтшзп)* DataSetl.xsd* ]
:"jrt'■>;■. ] P'tml .vr |Гтшзп)* DataSetl.xsd* ]
■ • P>y* ' Fon'. 'h [ I?»- "k^t * DataSet 1 .xsd* |
■ • P>y* ' Fon'. 'h [ I?»- "k^t * DataSet 1 .xsd* |
С 1> Je^ietak4l OrderlDЧЕ Product®E ЦенаE КогичестеоE СкидкаС 1> Je^ietak4l OrderlDЧЕ Product®E ЦенаE КогичестеоE СкидкаTordeToetaSs^ int ir* decimal short floatTordeToetaSs^ int ir* decimal short floatРис. 2.4. Окно XML DesignerРис. 2.4. Окно XML Designerz™^.„,„„,UHc-f der Details ((Order Details)z™^.„,„„,UHc-f der Details ((Order Details)Г W. OrderlD \ 9E ProductlDГ W. OrderlD \ 9E ProductlD: Г Цена: Г ЦенаКоличествоКоличествоEEEEСкидкаСтоимостьСкидкаСтоимостьInt mt decimal short float decimalInt mt decimal short float decimalРис. 2.5. Вычисляемая колонкав окне XML DesignerРис. 2.5. Вычисляемая колонкав окне XML Designer
С 1> Je^ietak
4l OrderlD
ЧЕ Product®
E Цена
E Когичестео
E Скидка
С 1> Je^ietak
4l OrderlD
ЧЕ Product®
E Цена
E Когичестео
E Скидка
TordeToetaSs^ int ir* decimal short float
TordeToetaSs^ int ir* decimal short float
Рис. 2.4. Окно XML Designer
Рис. 2.4. Окно XML Designer
z™^.„,„„,
UHc-f der Details ((Order Details)
z™^.„,„„,
UHc-f der Details ((Order Details)
Г W. OrderlD \ 9E ProductlD
Г W. OrderlD \ 9E ProductlD
: Г Цена
: Г Цена
Количество
Количество
E
E
E
E
Скидка
Стоимость
Скидка
Стоимость
Int mt decimal short float decimal
Int mt decimal short float decimal
Рис. 2.5. Вычисляемая колонкав окне XML Designer
Рис. 2.5. Вычисляемая колонкав окне XML Designer
Оставаясь на добавленной колонке в сетке таблицы, перейдите в окно Properties и найдите там свойство Expression. В данной строке введите значение вычисляемого выражения (рис. 2.6).
Рис. 2.6. Вычисляемое выражение в окне PropertiesРис. 2.6. Вычисляемое выражение в окне Properties
Рис. 2.6. Вычисляемое выражение в окне Properties
Рис. 2.6. Вычисляемое выражение в окне Properties
Добавление таблиц в сформированный объект DataSet
Иногда возникает необходимость добавить таблицу к набору данных, который уже создан. Наиболее простой путь заключается в удалении набора данных и создание его заново, при этом в создаваемый набор будет автоматически включена новая таблица. Однако в этом случае могут быть потеряны некоторые объекты, которые разработчик вручную добавлял к набору данных после его автоматического создания (например, ограничения и объекты связывания таблиц DataRelation).
Вы можете добавить новую таблицу к уже созданному объекту DataSet двумя способами.
О С помощью Component Designer. Это самое простое решение, которое позволяет перетаскивать элементы на форму или компонент и затем восстанавливать изменяемый набор данных.
Q С помощью XML Designer (изменение схемы набора данных). Эта стратегия полезна, если вы имеете навыки работы с XML-дизайнером и у вас нет открытой формы или компонента. Добавление таблицы в этом случае подобно формированию схемы вручную.
Добавление таблицы в существующий объект DataSet с использованием Component Designer состоит из следующих шагов.
На форму или компонент, с которой вы работаете, добавляется новый адаптер данных, который ссылается на добавляемую таблицу источника данных.
Выделяется мышью добавленный адаптер данных, затем в меню Data выбирается пункт Generate Dataset.
Появится диалоговое окно Generate Dataset.
Переключатель Choose a dataset устанавливается в положение Existing и затем выбирается имя набора данных, к которому будет добавляться таблица.
В области Choose which table(s) to add to the dataset, устанавливаются флажки напротив имен всех таблиц, которые хочется добавить к набору данных. Список включает таблицы всех доступных адаптеров данных (рис. 2.7).
Если нужно поместить экземпляр изменяемого набора данных на форму или компонент, устанавливается флажок Add this dataset to the designer.
Нажатие кнопки OK создает и обновляет объект DataSet.
Рис. 2.7. Список таблиц в диалоговом окне Generate DatasetРис. 2.7. Список таблиц в диалоговом окне Generate Dataset
Рис. 2.7. Список таблиц в диалоговом окне Generate Dataset
Рис. 2.7. Список таблиц в диалоговом окне Generate Dataset
Информация о новой таблице добавится к схеме набора данных и к файлу описания класса набора данных. Существующая информация об объекте DataSet остается неповрежденной (существовавшие таблицы, ограничения и отношения). Схема обновленного набора данных представлена на рис. 2.8.
VT Customer® string E CompanyNa string F ContactNem stringVT Customer® string E CompanyNa string F ContactNem stringE ContactTitle stringE Address strngE ContactTitle stringE Address strngJ •;• Яые I K.-» I .! Гсч»-»)* DataSet lj«d |
VT Customer® string E CompanyNa string F ContactNem string
VT Customer® string E CompanyNa string F ContactNem string
E ContactTitle string
E Address strng
E ContactTitle string
E Address strng
^C OrderTO mt t Customerto stmg E Employee® ht E Order DatedateTrne
E RequtredDat dateTrne
Рис. 2.8. Таблицы объекта DataSet в окне XML Designer
Добавление существующего типизированного объекта DataSet к форме или компоненту
В ходе работы над созданием приложения возникает необходимость добавления типизированных наборов данных к форме или компоненту, их связывания с компонентами отображения данных. Когда вы добавляете набор
данных к форме, вы фактически создаете экземпляр класса типизированного набора данных. Сам класс типизированного набора данных уже должен существовать. Он может иметь несколько источников происхождения:
G вы сгенерировали его в другой форме или компоненте вашего проекта;
Q вы создали его вручную в XML Designer;
Q вы создали ссылку на XML Web-service другого компонента, который возвращает набор данных.
Вы можете добавить к форме или компоненту также набор данных без контроля типов, но делается это несколько иначе, чем добавление экземпляра класса типизированного набора данных.
Для добавления существующего объекта DataSet к форме или компоненту проделайте следующее.
Откройте форму или компонент в окне дизайнера проекта.
Из вкладки Data окна Toolbox перетащите объект DataSet в окно дизайнера проекта.
Откроется диалоговое окно Add Dataset (рис. 2.9).
Рис. 2.9. Диалоговое окно Add Dataset
Установите переключатель Typed Dataset и затем в раскрывающемся списке выберите тот набор данных, который вы хотите использовать и нажмите кнопку ОК.
Раскрывающийся список заполнится именами всех типизированных классов набора данных вашего проекта.
Примечание
Если вы добавили XML Web-service или компонент, но не видите схему набора данных в Solution Explorer, раскройте узел reference. Если вы и после этого не видите схему, перепроверьте, что XML Web-service или компонент возвращают типизированный набор данных.
Экземпляр класса типизированного набора данных добавится к форме или компоненту.
Добавьте код к форме или компоненту, который позволит заполнить набор данных. Обычно для этих целей вызывается метод пи адаптера данных.
Следующий пример (листинг 2.4) показывает, как можно заполнить таблицу Customers (Клиенты) в наборе данных dsCustomersOrders (экземпляр класса которого имеет имя dsCustomersOrders).
Листинг 2.4
' Visual Basic
OleDbDataAdapter1.Fill(dsCustomersOrders1, "Customers")
// C#
OleDbDataAdapter!.Fill(dsCustomersOrders1, "Customers");
Если объект DataSet представляет информацию, возвращаемую XML Web-service или компонентом, вы должны загрузить его, вызвав метод, который возвращает данные. В этом случае необходимо поместить данные, возвращаемые из XML Web-service или компоненты в набор данных вашей формы. Пример из листинга 2.5 показывает, как создается экземпляр класса XML Web-service, вызывается его метод с именем GetCustomersDataset, и полученные данные загружаются в набор данных С именем dsCustomers1.
Листинг 2.5
' Visual Basic
Dim ws1 As New MyServer.CService1()
dsCustomers1.Merge(ws1.GetCustomersDataset())
// C#
MyServer.CService1 ws1=new MyServer.CService1()
dsCustomers1.Merge(ws1.GetCustomersDataset());
Если логикой вашего приложения требуется возвращение корректировок пользователя от объекта DataSet к исходной базе данных, добавьте к приложению код обновления источника данных.
Если набор данных заполнялся через адаптер данных, то можно назвать его метод Update.
Добавление объектов DataSet без контроля типов данных к форме или компоненту
Набор данных без контроля типов — экземпляр класса DataSet, который вы создаете в форме или компоненте. В отличие от типизированного набора данных, набор данных без контроля типов является экземпляром класса, который сгенерирован без использования XML-схемы из xsd-файла. Как следствие, набор данных без контроля типов не имеет структуры, свойственной типизированным наборам данных. Вы создаете таблицы, столбцы, ограничения, объекты DataRelation самостоятельно во времени разработки приложения в окне Properties, в программном коде во время выполнения приложения, или с помощью адаптера данных во время заполнения данными объекта DataSet.
Примечание
Хотя набор данных без контроля типов основан на классе, который не имеет схемы, после его формирования можно экспортировать его структуру в файл схемы (с помощью метода WriteXmlSchema).
Ниже описана последовательность создания набора данных без контроля типов с использованием Component Designer в ходе разработки формы или компонента.
Создание набора данных без контроля типов во время разработки приложения.
Из вкладки Data окна Toolbox перетащите элемент DataSet на форму или компонент, с которым вы работаете.
Появится диалоговое окно Add Dataset (рис. 2.10).
Выберите Untyped Dataset и нажмите кнопку ОК.
Пустой набор данных добавится к форме или компоненту.
Если вы хотите дать набору данных новое имя, выделите его мышью, откройте окно Properties и отредактируйте следующие два свойства:
• Name — свойство устанавливает объекту имя, через которое будет осуществляться обращение к набору данных из программного кода;
DataSetName — если выполняется экспорт набора данных В XML-документ, то свойство устанавливает имя набора данных в документе. Установка этого свойства позволит избежать проблем, связанных с дублированием имен.
Рис. 2.10. Задание нетипизированного набора данных в диалоговом окне Add DataSet
Добавление таблиц и колонок
Вы можете использовать окно Properties, чтобы создать структуру набора данных без контроля типов. Набор данных включает свойство Tables, являющееся коллекцией объектов DataTable, которые будут содержаться в наборе данных. Каждая таблица в свою очередь поддерживает свойство Columns, которое является коллекцией объектовDataColumn. Для создания таблиц и столбцов можно использовать Collection Editor, который вызывается из окна Properties.
Примечание
Вы не можете создать реальные записи в наборе данных без контроля типов во время разработки приложения, это можно сделать только во время выполнения программы. Поэтому коллекция ROWS набора данных недоступна в окне Properties.•
Добавление таблиц и столбцов к набору данных.
В форме или компоненте выделите мышью набор данных и откройте окно свойств — Properties (рис. 2.11).
Рис. 2.11. Доступ к коллекции таблиц в окне свойств объекта DataSet
В свойстве Tables нажмите кнопку справа, чтобы открыть диалоговое окно Tables Collection Editor (рис. 2.12).
Рис, 2.12. Диалоговое окно Tables Collection Editor
Нажмите кнопку Add, чтобы создать новую таблицу. Если вы хотите переименовать таблицу, выберите ее и в правой области окна в сетке свойств переопределите значение свойства Name.
Примечание j
Имена всех таблиц во всех наборах данных в форме или компоненте используют одно и то же пространство имен. Поэтому, вы не можете использовать имя для таблицы в одном наборе данных, если оно уже задействовано в другом наборе данных.
Для добавления колонок к таблице выполните следующие шаги.
Удостоверьтесь, что таблица, с которой вы работаете, выбрана в списке Members, и затем в сетке Properties нажмите кнопку в свойстве Columns, чтобы вызвать диалоговое окно Columns Collection Editor (рис. 2.13);
Рис. 2.13. Диалоговое окно Columns Collection EditorРис. 2.13. Диалоговое окно Columns Collection Editor
Рис. 2.13. Диалоговое окно Columns Collection Editor
Рис. 2.13. Диалоговое окно Columns Collection Editor
Нажмите кнопку Add, чтобы создать новый столбец, и затем установите свойства нового столбца в сетке справа. Некоторые из свойств позволяют устанавливать ограничения для столбца (например, уникальное значение, непустое значение и т. п.). Типичные свойства, которые можно установить, приведены в табл. 2.3.
Таблица 2.3. Перечень свойств колонки таблицы нетипизированного набора данных
AllowDBNullAllowDBNullСвойстваОписание
AllowDBNull
AllowDBNull
Булево значение, указывающее, можно ли столбцу присваивать пустое значение (Null)
Таблица 2.3. (окончание)
Свойства
Описание
ColumnName
Имя столбца а коллекции таблиц Tables, которое указывает, как можно сослаться на столбец из программного кода
DataType
Тип данных .NET Framework, который будет предписан столбцу. Если вы импортируете или экспортируете информацию XML- документа в набор или из набора данных, то типы данных объекта DataSet будут автоматически преобразованы в типы данных схемы (например, System. String будет преобразована в xs:string и наоборот). Тип данных можно выбрать из раскрывающегося списка
Readonly
Булево значение, указывающее, может ли столбец быть изменен
Unique
Булево значение, указывающее уникальное ограничение на столбец. Это свойство всегда устанавливается равным true для колонки первичного ключа, но оно также может быть установлено для любого столбца
Name
Имя экземпляра столбца, используемого только во время разработки приложения
• Повторите последний шаг для каждого столбца, который вы хотите добавить к таблице (рис. 2.14);
Рис. 2.14. Колонки таблицы, созданные в диалоговом окне Columns Collection Editor
Когда вы закончите добавлять столбцы для текущей таблицы, нажмите кнопку ОК, чтобы закрыть диалоговое окно Columns Collection Editor.
Чтобы установить первичный ключ для таблицы, используйте раскрывающийся список в свойстве PrimaryKey.
В раскрывающемся списке установите флажок рядом с каждой частью первичного ключа.
После выбора одного или нескольких столбцов для первичного ключа вы можете раскрыть свойство PrimaryKey и установить дополнительные свойства для каждого столбца первичного ключа. Свойство unique автоматически устанавливается равным true для всех столбцов, которые являются частью первичного ключа.
Повторите шаги 3-5 для каждой таблицы, создавая нужный вам набор столбцов.
Вычисляемые колонки в нетипизированных объектах DataSet
Если используется нетипизированный набор данных, вы не можете использовать XML Designer для создания вычисляемых колонок, потому что как таковой схемы данных не существует (если она не была сгенерирована из набора данных методом WriteXmlSchema). Однако в этом случае можно создать вычисляемые колонки с помощью Component Designer.
Для создания вычисляемых колонок в нетипизированном наборе данных необходимо выполнить следующие шаги.
Выберите нетипизированный набор данных в форме или компоненте и откройте окно его свойств Properties.
Щелкните кнопку в свойстве Tables, при этом откроется диалоговое окно Tables Collection Editor.
В редакторе коллекции щелкните кнопкой на свойстве Columns, при этом откроется диалоговое окно Columns Collection Editor.
Щелкните кнопку Add для создания новой колонки.
Выберите новую колонку и в сетке свойств Properties, установите свойство ColumnName таким, каким вы хотите видеть имя колонки в программном коде.
Примечание
Вы также можете устанавливать имена колонок динамически во время выполнения приложения.
Выберите соответствующий тип данных для результатов вычисления.
Введите вычисляемое выражение как значение свойства Expression.
На рис. 2.15 представлено окно редактора коллекции колонок, в котором сформированы три колонки: Цена, Количество и Стоимость (Стоимость является вычисляемой колонкой).
Рис. 2.15. Вычисляемая колонка, созданная в диалоговом окне Columns Collection Editor
Добавление ограничений
Вы можете установить два типа ограничений в наборе данных.
Q Уникальность значения колонки. Данное ограничение проверяет, что любое новое значение в колонке являются для нее уникальным.
Q Ограничение первичного ключа. Данное ограничение определяет правила того, как будут обновлены связанные записи дочерней таблицы, когда изменяется значение в соответствующем столбце родительской таблицы.
Ниже описано добавление ограничения к нетипизированному набору данных во время разработки приложения.
В форме или компоненте мышью выделите набор данных и откройте окно его свойств Properties.
Щелкните кнопку в свойстве Tables для открытия диалогового окна Tables Collection Editor.
Выберите таблицу, к которой добавляется ограничение, и затем щелкните кнопку в свойстве Constraints для открытия диалогового окна Constraints Collection Editor (рис. 2.16).
Рис. 2.16. Диалоговое окно Constraints Collection Editor
Щелкните кнопку Add и затем выберите Unique Constraint или Foreign Key Constraint из выпадающего списка.
Появится одно из диалоговых окон Unique Constraint или Foreign Key Constraint. Сконфигурируйте в нем соответствующее ограничение. Для вызова справочной информации при работе в этих диалоговых окон нажмите клавишу <Fl>.
Добавление реляционных отношений
Вы можете также задать реляционные отношения между таблицами набора данных (с помощью объектов DataRelation) на этапе разработки проекта.
Ниже описано добавление объектов DataRelation для нетипизированного набора данных на этапе разработки проекта.
В форме или компоненте мышью выделите набор данных и откройте окно его свойств Properties.
В строке свойства Relations щелкните кнопку для открытия диалогового окна Relations Collection Editor (рис. 2.17).
Рис. 2.17. Диалоговое окно Relations Collection Editor
Нажмите кнопку Add для создания новой реляционной связи.
Откроется диалоговое окно Relation с установленными по умолчанию значениями параметров отношений (рис. 2.18).
Рис. 2.18. Диалоговое окно Relation
В диалоговом окне Relation задайте нужные вам значения параметров, руководствуясь данными табл. 2.4.
Таблица 2.4. Параметры конфигурирования реляционных связей
Значение
Описание
Name
Имя, которое используется для обращения к объекту DataRelation в программном коде. Обычно в качестве имени выбирают слитное название связываемых таблиц (например, CustomersOrders)
Parent table
Родительская таблица. Выбирается из выпадающего списка
Child table
Дочерняя таблица. Выбирается из выпадающего списка
Key Columns
Имена колонок в родительской таблице, которые составляют первичный ключ для связи с дочерней таблицей. Можно выбирать имена колонок из выпадающего списка или вводить их вручную
Foreign Key Columns
Имена колонок в дочерней таблице, которые составляют внешний ключ для связи с родительской таблицей
Enforce constraints
Булево значение, указывающее, будет ли объект DataRelation использоваться для каскадного обновления записей дочерней таблицы при изменении записей в родительской таблице и наоборот
Если вы хотите использовать это ограничение, то в родительскою таблицу добавить внешний ключ
Update rule
Характер (правила) каскадного обновления (удаления) записей в дочерней таблице, когда имело место корректировка
Delete rule
данных в родительской таблице
Accept/Reject rule
Щелкните кнопку ОК для сохранения созданной реляционной связи.
Повторите шаги с 3 по 5 для других реляционных связей, если они необходимы.
Способы фильтрации и сортировки данных в DataSet
После того, как объект DataSet заполнен данными, ваше приложение должно обеспечить представление имеющейся в нем информации в различных "ракурсах". Например, конечный пользователь может пожелать отсор-
тировать записи по определенному признаку (по номеру заказа, по фамилии заказчика, по дате заказа и т. п.) или — увидеть только некую вырезку из записей (например, отфильтровать заказы по заданной дате). Поскольку набор данных отсоединен из источника данных, то нерационально каждый раз обращаться к первоисточнику и получать тот же набор данных, но, например, отсортированных в другом порядке.
Вместо этого можно использовать встроенные возможности набора данных — изменение порядка расположения записей (сортировка) и формирование ограниченного поднабора данных (фильтр). И реализация может проходить двумя способами.
Q В таблицах набора данных поддерживается метод Select, который вы можете вызвать для изменения сортировки и фильтрации. Метод не меняет содержание или порядок расположения записей в таблице; вместо этого он представляет вам список записей, сформированных на основе критериев, которые вы задаете.
Q Можно использовать представление данных (объект DataView). Представление — объект, который формирует срез таблицы данных, т.е. выделяет фильтрованную и отсортированную часть содержимого таблицы. Представления объекта DataSet подобны представлениям баз данных (view), однако они не получают новую порцию информации от источника данных при каждом обращении к ним. Они позволяют увидеть по- новому данные, уже содержащиеся в таблицах объекта DataSet.
Оба метода обеспечивают одинаковые возможности фильтрования и сортировки данных. Различие заключается в том, что вызвать метод select таблицы набора данных можно только из программного кода во время выполнения приложения. Использование же представлений обеспечивает следующие преимущества:
Q вы можете создать и сконфигурировать представление данных на этапе разработки проекта, с возможностью изменения его свойства и в режиме работы приложения;
Q вы можете связывать представления с объектами отображения данных наэтапепроектированияприложения;
О вы можете создать мультипредставления, которые позволяют показывать данные из таблицы различными способами. Например, одно и то же представление может показать данные таблицы orders (Заказы), отсортированные по дате заказа, по имени клиента, по номеру заказа и т. д.
Объект DataView, создаваемый по умолчанию
Если вы хотите использовать представления данных, то можете добавить этот объект к форме или компоненту тем же способом, которым добавляют-
4 Зак 873
ся другие элементы данных (перетаскиванием объекта в окно дизайнера формы и установкой его свойств). Однако даже если вы явно не добавляете представление данных к вашей форме или компоненту, то данный объект создается автоматически (по умолчанию) и является доступным для каждой таблицы в наборе данных. Вы можете получить доступ к представлению, созданному по умолчанию, используя свойства таблицы — DefaultView, которое возвращает объект DataView. Также можно устанавливать свойства представления данных динамически (во время исполнения приложения).
Вы можете использовать представления данных, созданные по умолчанию, так же, как и созданные вами. Однако использование своих представлений имеет некоторые преимущества:
Q вы можете использовать возможность многократного отображения данных единственного DataSet в совершенно разных видах;
Q вы можете установить свойства представления данных во время разработки проекта (свойства представления данных, созданного по умолчанию, доступны только во время исполнения приложения);
Q вы можете назначить удобочитаемые имена для ваших представлений данных.
Фильтрация таблиц данных
Используя метод Select таблицы или свойство RowFilter представления данных, можно фильтровать записи таблицы данных, то есть делать доступным только те записи, с которыми необходимо работать в данный момент. Это обеспечивает возможность работы с различными поднаборами записей таблицы объекта DataSet. Для определения критерия фильтра используется тот же синтаксис, что и при формировании выражений вычисляемых колонок. Результатом выражения фильтра является булево значение: если оно равно true, то запись включается в отфильтрованный набор. Выражение фильтра может иметь, например, следующий вид:
Price > 10.00
В выражениях вы можете ссылаться на значения колонок по их именам.
Фильтрация по RowState и Version
Набор данных может поддерживать различные версии записей в таблицах. Когдазаписизаполняютсяпервыйраз(изисточникаданных),тонабор
данных содержит первоначальную (оригинальную) версию записей. Если вносятся изменения в записи, то набор данных поддерживает две версии записей: первоначальную и текущую (в текущей отражены все внесенные изменения). Каждая запись имеет свойство, отражающее ее состояние: не
изменялась, обновлена, новая, удалена. Удаленные записи, например, продолжают существовать в таблице данных, но они помечаются как удаленные и не отображаются в объектах визуализации. Обычно фильтрации подвергаются только текущие версии записей таблицы данных.
Если вы будете перебирать записи таблицы данных простым выполнением цикла по коллекции строк — ROWS, вы получите весь набор записей — измененные, новые и удаленные. Фильтр же позволяет возвращать только те записи, которые соответствуют определенным критериям или имеют определенное состояние.
Если вы вызываете метод select и передаете ему выражение фильтра, то можно еще добавить и параметр, указывающий, что строки, которые необходимо отфильтровать, являются той или иной версией. Если вы используете представление данных, вы можете установить индикатор RowStateFilter, указывающий, какую версию или состояние строк вы хотите получить.
Сортировка
Сортировка подобна фильтрации в том, что при сортировке так же задается выражение, но оно определяет порядок расположения записей. Типичное выражение сортировки это имя столбца, по которому необходимо отсортировать данные. Например, чтобы отсортировать данные по столбцу "дата заказа" (OrderDate), в выражении сортировки просто указывается имя столбца — OrderDate. Однако вы можете отсортировать данные любым выражением, включающим и расчетные значения. Если вызывается метод таблицы Select, то выражение сортировки передается ему как параметр. Если используется представление данных, то выражение сортировки определяется как значение свойства sort.
Задание выражений фильтрации и сортировки с помощью Data View Manager
Вы можете определить индивидуальные условия сортировки и фильтрации для каждой таблицы набора данных. Если в наборе данных содержится несколько таблиц, то индивидуальные условия фильтрации и сортировки можно задать с помощью объекта DataViewManager. Структура DataViewManager аналогична структуре объекта DataSet — это объект, который управляет коллекцией представлений данных, каждое из которых связано с определенной таблицей в наборе данных.
Использование DataViewManager особенно эффективно, когда необходимо оперировать связанными таблицами. Например, требуется сортировать или фильтровать записи дочерней таблицы на основе родительской. Допустим, в
наборе данных содержатся таблицы клиентов (Customers), заказов (orders) и объект DataRelation, который связывает эти две таблицы. Для сортировки таблицы Customers по имени компании (CompanyName) и таблицы Orders по дате заказа (OrderDate) можно использовать индивидуальные представления данных. Однако когда будет вызван метод GetChildRecords объекта DataRelation, чтобы получить список заказов конкретного клиента, то результирующие записи не будут отсортированы. Если для задания условий сортировки использовать объект DataViewManager, то сортировка будет проведена.
Создать и сконфигурировать объект DataViewManager можно только в программном коде. Нет никакого другого объекта, который бы имел описанные выше возможности и который мог бы настраиваться и конфигурироваться на этапе проектирования приложения. Это означает, что связать DataViewManager с любым объектом отображения данных можно только в программном коде и увидеть результаты работы объекта только на этапе работы приложения.
Фильтрацияисортировкиданных
в DataSet с помощью объекта DataView
Объект DataView обеспечивает представление содержимого таблицы в фильтрованном и сортированном виде.
Для формирования объекта DataView выполните следующие действия.
Создайте объект DataSet.
Добавьте программный код для заполнения набора данных.
Из вкладки Data окна Toolbox, перетащите объект DataView на форму или компонент (рис. 2.19).
Toolbox-в X
Data
1^ Pointer
1^1 DataSet
OieDbData Adapter
^ OteDbConnecton jS OleDbCommand ^ SqlDataAdapter ' j£ SqlConnectlon ^l SqiCommand
DataView
Рис. 2.19. Объект DataView в окне Toolbox
Новое представление данных добавиться к форме и получит имя по умолчанию DataView1.
Если вы хотите конфигурировать объект DataView в режиме разработки приложения, а не программно — выделите мышью этот объект и перейдите в окно его свойств Properties, В табл. 2.5 перечислены настраиваемые свойства.
Примечание
Вы можете установить все эти свойства, кроме имени, во время выполнения программы.
Таблица 2.5. Свойства объекта DataView
Свойства
Описание
Name
Имя, через которое можно обратиться к DataView в программном коде
Table
Ссылка на таблицу (объект DataTable), для которой создается представление. Вы можете выбрать имя таблицы из раскрывающегося списка. Необходимо обязательно установить данное свойство, иначе в представлении не будет содержаться никаких записей (однако оно может быть установлено во время выполнения приложения)
Sort
Выражение, указывающее, как сортировать записи в представлении (в самой таблице данные не отсортированы). Обычно выражение сортировки содержит имя столбца таблицы и (не обязательно) спецификатор АSС или DESC для указания направления сортировки (по возрастанию или убыванию). Однако сортировать данные можно с помощью любого выражения, включая вычисления
RowFilter
Выражение, определяющее, какой набор записей включить в представление. Результат выражения имеет булево значение; если выражение возвращает true, то запись будет включена в представление. Выражение может иметь, например, следующий вид: Price > 10.00
RowStateFilter
Версия записей, которые должны быть включены в представление. По умолчанию данное свойство имеет значение CurrentRows (текущая версия — будут включены все строки, в которых сделаны любые изменения)
AllowEdit, AllowNew, AllowDelete
Определяет возможность вносить изменения в записи представления (редактирование, добавление, удаление)
Использование объекта DataView для фильтрации и сортировки данных
С помощью DataView можно установить критерии сортировки на стации разработки проекта и связать этот объект с компонентами отображения данных.
Вы можете фильтровать и сортировать данные с помощью объекта DataView, который добавляется к форме или компоненту. Это позволяет устанавливать необходимые параметры фильтрации и сортировки во время разработки проекта. Как альтернативу можно использовать объект DataView устанавливаемый по умолчанию (DefaultView), который формируется автоматически для каждой таблицы набора данных, но в таком случае вы можете изменить параметры фильтрации и сортировки только в программном коде.
Для использования объекта DataView необходимо выполнить следующие шаги.
Если вы хотите установить параметры фильтрации и сортировки во время разработки проекта, добавьте DataView к форме или компоненту.
Установите значение свойства Sort, задав выражение сортировки. Выражение сортировки может включать имена колонок таблицы, а также операции вычисления. Если вы устанавливаете или изменяете выражение сортировки динамически (во время работы программы), то вид данных автоматически изменяется.
Установите значение свойства RowFilter, используя выражение (критерий) фильтрации. Результат выполнения выражения должен иметь значение true или false, например:
CustomerStatus='Active'
Примечаниеj
Если выражение фильтра содержит зарезервированные знаки (символы), в частности апостроф, например, "Margie's Travel", то эти символы должны быть выделены знаком наклонной черты (\). Например, следующее выражение показывает, как использовать знак \, чтобы включить апостроф в выражение фильтра: CompanyName='Margie\'s Travel'
Для фильтра, учитывающего версию или состояние записи, установите свойство RowStateFilter равным значению свойства CurrentRows элемента DataViewRowState (ЛИСТИНГ 2.6).
Листинг 2.61
' Visual Basic
Dataview1.RowStateFilter=DataViewRowState.CurrentRows
// C#
Dataview1.RowStateFilter=DataViewRowState.CurrentRows;
Следующий пример (листинг 2.7) показывает, как установить параметры фильтрации и сортировки данных во время работы приложения, используя DefaultView.
Листинг 2.7
' Visual Basic
Dataset1.Customers.DefaultView.Sort="City"
// C#
Dataset1.Customers.DefaultView.Sort="City";
Следующий пример (листинг 2.8) показывает, как явно добавить объект DataView к форме на этапе работы программы. Здесь проверяются значения двух переключателей, и в зависимости от их состоянии, устанавливается различный порядок сортировки. Фильтры обеспечат показ только текущих записей. Результаты показаны в объекте DataGrid, который связан с объектом DataView.
Листинг 2.8
' Visual Basic
If radioCity.Checked Then
DataView1.Sort="City"
ElseIf radioCompanyName.Checked Then
DataView1.Sort="CompanyName"
End If
Dataview1.RowFilter="CustomerStatus='Active'"
Dataview1.RowStateFilter=DataViewRowState.CurrentRows
Me.DataGrid1.DataSource=DataView1
// C#
if (radioCity.Checked)
(
DataView1.Sort="City";
)
else if (radioCompanyName.Checked)
DataView1.Sort="CompanyName" ;
}
DataView1.RowFilter="CustomerStatus='Active'";
DataView1.RowStateFilter=DataViewRowState.CurrentRows;
this.DataGrid1.DataSource=DataView1;
Фильтрация и сортировка таблиц данных в DataSet
Вы можете фильтровать и сортировать содержание самой таблицы, вызвав метод таблицы select. Этот способ позволяет фильтровать и сортировать данные только во время исполнения приложения. В таком случае не происходит изменения содержания самой таблицы, просто вы работаете с набором пересортированных данных таблицы.
Для фильтрации и сортировки данных таблицы нужно вызвать метод табли- цыselect, передавемутрипараметра:
DataTable.Select(filterExp, sortExp, rowstatevalue)
В табл. 2.6 приведено описание этих параметров.
Таблица 2.6. Параметры фильтрации и сортировки объекта DataTable
Параметр
Описание
filterExp
Выражение фильтра, которое должно иметь результат true ИЛИ false
sortExp
Выражение сортировки. Это обычно имя колонки таблицы, но может быть и любое расчетное значение
rowstatevalue
Значение, определяющее записи какой версии или какого состояния должны попасть в фильтр. Обычно значение этого параметра соответствует одному из элементов набора DataViewRowState (например, DataViewRowState.CurrentRows)
Вы можете вызвать метод только с первым или только с первыми двумя параметрами. Чтобы пропустить параметр, внесите в его. значение пусто (Nothing для VB, null для С#).
Метод select возвращает массив строк с данными.
Далее показан пример (листинг 2.9), как фильтруется и сортируется таблица Customers в наборе данных с именем dataSet1. Выражение фильтра выбирает клиентов со статусом Active. Выражение сортировки обеспечивает сортировку данных по наименованию города — колонка city, и заключи-
тельный параметр определяет, что будут выбраны записи только текущей версии. Отсортированный список будет показан в элементе listBox1.
Листинг 2.9
' Visual Basic
Dim filterExp As String="Status='Active'"
Dim sortExp As String="City"
Dim drarray() As DataRow
Dim i As Integer
drarray=dataSet1.Customers.Select(filterExp,sortExp,DataViewRowState,Curr entRows)
For i=0 To (drarray.Length-1)
listBox1.Items.Add(drarray(i)("City").ToString)
Next
// C#
string filterExp="Status='Active'";
string sortExp="City";
DataRow[] drarray;
drarray=dataSet1.Customers.
Select (filterExp, sortExp,DataViewRowState.CurrentRows) ;
for (int i=0; i<drarray.Length-1; i++)Н-)
listBox1.Items.Add(drarray[i]["City"].ToString());
Следующий пример (листинг 2.10) показывает, какие параметры должен иметь метод Select, чтобы выдать только удаленные записи (в параметрах пропущены значения выражений фильтра и сортировки и указан только параметр состояния записи).
Г"--— "-~— 1
Листинг 2.10
' Visual Basic
drarray=dataSet1.Customers.Select(Nothing, Nothing,^
DataViewRowState.Deleted)
// C#
drarray=dataSet1.Customers.Select(null,null,DataViewRowState.Deleted);
Доступ к записям в объекте DataView
Когда вы работаете с объектом DataView, можно иметь доступ к отфильтрованным или отсортированным записям, получая их не из таблицы, а непосредственно от объекта DataView, в котором они находятся. Можно также изменять, вставить и удалять записи через DataView. Но для этого необходимы определенные условия.
Q Объект DataView должен иметь достаточно информации о каждой записи, чтобы определить, какой записи таблицы она соответствует. Эта информация может включать первичный ключ и другие элементы, которые совместно обеспечиваютуникальную идентификацию записей.
Q Такие свойства объекта DataView как AllowEdit, AllowNew и AllowDelete должны иметь значения true, если вы собираетесь редактировать, добавлять или удалять записи.
Поиск записей
Для осуществления поиска записей в DataView выполните следующие действия.
Задайтев свойствеSortобъектаDataView имястолбцаилистолбцов,в
которых вы хотите выполнить поиск.
ВызовитеметодFindилиFindRowsобъектаDataView,передаваяему
значение критерия поиска:
если необходимо найти одну запись, то вызовите метод Find;
если необходимо найти более одной записи, то используйте метод FindRows.
Следующий пример (листинг 2.11) показывает, как возвратить индекс найденной строки по значению критерия, заданного в текстовом поле.
Листинг 2.11
' Visual Basic
DataView1.Sort="CustomerID"
Dim foundIndex as Integer=DataView1.Find(TextBox1.Text)
// C#
dataView1.Sort="CustomerID";
int foundIndex=dataView1.Find(textBox1.Text);
Чтение записей
Для обращения к записи объекта DataView, необходимо указать ее индекс (номер записи). Для обращения к столбцу записи нужно сослаться на его имя. В следующем примере (листинг 2.12), получено имя клиента (CustomerName) отпервой (нулевой) записи объекта Dataview1.
Листинг 2.12
' Visual Basic
Dim DataView1 as New DataView(ds.Customers)
Dim cname As String=CType(DataView1(0)("CustomerName"), String)
// C#
DataView dataView1=new DataView(ds.Customers);
string cname=dataView1[0]["CustomerName"].ToString();
Следующий пример (листинг 2.13) показывает, как в цикле просмотреть все записи объекта DataView , который отображает данные таблицы Customers (Клиенты). Здесь значения трех полей (CustomerId, CompanyName и City) каждой записи разделяются пробелами и помещаются в строковую переменную s и затем все строки отображаются в текстовом поле.
Листинг 2.13
' Visual Basic
Dim drv As DataRowView
DimsАз String=""
For Each drv In DataView1
s &=drv("CustomerID").ToString & " "
s &=drv("CompanyName").ToString & " "
5 &=drv("City").ToString & ControlChars.CrLf
Next
TextBox1.Text=s
// C#
string s="";
foreach (DataRowView drv in dataView1)
{
s +=drv["CustomerID"].ToString()+" ";
s +=drv["CompanyName"].ToString()+" ";
s +=drv["City"].ToString()+"\n";
}
textBox1.Text=s;
Обновлениезаписей
При обновлении записей в DataView в программном коде для идентификации записи используется ее индекс, а для идентификации колонки — ее имя.
Примечание
Вы не сможете отредактировать записи объекта DataView, если его свойство AllowEdit имеет значение false.
Следующий пример (листинг 2.14) демонстрирует, как можно изменить значение первой записи в колонке с именем компании (CompanyName),
ЛИСТИНГ 2.14
U.:
' Visual Basic
DataView1(0)("CompanyName")="Fabrikam, Inc."
// C#
dataView1[0]["CompanyName"]="Fabrikam, Inc.";
Добавление записей в DataView
Для добавления новой записи (листинг 2.15) используется метод AddNew объекта DataView, который создает новую запись и возвращает ее объекту DataRowView.
i"•
Листинг 2.15
MS.™———
' Visual Basic
Dim drv As DataRowView
drv=DataView1.AddNew()
// C#
DataRowView drv;
drv=dataView1.AddNew();
После добавления новой записи ее можно модифицировать, как и любую другую запись.
Примечание
Вы не сможете добавить запись к объекту DataView, если его свойство AllowNew имеет значение false.
Следующий пример (листинг 2.16) показывает, как добавить новую запись к объекту DataView и модифицировать значения трех полей в этой записи.
Листинг 2.16
' Visual Basic
Dim drv As DataRowView
drv=DataView1.AddNew()
drv("CustomerID")="AAA" drv("CompanyName")="AAFabrikam,Inc."
drv("City")="Aurora"
// C#
DataRowView drv;
drv=dataView1.AddNew();
drv["CustomerID"]="AAA";
drv["CompanyName"]="AAFabrikam, Inc.";
drv["City"]="Aurora";
Удаление записей
Для удаления записи нужно вызвать метод Delete объекта DataView, передав ему индекс записи, которую необходимо удалить.
Примечание
Вы не сможете удалить запись объекта DataView, если его свойство AllowDelete имеет значение false.
Следующий пример (листинг 2.17) показывает, как удалить первую (нулевую) запись.
Листинг 2.17
' Visual Basic
DataView1.Delete(0)
// C#
dataView1.Delete(0);
Работа с коллекцией DataView через объект DataViewManager
В Visual Studio имеется объект DataViewManager, который содержит коллекцию объектов DataView, каждый из которых связан с одной таблицей набора данных DataSet. В приложении DataViewManager обеспечивает централизованный доступ к сортированным и фильтрованным данным. Такой доступ очень удобен при работе со связанными таблицами.
Примечание j
Вы должны создавать и конфигурировать DataViewManager в программном коде (этот объект не поддерживается в режиме разработки проекта).
Создание и конфигурирование объектаDataViewManager.
Создайте объект DataSet.
Добавьте программный код для заполнения набора данных.
Создайте экземпляр класса DataViewManager.
Укажите в свойстве DataSet объекта DataViewManager имя того набора данных (DataSet), который был создан в шаге 1.
Задайте выражения сортировки и фильтрации для таблиц, доступных в DataViewManager черезколлекциюDataViewSettings,
Примечание
Для установки параметров таблиц, доступных в DataViewManager, используйте его свойство DataViewSettings.
Если вы хотите связать объект отображения данных с DataViewManager, то устанавливайте свойство этого объекта data-binding после того, как сконфигурирован DataViewManager. При этом, например, в Windows-форме в свойстве объекта отображения данных DataSource нужно указать имя объ- ектаDataViewManager, а В свойствеDataMember —ИМЯ таблицы.
В следующем примере (листинг 2.18) показано, как создается объект DataViewManager и устанавливаются параметры фильтрации и сортировки для таблиц. Предполагается, что есть набор данных с именем dsCustomersOrders, параметры сортировки задаются для таблиц Customers (Клиенты) и Orders (Заказы), объект DataViewManager отображает в сетке данных таблицу titles. -
Листинг 2.18
' Visual Basic
Dim dvm As New DataViewManager()
dvm.DataSet=dsCustomersOrders1
dvm.DataViewSettings("Customers").Sort="CompanyName" dvm.DataViewSettings("Orders").Sort="OrderDate" Datagrid1.DataSource=dvm
Datagrid1.DataMetnber="titles"
// C#
DataViewManager dvm=new DataViewManager();
dvm.DataSet=dsCustomersOrders1;
dvm.DataViewSettings["Customers"].Sort="CompanyName";
dvm.DataViewSettings["Orders"].Sort="OrderDate";
dataGrid1.DataSource=dvm;
dataGrid1.DataMember="titles";
Реляционные отношения в DataSet
В объекте Dataset можно устанавливать реляционные связи между таблицами С ПОМОЩЬЮ объекта DataRelation.
Объект DataRelation
Достаточно часто возникает необходимость работы приложения со связанными таблицами. Хотя в наборе данных может содержаться несколько таблиц (как и в базе данных), но это не означает, что они будут связаны между собой. Однако вы можете создать объект DataRelation, который обеспечит установку связи между родительской и дочерней таблицами. Эти отношения основаны на обшей колонке (ключевом столбце).
Например, набор данных может содержать таблицу customers (Клиенты) и таблицу Orders (Заказы). Даже если таблицы и содержат общее ключевое поле (в этом примере ключевым является поле CustomerID), сам набор данных не создает и не отслеживает связи между таблицами, их нужно задать через объект DataRelation.
Объект DataRelation может выполнять две функции.
Q Делать доступными записи связанной дочерней таблицы с текущей записью родительской таблицы и наоборот.
Q Предписывать ограничения для обеспечения целостности данных (например, удаление связанных дочерних записей при удалении родительской записи).
Важно понять различия между реальным объединением данных и функционированием объекта DataRelation. В реальном объединении происходит взя-
тие записей из родительской и дочерних таблиц и помещение их в единый, плоский набор записей (Recordset). Когда используется объект DataRelation, никакой новый набор записей не создается. Вместо этого отслеживается отношение между несколькими самостоятельными таблицами, поддерживается синхронизация записей в родительской и дочерних таблицах.
Доступ к связанным записям
Если таблицы в наборе данных имеют реляционные отношения, то, работая с записью одной таблицы, через объект DataRelation можно сделать доступными связанные записи другой таблицы. Например, можно создать набор данных, содержащий таблицу customers с информацией о клиентах (с первичным ключом CustomerID) и таблицу Orders с заказами клиентов (с внешним ключом CustomerID). Для этих таблиц можно создать объект DataRelation, в свойствах которого установлены ссылки на эти ключи.
После можно использовать объект DataRelation для получения связанных записей. Причем физического объединения таблиц не происходит. Вместо этого вызывается метод GetChildRows записи родительской таблицы, с подключением объекта DataRelation, в котором определены реляционные отношения. Метод возвращает набор связанных записей дочерней таблицы.
В следующем примере (листинг 2.19) иллюстрируется получение связанных записей. В данном примере родительской записью является первая (нулевая) строка таблицы Customers (Клиенты), а массив строк данных (drarray) заполняется дочерними записями из связанной таблицы с заказами клиентов.
Листинг2.19
' Visual Basic
Dim RowCtr As Integer
Dim drarray() As DataRow
RowCtr=0
drarray = ъ
dsCustomersOrders1,Customers(RowCtr).GetChildRows("CustomersOrders")
// C#
int rowCtr;
DataRow[] drarray;
rowCtr=0;
drarray= ъ
dsCustomersOrders1.Customers[rowCtr].GetChildRows("CustomersOrders");
В данном примере сначала определяется переменная RowCtr для хранения номера (задания) строки родительской таблицы. Далее создается экземпляр класса DataRow с именем drarray (массив строк, куда будут помещены связанные записи дочерней таблицы). Ну и, наконец, вызывается метод GetChildRows таблицы Customers, в качестве параметра ему передается имя dsCustomersOrders ранее созданного объекта DataRelation.
Точно так же можно получить запись родительской таблицы (из заданной записи дочерней таблицы), вызвав метод GetParentRow дочерней таблицы. В этом случае метод возвращает не множество, а одну запись данных.
•
Использование ограничений в объекте DataRelation
Объект DataRelation также используется для того, чтобы создавать и кон- фигурироватьследующиеограничения:
Q уникальное ограничение, которое гарантирует то, что в колонке таблицы не содержится дублированных значений;
Q ограничение внешнего ключа, которое используется для поддержания целостности данных в родительских и дочерних таблицах набора данных.
Ограничения, которые вы определяете в объекте DataRelation, автоматически формируют некоторые дополнительные объекты и определяют их свойства. Если вы создаете ограничение внешнего ключа, используя объект DataRelation, Экземпляр Класса ForeignKeyConstraint добавит СВОЙСТВО ChildKeyConstraint.
Ограничение уникальности записи можно задать простой установкой свойства колонки Unique в значение true, или добавив экземпляр ParentKeyConstraint класса UniqueConstraint объекта DataRelation.
Как часть ограничения внешнего ключа, вы можете определить типовые правила целостности данных, которые работают трех случаях:
О когда изменена родительская запись;
Q когда удалена родительская запись;
Q когда изменения приняты или отвергнуты.
Набор этих правил определен и приводится в табл. 2.7.
Таблица 2.7. Правила обеспечения целостности данных
Правило внешнего ключаВыполняемые действия
CascadeИзменения (обновление или удаление) сделанные в
родительской записи, будут сделаны и в связанных записях дочерней таблицы
Таблица 2.7. (окончание)
Правило внешнего ключа
Выполняемые действия
SetNull
Дочерние записи не удаляются, но внешний ключ в этих записях получает значение DBNull. Таким образом дочерние записи остаются как бы "сиротами", то есть они теряют связь с родительской записью
Использование этого правила может исказить некоторые результаты выборки из дочерних таблиц
SetDefault
Внешний ключ в связанных дочерних записях получает значение по умолчанию (как задано в свойстве колонки DefaultValue)
None
Никакие изменения не делаются в связанных дочерних записях. Таким образом можно оборвать ссылку дочерних записей на ошибочную родительскую запись
Default
Значение по умолчанию — Cascade
Отношения для задания ограничений
(Constraint-only Relations)
При создании объекта DataRelation, вы можете установить флажок Constraint only определяющий, что реляционная связь будет использоваться только для задания ограничения, то есть она не будет обеспечивать доступ к связанным записям. При такой установке создается более простой и эффективный набор данных, поскольку он содержит меньше методов, чем такой же объект со способностью ссылки и выборки связанных записей.
Создание объекта DataRelation с помощью XML-дизайнера
Объекты DataRelation — часть структуры набора данных, наряду с таблицами и колонками, определенными в наборе данных. Поэтому для типизированных наборов данных объекты DataRelation определены в схеме данных. Вы можете создать объекты DataRelation в наборе данных, используя XML-дизайнера. Для этого совсем не обязательно знать XML-формат или структуру схемы.
Создание объекта DataRelation в наборе данных с помощью XML- дизайнера происходит следующим образом.
Создается схема для набора данных (если она еще не создана).
В Solution Explorer нужно двойным щелчком открыть XML-схему (xsd- файл).
Схема откроется на вкладке Schema, где будет представлена каждая таблица в объекте в виде сетки (рис. 2.20).
t yt -г.г. rorml ,b [Dcsig-. ■ DataSet 1 .xsd* |
Zustorners ((Customers)Zustorners ((Customers)^E CustomerlD string^E CustomerlD stringE CompanyNa string E ContactNam string E ContactTItle string F Address stringE CompanyNa string E ContactNam string E ContactTItle string F Address stringE Oty stringE Oty stringEB^r- (^Orders)pt OrderlD ' kitE CustomerlD stringE EmployeelD IntE OrderDate datetimeF RequiredDat dateTImeF ShlppedDate dateTimeE ShipVia IntEB^r- (^Orders)pt OrderlD ' kitE CustomerlD stringE EmployeelD IntE OrderDate datetimeF RequiredDat dateTImeF ShlppedDate dateTimeE ShipVia Int
Zustorners ((Customers)
Zustorners ((Customers)
^E CustomerlD string
^E CustomerlD string
E CompanyNa string E ContactNam string E ContactTItle string F Address string
E CompanyNa string E ContactNam string E ContactTItle string F Address string
E Oty string
E Oty string
EB^r- (^Orders)pt OrderlD ' kit
E CustomerlD string
E EmployeelD Int
E OrderDate datetime
F RequiredDat dateTIme
F ShlppedDate dateTime
E ShipVia Int
EB^r- (^Orders)pt OrderlD ' kit
E CustomerlD string
E EmployeelD Int
E OrderDate datetime
F RequiredDat dateTIme
F ShlppedDate dateTime
E ShipVia Int
Рис. 2.20. Связываемые таблицы в XML-схеме
Из вкладки XML Schema окна Toolbox, перетащите объект Relation на дочернюю таблицу (рис. 2.21).
Рис. 2.21. Объект Relation в окне ToolboxРис. 2.21. Объект Relation в окне Toolbox
Рис. 2.21. Объект Relation в окне Toolbox
Рис. 2.21. Объект Relation в окне Toolbox
Откроется диалоговое окно Edit Relation (рис. 2.22).
Если вы хотите изменить имя объекта DataRelation, внесите его в поле Name.
Удостоверьтесь, что указатель родительского элемента Parent element установлен на имя родительской таблицы, а указатель дочернего элемента Child element на имя дочерней таблицы создаваемого объект DataRelation.
В списке ключей Key выберите ключ в родительской таблице, который вы хотите использовать для создания объекта DataRelation.
Name: [Customer sOrders
Chid element:Chid element:у j jOrdersу j jOrdersTo define a relationship (keyref), select the parent element and key, select the child element, and then select the child field corresponding to each parent field.
Chid element:
Chid element:
у j jOrders
у j jOrders
Parent element: [customers
Key:
{Constraint 1
Fields:Fields:Key FieldsKey FieldsCustomer IDCustomer IDDataset PropertiesDataset PropertiesГ* Create Foreign key constraint onlyГ* Create Foreign key constraint onlyForeign Key Fields Customer IDForeign Key Fields Customer IDUpdate rule: [(Default)iUpdate rule: [(Default)iDelete rule:7] [(Default)Delete rule:7] [(Default)Accept/Reject rule:[(Default)Accept/Reject rule:[(Default)
Fields:
Fields:
Key Fields
Key Fields
Customer ID
Customer ID
Dataset Properties
Dataset Properties
Г* Create Foreign key constraint only
Г* Create Foreign key constraint only
Foreign Key Fields Customer ID
Foreign Key Fields Customer ID
Update rule: [(Default)i
Update rule: [(Default)i
Delete rule:
7] [(Default)
Delete rule:
7] [(Default)
Accept/Reject rule:
[(Default)
Accept/Reject rule:
[(Default)
CancelCancel
Cancel
Cancel
Help
Рис. 2.22. Диалоговое окно Edit Relation
Примечание
Элементы, представленные в списке ключей Key не являются именами ключевых колонок таблиц. Они являются лишь элементами схемы, которые могут сослаться на любую колонку таблицы, имеющей ограничение по уникальности (включая и фактический первичный ключ таблицы), Ключ может быть составным, то есть включать несколько колонок таблицы.
В сетке элементов схемы Fields удостоверьтесь, что колонки первичного ключа родительской таблицы (Key Field) и колонки внешнего ключа дочерней таблица (Forign Key Field) установлены в соответствии друг с другом. Если необходимо, вы можете изменить имена колонок в сетке или ввести имена в дополнительные колонки, используемые для определения реляционных отношений.
Если вы хотите создать связи, которые только предписывают некоторые ограничения (не используются для выборки связанных записей от дочерних или родительских таблиц), установите флажок Create foreign key constraint only.
Созданные таким образом связи позволят создать более простой и эффективный набор данных с меньшим количеством методов. Однако при этом возможность доступа к связанным записям теряется.
Если вы хотите, чтобы в наборе данных обеспечивалась целостность информации при обновлении и удалении записей, то установите флажок Enforce Constraints и затем выберете правила обеспечения целостности из списков Update Rule и Delete Rule.
Примечание
Если вы не устанавливаете флажок Enforce Constraints, то объект DataRelation позволит вам получать связанные записи от каждой дочерней таблицы, но не будут выполняться действия, обеспечивающие синхронизацию записей дочерних таблиц при изменениях в записи родительской таблицы.
Нажмите кнопку ОК для создания объекта DataRelation.
При этом XML-дизайнер нарисует линии связей между таблицами с объектами отношения в виде серых квадратов (рис. 2.23).
Start Page ' Form! b (C’es-g.-i]* DataSet Lnsd* |
E RequiredDat dateTime E ShippedDate dateTime E ShlpVia IntE RequiredDat dateTime E ShippedDate dateTime E ShlpVia IntE$>d?rs^|(Orders)$t OrderlD int E CustomerlD string E EmployeelD int E OrderDate dateTimeE$>d?rs^|(Orders)$t OrderlD int E CustomerlD string E EmployeelD int E OrderDate dateTimeEB^tatomw^jCCustcmers)
E RequiredDat dateTime E ShippedDate dateTime E ShlpVia Int
E RequiredDat dateTime E ShippedDate dateTime E ShlpVia Int
E$>d?rs^|(Orders)
$t OrderlD int E CustomerlD string E EmployeelD int E OrderDate dateTime
E$>d?rs^|(Orders)
$t OrderlD int E CustomerlD string E EmployeelD int E OrderDate dateTime
^E CustomerlD string E CompanyNa string E ContactNam string E ContactTtle string E Address string E City string
E Region string
Рис. 2.23. Связи между таблицами в XML схеме
Для редактирования реляционных отношений:
В окне редактирования схемы Design (XML-дизайнера) щелкните правой кнопкой мыши на объекте реляционного отношения (серый квадрат на линии, связывающей таблицы) и выберите пункт меню Edit Relation;
В открывшемся диалоговом окне Relation (KeyRef) Editor отредактируйте информацию о текущем объекте DataRelation.
Для удаления реляционных отношений в окне редактирования схемы XML дизайнера, щелкните правой кнопкой мыши на объекте реляционного отношения (серый квадрат на линии, связывающей таблицы) и выберите пункт меню Delete.
Обновление набора данных
в Visual Studio .NET
Когда в приложении пользователь работает с наборами данных Dataset, то фактически он оперирует с записями, оторванными от основной базы и находящимися в памяти компьютера. При такой модели доступа к данным возникает необходимость периодического обновления информации, содержащейся в основной базе данных. Когда пользователь вносит какие- либо изменения в записи таблицы объекта DataSet, то DataSet отслеживает и запоминает все эти изменения. По мере необходимости все сделанные изменения можно вернуть источнику данных. В течение процесса обновления источника данных происходит несколько событий, которые можно использовать для проверки правильности введенной пользователем информации.
Примечание
В Windows-формах, используется связывание объектов визуального отображения информации с объектом DataSet, поэтому обновление самого DataSet происходит автоматически, и эти процессы не нужно специально программировать.
Введение в обновление набора данных
Поскольку набор данных это фактически набор записей, оторванных от основной базы и помешенных в оперативную память компьютера, то процесс возврата изменений первоначальному источнику данных является изолированной процедурой и отделен от процесса модификации данных В DataSet.
Двухступенчатое обновление
Модификация источника данных через набор данных происходит в два этапа. На первом этапе модифицируется сам набор данных: пользователь добавляет новые записи, изменяет или удаляет существующие. Все эти процессы происходят в копии, оторванной от основного источника данных. На втором шаге необходимо послать эти изменения от оторванного набора данных к первоначальному источнику данных. То есть все изменения в наборе данных не передаются к основному источнику данных автоматически, этот процесс нужного активизировать явно. Это обычно достигается путем вызова метод Update адаптера данных. Схема двухступенчатого обновления данных в DataSet приведена на рис. 2.24.
DataSetDataSetDataRowStateUnchangetDataRowStateUnchangetDataRowStateModlfed DataRowStateModlfed DataAdapterDataAdapterDataAdapter.Fill DataAdapter. UpdateDataAdapter.Fill DataAdapter. UpdateОригинальная запись из базы данныхFirstName=" James'LastName'Wilson"DataRowVersion=Original/CurrentОригинальная запись из базы данныхFirstName=" James'LastName'Wilson"DataRowVersion=Original/CurrentСтадия 1. Обновление DataSetСтадия 1. Обновление DataSetОригинальная версия записиFirstName=' James”LastName”Wllson"DataRowVersion=OriginalОригинальная версия записиFirstName=' James”LastName”Wllson"DataRowVersion=OriginalТекущая версия записиFirstName='Jim"LastName'Wilson"DataRowVersion=CurrentТекущая версия записиFirstName='Jim"LastName'Wilson"DataRowVersion=CurrentЗначения колонок используютсядля поиска корректируемой строкив источнике данных (в предложенииWHERE SQL-запроса)Значения колонок используютсядля поиска корректируемой строкив источнике данных (в предложенииWHERE SQL-запроса)Значения колонок в DataSetиспользуются для обновленияколонок в источнике данных(в предложении SET SQL-запроса)Значения колонок в DataSetиспользуются для обновленияколонок в источнике данных(в предложении SET SQL-запроса)
DataSet
DataSet
DataRowState
Unchanget
DataRowState
Unchanget
DataRowState
Modlfed
DataRowState
Modlfed
DataAdapter
DataAdapter
DataAdapter.Fill DataAdapter. Update
DataAdapter.Fill DataAdapter. Update
Оригинальная запись из базы данныхFirstName=" James'LastName'Wilson"
DataRowVersion=Original/Current
Оригинальная запись из базы данныхFirstName=" James'LastName'Wilson"
DataRowVersion=Original/Current
Стадия 1. Обновление DataSet
Стадия 1. Обновление DataSet
Оригинальная версия записиFirstName=' James”LastName”Wllson"
DataRowVersion=Original
Оригинальная версия записиFirstName=' James”LastName”Wllson"
DataRowVersion=Original
Текущая версия записиFirstName='Jim"LastName'Wilson"
DataRowVersion=Current
Текущая версия записиFirstName='Jim"LastName'Wilson"
DataRowVersion=Current
Значения колонок используютсядля поиска корректируемой строкив источнике данных (в предложенииWHERE SQL-запроса)
Значения колонок используютсядля поиска корректируемой строкив источнике данных (в предложенииWHERE SQL-запроса)
Значения колонок в DataSetиспользуются для обновленияколонок в источнике данных(в предложении SET SQL-запроса)
Значения колонок в DataSetиспользуются для обновленияколонок в источнике данных(в предложении SET SQL-запроса)
Стадия 2. Обновление БД
Рис. 2.24. Схема двухступенчатого обновления данных в DataSet
Информация в объекте DataSet доступна через его коллекции. Набор данных содержит коллекцию таблиц (DataTable). Таблица содержат коллекции строк (DataRow). Строка содержит коллекцию колонок (DataColumn). Внесение изменений в наборе данных происходит путем навигации по элементам коллекции и модификации значений конкретных колонок. В объекте DataSet имеется набор методов, которые позволяют модифицировать только сам набор записей (их используют тогда, когда заведомо известно, что обновления не будут передаваться источнику данных). И есть набор методов, которые позволяют обновить информацию, как в наборе данных, так и в источнике данных.
Например, чтобы удалить записи из таблицы можно вызвать метод RemoveAt коллекции ROWS таблицы данных, которая физически удаляет записи из набора данных. Если набор данных используется только как элемент для ото-
бражения информации, и не предполагается возвращать изменения источнику данных или передавать другому приложению, то это наиболее оптимальный путь.
Однако если вы намереваетесь послать изменения источнику данных или другому приложению, то нужно фиксировать (запоминать) все изменения, которые были сделаны в DataSet. Затем, когда потребуется переслать изменения источнику данных, необходимо будет знать, какие записи были изменены в объекте DataSet и как их найти в источнике данных. Например, если вы удаляете запись в наборе данных, то нужно запомнить ключевую информацию об этой записи, а затем, когда будет вызван метод адаптера данных DeleteCommand, то ему должны быть переданы параметры удаленной записи, чтобы он смог определить местонахождение аналогичной записи в источнике данных и удалить именно ее.
Объединение наборов данных
Вы можете модифицировать содержание наборов данных путем их объединения, то есть, копируя содержание одного набора данных (исходный) в другой набор данных (целевой). Когда выполняется объединение наборов данных, то записи исходного набора данных добавляются к записям целевого набора данных. Если в исходном наборе есть дополнительные колонки, то они добавляются к целевому набору данных. Объединяемые наборы данных полезно создавать тогда, когда приложение получает второй набор данных от другого приложения или от компонента типа XML Web-service, или когда информацию, содержащуюся в нескольких наборах данных приложения, необходимо показать пользователю в одном компоненте отображения информации.
Когда делается объединение наборов данных, то методу объединения Merge можно передать дополнительный параметр preserveChanges (Boolean), который определит, нужно ли сохранить модифицированные записи в целевом наборе данных. Поскольку наборы данных DataSet поддерживают множественные версии записей, важно помнить, что при объединении наборов данных записи разных версий будут объединены. В следующей табл. 2.8 представлены записи в двух наборах данных, которые будут подвергнуты объединению.
Таблица 2.8. Записи двух наборов данных, до объединения
DataRowVersion
Целевой Dataset
Исходный Dataset
Original
James Wilson
James С.
Wilson
Current
Jim Wilson
James C.
Wilson
При значении параметра preserveChanges=false (не сохранять измененные записи) вызов метода слияния двух наборов данных вышеупомянутой таб-
лицы targetDataset.Merge (sourceDataset) приведет к следующему результату (табл. 2.9).
Таблица 2.9. Записи двух наборов данных после объединения (preserveChanges=false)
DataRowVersion
Целевой DataSet
Исходный DataSet
Original
James С. Wilson
James C. Wilson
Current
James C. Wilson
James C. Wilson
При значении параметра preserveChanges=true (сохранять измененные записи) вызов метода слияния двух наборов данных вышеупомянутой таблицы targetDataset.Merge(sourceDataset) приведет К другому результату (табл. 2.10).
Таблица 2.10. Записи двух наборов данных после объединения (pressrveChartges=true)
DataRowVersion
Целевой DataSet
Исходный DataSet
Original
James С. Wilson
James C. Wilson
Current
Jim Wilson
James C. Wilson
Ограничения обновления
Когда выполняется модификация записи, то пользователь поочередно изменяет значения отдельных столбцов. Если набор данных содержит ограничения (типа внешних ключей или запрещения присвоения значения null), то возможно, что вся запись может временно находиться в состоянии ошибки, поскольку пользователь не может одновременно присвоить или изменить значения всех столбцов.
Чтобы предотвратить преждевременное нарушение работы программы, можно временно приостановить действие ограничений обновления. Такое действие преследует две цели:
Q препятствует преждевременной остановке работы приложения по ошибке, когда пользователь еще не закончил модификацию столбцов записи;
Q позволяет обработать некоторые события, и которых можно проверить корректность вводимой пользователем информации.
После того, как пользователь завершил обновление всех колонок записи, можно вновь включитьдействие ограничений.
Примечание
В Windows-формах в объекте DataGrid автоматически приостанавливается действие ограничений до тех пор, пока пользователь не перейдет на другую
строку, при этом нет необходимости явно вызывать методы BeginEdit, EndEdit или CancelEdit.
Ограничения автоматически блокируются, когда вызывается метод слияния набора данных Merge. Когда после слияния наборов данных есть нарушение одного из ограничений, то в этой ситуации свойству EnforceConstraints присваивается значение false. Все несоблюдения ограничений должны быть разрешены перед присвоением свойству EnforceConstraints значения true.
Ошибки обновления набора данных
Когда происходит модификация записи в наборе данных, то могут возникнуть ошибки. Например, столбцу может быть присвоено значение, которое имеет несоответствующий тип данных, превышает допустимую размерность, нарушается целостность данных и т. п. Для предотвращения сбоя работы приложения при возникновении ошибочных ситуаций имеется возможность проверки правильности вводимой информации на любой стадии обновления данных.
Поддержание информации об изменениях в записях таблиц набора данных
Информация об изменениях в наборе данных поддержана двумя способами: наличие в каждой строке признака, указывающего на факт внесения изменения в строку (Rowstate), сохранение нескольких копий (версий) строки (DataRowVersion). На основе этой информации можно однозначно определить, что изменялось в наборе данных и куда адресовать эти изменения в источнике данных.
Свойство DataRowState
Объект DataRow имеет свойство DataRowState, в котором храниться информация о состоянии строки данных.
В табл. 2.11 приведены возможные значения свойства DataRowState-
Таблица 2.,11. Значения свойства DataRowState объекта DataRow
Значение свойстваОписание
AddedСтрокабыладобавленакколлекциистрок
DataRowCollection (для этой строки существует только текущая версия в наборе данных и отсутствует соответствующая оригинальная версия). Ее не было в наборе данных на момент последнего вызова метода AcceptChanges
Таблица 2.11. (окончание)
Значение свойства
Описание
Deleted
Строкабылаудаленаиспользованиемметода
DataRow.Delete объекта DataRow
Detached
Modified
Строка была создана, но еще не является элементом коллекции DataRowCollection. Объект DataRow находится в этом состоянии сразу после того, как был создан, но еще не добавлен к коллекции, или если он был специально удален из коллекции
Значение столбца в строке было изменено
unchanged
Строка не изменялась с тех пор, как был вызван метод AcceptChanges
Версия строки DataRowVersion
Наборы данных поддерживают множественные версии записей. Объект DataRow имеет свойство DataRowVersion, в котором хранится информации о версии каждой строки.
В табл. 2.12 приведены возможные значения свойства DataRowVersion.
Таблица 2.12. Значения свойства DataRowVersion объекта DataRow
Значение свойства
Описание
Current
Текущая версия записи. В этой строке содержатся все изменения, выполненные с момента последнего вызова метода AcceptChanges. Если строка была удалена, то у нее нет текущей версии
Default
Значение по умолчанию (как определено схемой набора данных или источником данных)
Original
Первоначальная (оригинальная) версия записи. Состояние записи до того, как в нее были внесены какие-либо изменения. Практически эта та версия записи, которая была получена от источника данных
Proposed
Промежуточная версия записей, которая существует временно (в режиме внесения в нее изменений). То есть она существует в промежуток времени между вызовами методов начала редактирования (BeginEdit) и завершением редактирования (EndEdit), Вы можете обратиться к этой версии записи в об- 1 работчике события RowChanging. Вызов метода CancelEdit полностью отменит все внесенные в строку изменения и удалит промежуточную версию строки данных
Первоначальная (оригинальная) и текущая версии записей используются тогда, когда требуется вернуть изменения источнику данных. Как правило, когда изменения посылаются источнику данных, то все обновления, которые требуется передать базе данных, находятся в текущей версии записи, а информация из первоначальной (оригинальной) версии используется для того, чтобы определить местонахождение записи, которую нужно модернизировать в таблице источника данных. Например, если пользователь изменил значение первичного ключа записи, то в этом случае, если не сохранить оригинальную запись, будет просто невозможно определить местонахождение соответствующей записи в источнике данных, чтобы выполнить в ней замену модифицированных пользователем колонок. Эти две версии также используются при контроле параллелизма (одновременной работы с записью нескольких пользователей). Перед инициализацией процедуры обновления можно сравнить первоначальную (оригинальную) версию записи с записью в источнике данных, чтобы определить, вносил ли в нее кто-нибудь изменения с тех пор, как она была загружена в набор данных.
Промежуточная версия может быть задействована тогда, когда необходимо выполнить проверку правильности введенной информации перед тем, как изменить текущую версию.
Первоначальная (оригинальная) или текущая версия строки существуют не всегда. Например, когда в таблицу набора данных добавляется новая строка, то первоначальной версии не существует, поскольку этой строки еще нет в источнике данных (существует только текущая версия). Точно так же, если строка была удалена с использованием метода Delete, то остается только первоначальная версия строки, текущая версия отсутствует.
Для проверки существования определенной версии записи можно использовать свойство строки данных HasVersion. Из программы можно обратиться к любой версии записи, передавая значение DataRowVersion как дополнительный параметр при обращении к значению столбца.
Получение измененных записей
Обычно при работе с приложением модифицируются не все записи в наборе данных. Например, при работе с элементом DataGrid Windows-формы, который отображает много записей, пользователь может модифицировать, удалить или вставить только несколько записей. Наборы данных и таблицы данных поддерживают метод GetChanges, что позволяет возвратить только те строки, в которые вносились изменения.
Вы можете создать любые подмножества измененных записей, используя методGetChangesДЛЯлюбойтаблицы данных (DataTable.GetChanges) ИЛИ для всего набора данных (DataSet.GetChanges). Если был вызван метод
для таблицы данных, то в результате его работы будет возвращена копия таблицы только с измененными записями. Точно так же, если был вызван метод для набора данных, то будет сформирован новый набор данных только с измененными записями этого набора. Вызов метода GetChanges без указания статуса строк, позволит получить все измененные записи. Если методу GetChanges передать в качестве параметра статус строки (DataRowState), тогда можно получить нужное подмножество измененных записей: только добавленные записи, записи, отмеченные для удаления, отдельные записи (не являющиеся элементами коллекции строк), модифицированные записи.
Получение подмножества измененных записей особенно полезно тогда, когда требуется переслать записи другому компоненту программы для дополнительной обработки. Вместо того чтобы посылать полный набор данных, можно передать только те записи, которые нуждаются в дополнительной обработке, тем самым уменьшить поток передаваемой между компонентами информации.
Завершение изменений в наборе данных
В процессе появления изменений в наборе данных, изменяется и свойство RowState для отдельных записей. В приложении можно обеспечить доступ как к первоначальным, так и к текущим версиям записей, используя свойство RowVersion.
Если все изменения, внесенные пользователем в набор данных, переданы источнику данных, то после этого нет необходимости поддерживать информацию о статусе и версиях записей. Как правило, есть два события, после которых набор данных и источник данных находятся в полностью синхронизированном состоянии:
Q сразу после того, как информация была загружена из источника данных в набор данных;
Ц после передачи всех изменений от набора данных до источника данных.
Вы можете завершить поддержку обработки изменений набора данных, вызвав метод AcceptChanges (принять изменения). Как правило, метод AcceptChanges вызывается в приложении в двух случаях.
Q После загрузки набора данных. Если набор данных был загружен путем вызова метода Fill в адаптер данных, то адаптер данных автоматически завершает процедуру поддержки изменений. Однако если вы загружаете набор данных путем объединения его с другим набором данных, то процедуру завершения изменений необходимо вызвать принудительно.
Примечание
Вы можете предотвратить действие адаптера данных по автоматическому завершению изменений при вызове метода Fill путем присвоения свойству AcceptChangesDuringFill значения false. В этом случае свойству RowState каждой строки, вставленной в течение заполнения объекта DataSet, будет присвоено значение Added,
Q После того, как изменения в наборе данных были пересланы другому процессу, типа XML Web-service.
Примечание
Завершая процесс изменения данных, вы стираете информацию о произведенных действиях. Не завершайте процедуру изменения до тех пор, пока не выполните всех операций, связанных со знанием изменений, которые были сделаны в наборе данных.
РаботаметодаAcceptChanges приводит кследующемурезультату:
Q значения колонок текущей (current) версии записей переносятся в колонки первоначальной (original) версии записей (поверх имеющихся там данных);
Q удаляются все строки, свойство которых RowState имеет значение Deleted;
Q свойству всех записей RowState присваивается значение Unchanged.
Метод AcceptChanges доступен на трех уровнях. Можно вызвать данный метод для строки (для объекта DataRow), но тогда завершаются изменения только в одной строке. Можно также вызвать этот метод для таблицы (для объекта DataTable), в результате чего изменения будут зафиксированы во всех строках таблицы. И, наконец, метод можно применить ко всему набору данных (для объекта DataSet), вследствие чего будут завершены все изменения во всех записях всех таблиц набора данных.
В табл. 2.13 показано, какие изменения будут завершены в зависимости от того, к какому объекту адресован метод AcceptChanges.
Таблица 2.13. Результат работы метода AcceptChanges в зависимости от связанного с ним объекта
МетодРезультат работы метода
DataRow.AcceptChangesЗавершение изменений только в определенной строке
DataTable.AcceptChanges Завершение изменений во всех строках определенной таблицы
DataSet.AcceptChanges Завершение изменений во всех строках, во всех таблицах набора данных
Примечание
Если происходит загрузка набора данных путем вызова метода Fill адаптера данных, то не нужно явно вызывать метод AcceptChanges, так как по умолчанию метод Fill вызовет его автоматически после завершения загрузки данных.
С методом AcceptChanges связан другой метод— RejectChanges, который выполняет противоположное действие — отменяет все изменения. При вызове метода RejectChanges происходит копирование столбцов строки первоначальной версии в строку текущей версии, а свойству Rowstate каждой записи присваивается значение Unchanged.
Проверка правильности данных
Как правило, в приложениях требуется проверка корректности вводимой пользователем информации или проверка данных, получаемых от других приложений на размерность, на соответствие типа, на принадлежность определенному интервалу и т. п.
Проверку корректности данных можно выполнить несколькими способами.
О На уровне объектов отображения информации в формах. В этом случае проверка данных выполняется при работе с элементами форм. Если вы работаете с Web-формами, то для проверки корректности данных можно использовать соответствующие визуальные элементы управления. Если вы работаете с Windows-формами, то обычно такая проверка осуществляется на уровне объектов RichTextBox или TextBox. Другой способ управлять корректностью вводимых пользователем данных в Windows-форме — использование элемента Masked Edit Control.
Q На уровне источника данных. В таком случае при отправлении информации к источнику данных можно запрограммировать правила приема или отклонения получаемых данных. Если вы работаете с базой данных, которая имеет соответствующие средства для того, чтобы подтвердить правильность получаемой информации и обеспечивает возврат в приложение сведений об ошибках, то это может быть достаточно эффективным подходом, потому что есть возможность проверить правильность данных независимо от того, откуда они поступили. Однако, эти средства проверки, как правило, более "бедные" чем те, которые используются на уровне приложений. Кроме того, это может привести к многочисленным излишним шагам по передачи информации от приложения к базе данных и обратно.
Q На уровне бизнес-правил (в трехуровневых приложениях). В данном случае проверка корректности вводимой информации происходит на
уровне бизнес-логики приложения. Такой способ эффективно использовать при работе с наборами данных. Набор данных обеспечивает поддержку нескольких версий записей, что дает возможность сравнить измененные записи с первоначальными без дополнительных обращений к источнику данных, принять сделанные изменения или откатиться назад. Этот метод сочетает достоинства двух предыдущих, так как на уровне бизнес-логики есть возможность проверить корректность данных независимо от того, где и кем были сделаны изменения. При этом нет необходимости обращаться к источнику данных и можно обеспечить достаточно сложную и специфичную для конечных приложений логику проверки правильности данных.
Модификация, вставка и удаление записей в наборе данных
После того, как объект DataSet заполнен данными, пользователи приложения обычно модифицируют полученную информацию, и затем эти изменения пересылаются источнику данных. Так как отдельные записи в DataSet представлены объектом DataRow, то все изменения в набор данных производятся путем модификации, добавления и удаления индивидуальных строк.
Модифицирование существующих записей в наборе данных
Чтобы выполнить редактирование какого-либо значения в наборе данных, необходимо обратиться к конкретному столбцу в определенной строке. К определенному значению в наборе данных можно обратиться следующим образом:
Q через индексы таблиц, строк и коллекций столбцов;
Q передавая в соответствующие коллекции наименования таблиц и столбцов как строковые переменные.
Модифицирование записей в типизированных и нетипизированныхнаборахданных
Наименования таблиц и столбцов в наборах данных без контроля типов не доступны во времени разработки приложения и к ним нужно обращаться через их соответствующие индексы.
Следующий пример (листинг 2.20) показывает, как изменить данные в первых двух столбцах пятой записи первой таблицы объекта dataset1, обращаясь к таблицам, строками и столбцам через индексы соответствующих коллекций (нумерация элементов в коллекциях начинается с нуля).
Листинг 2.20
' Visual Basic
dataset1.Tables(0).Rows(4).Item(0)="Wingtip Toys"
dataset1.Tables(0).Rows(4).Item(l)="Buffalo"
H c#
dataset1.Tables [0] .Rows [4].ItemArray [0]="Wingtip Toys";
dataset1.Tables[0].Rows[4].ItemArray[l]="Buffalo";
Пример, записанный в листинге 2.21, показывает, как необходимо модифицировать те же самые данные (из предыдущего примера, листинг 2.20), используя вместо индексов коллекций наименование таблицы и имена столбцов.
Листинг 2.21
' Visual Basic
dataset1.Tables("Customers").Rows(4).Item("CompanyName")="Wingtip Toys"
dataset1.Tables("Customers").Rows(4).Item("City")="Buffalo"
// c#
dataset1.Tables["Customers"].Rows[4] ["CompanyName"]="Wingtip Toys";
dataset1.Tables["Customers"].Rows[4] ["City"]="Buffalo";
Модифицирование записей в типизированных наборах данных
В типизированных наборах данных используется раннее связывание, за счет чего имена таблиц и столбцов доступны на этапе разработки приложения. Это позволяет создавать более удобочитаемый программный код.
Пример в листинге 2.22 показывает, как можно модифицировать данные в столбцах CompanyName и city в пятой записи таблицы customers в наборе данных DsCustomers1.
Листинг 2.22 -
' Visual Basic
DsCustomers1.Customers(4).CompanyName="WingtipToys"
DsCustomers1.Customers(4).City="Buffalo"
// C#'
dsCustomers1.Customers[4].CompanyName="Wingtip Toys";
dsCustomers1.Customers[4].City="Buffalo";
Добавление записей в набор данных
Чтобы добавить запись в набор данных, необходимо создать новую строку и добавить ее к коллекции DataRow соответствующей таблицы. Следующий пример показывает, как вставить дополнительные строки в объект DataTable набора данных. В этом примере предполагается, что в наборе данных присутствует таблица с именем ExistingTable, которая имеет два Столбца С именами FirstName И LastName.
Добавление записи в набор данных происходит следующим образом.
Вызовите метод таблицы данныхNewRow, который создает новую пустую запись.
Эта новая запись наследует коллекцию столбцов DataColumnCollection от исходной таблицы данных (листинг 2.23).
Листинг 2.23
' Visual Basic
Dim anyRow as DataRow=ExistingTable.NewRow
// C#
DataRow anyRow=ExistingTable.NewRow();
Присвойте колонкам этой строки требуемые значения (листинг 2.24).
Листинг 2.24
' Visual Basic
'Обращение к столбцам по номеру в коллекции
anyRow(0)="Jay"
anyRow(l)="Stevens"
'или обращение к столбцам по их именам
anyRow("FirstName")="Jay"
anyRow("LastName")="Stevens"
// C#
//Обращение к столбцам по номеру в коллекции
anyRow[0]="Jay";
anyRow[1]="Stevens";
// или обращение к столбцам по их именам
anyRow["FirstName"]="Jay";
anyRow["LastName"]="Stevens";
Добавьте новую запись в таблицу, вызвав метод Addобъекта
DataRowCollection (ЛИСТИНГ 2.25).
! Листинг 2.25
' Visual Basic
ExistingTable.Rows.Add(anyRow)
// C#
ExistingTable.Rows.Add(anyRow) ;
Добавление новых записей в типизированный набор данных
Типизированные наборы данных позволяют работать с именами столбцов как со свойствами объекта DataRow.
Следующий пример (листинг 2.26) иллюстрирует те же самые шаги, которые были показаны в предыдущем разделе.
Листинг2.26
' Visual Basic
Dim anyRow as DataRow=DatasetName.ExistingTable.NewRow anyRow.FirstName="Jay" anyRow.LastName="Stevens"
ExistingTable.Rows.Add(anyRow)
// C#
DataRow anyRow=DatasetName.ExistingTable.NewRow();
anyRow.FirstName="Jay";
anyRow.LastName="Stevens";
ExistingTable.Rows.Add(anyRow);
Удаление записей из набора данных
Если в приложении после удаления записи в наборе данных требуется сделать то же самое и в источнике данных, то необходимо использовать метод Delete таблицы данных. Если ваше приложение не должно пересылать обновления назад источнику данных, тогда возможно прямое удаление записи из коллекции строк.
Для удаления записи из таблицы данных вызовите метод Delete. Этот метод физически не удаляет запись из набора данных; он просто меняет ее статус — отмечает как удаленную запись, и она становится невидимой (перестает быть доступной конечному пользователю приложения).
Примечание
Если вы желаете получить число записей в таблице через свойство Count объекта DataRowCollection, то будут просуммированы и записи, которые отмечены как удаленные. Получить точное количество записей таблицы (без учета удаленных) можно путем их подсчета в цикле по коллекции, с проверкой свойства RowState каждой записи. В качестве альтернативы можно создать представление набора данных, которое отфильтрует неудаленные записи, и получить количество записей из свойства Count созданного представления.
Следующий пример (листинг 2.27) показывает, как вызвать метод Delete для удаления первой строки таблицы customers набора данных DsCustomers1.
Листинг 2.27
' Visual Basic
DsCustomers1.Customers.Rows(0).Delete()
// C#
DsCustomers1.Customers.Rows[0].Delete();
События при обновлении данных
Когда происходит обновление (модификация) записей, то в объекте DataTable активизируются определенные события, в обработчике которых можно запрограммировать требуемые действия как до, так и после обновления записи.
Если в приложении используется типизированный набор данных, то можно создать обработчики событий со строгим контролем типов. Это позволяет задействовать четыре дополнительных события, для которых можно создать соответствующиеобработчики:dataTableNameRowChanging,
dataTableNameRowChanged,dataTableNameRowDeleting,И
dataTableNameRowDeleted. Обработчики этих событий имеют параметры, среди которых есть имена столбцов вашей таблицы, что делает код удобочитаемым.
События обновления данных описаны в табл. 2.14.
Таблица 2.14. События обновления данных в объекте Data Table
Событие
Описание
Columnchanging
Значение в столбце изменяется (в данный момент). Событие передает строку и столбец наряду со значением колонки, в которое вносятся изменения
ColumnChanged
Значение в столбце было изменено. Событие передает строку и столбец наряду с предложенным значением
RowChanging
Изменения, сделанные в объекте DataRow собираются быть завершенными и переданными назад в набор данных. Если вы не вызвали метод BeginEdit, то событие RowChanging происходит для каждого изменения в столбце, немедленно после того, как произошло событие ColumnChanging. Если вы вызывали метод BeginEdit перед созданием изменений, то событие RowChanging происходит только тогда, когда вы вызываете метод EndEdit
Событие передает строку и значение, указывающее, какое было сделано действие (замена, вставка, удаление и так далее)
RowChanged
Строка была изменена. Событие передает строку и значение, указывающее, какое было сделано действие (замена, вставка, удаление и так далее)
RowDeleting
Строка удаляется. Событие передает строку и значение, указывающее, какое действие выполняется
RowDeleted
Строка была удалена. Событие передает строку и значение, указывающее, какое действие выполняется
События ColumnChanging, RowChanging И RowDeleting ПРОИСХОДЯТ В течение процесса обновления. Вы можете использовать эти события, чтобы проверить правильность данных или использовать их для других видов обработки. Поскольку обновления еще не завершены в течение этих событий, то можно отменить обновления, или обработать ошибку, которая может препятствовать завершению обновления.
События ColumnChanged, RowChanged И RowDeleted ЯВЛЯЮТСЯ событиями уведомления, которые происходят тогда, когда обновление было закончено успешно. Эти события полезны тогда, когда вы хотите запрограммировать действия, основанные науспешном обновлении данных.
Приостановка действия ограничений
при изменении данных
Если набор данных содержит ограничения (например, ограничение внешнего ключа), то при обновлении колонки в записи может произойти наруше-
ние ограничения (например, пользователь изменил значение ключевого поля). После того, как было закончено обновление одной колонки и выполняется переход к другой колонке, запись может оказаться в состоянии ошибки. Например, в наборе данных имеется таблица с двумя колонками, в которых не допускается наличие пустых значений (null). После создания новой записи оба поля будут содержать пустое значение. Допустим, пользователь изменил значение одной колонки и пытается перейти к следующей, но в этот момент сработает ограничение, поскольку следующее поле будет пустым (пользователь не можете одновременно редактировать две колонки). Если бы не было никакого механизма, позволяющего временно приостанавливать действие ограничения, то ошибка возникала бы каждый раз при попытке сдвинуться с редактируемой колонки.
Приостановка действия ограничения при обновлении данных.
Перед внесением изменений в колонку строки данных вызовите метод BeginEdit объекта DataRow.
Примечание
Все изменения данных, которые вы сделаете в строке после вызова метода BeginEdit, будут сохранены.
Сделайте изменение данных в строке.
Вызовите метод EndEdit для завершения изменений в строке и включения проверки ограничения,
Активизируется событие RowChanging.
Вызовите метод CancelEdit, если необходимо отказаться от изменений, сделанных в данной записи.
Следующий пример (листинг 2.28) демонстрирует простое внесение изменений в запись данных с использованием методов BeginEdit и EndEdit. В этом примере предполагается, что изменяется содержание пятой строки таблицы customers в типизированном наборе данных с именем DsCustomers1.
Листинг 2.28 —:. ——-—
' Visual Basic
DsCustomers1.Customers(4).BeginEdit()
DsCustomers1.Customers(4).CompanyName="Wingtip Toys"
DsCustomers1.Customers(4).City="Buffalo"
DsCustomers1.Customers(4).EndEdit()
C#
dsCustomers1.Customers[4].BeginEdit();
dsCustomers1.Customers[4].CompanyName="WingtipToys";
dsCustomers1.Customers[4].City="Buffalo";
dsCustomers1.Customers[4].EndEdit() ;
Слияниенаборовданных
Вы можете объединять наборы данных. При этом содержание одного набора данных (исходный) передается в другой набор данных (целевой). Ниже приведены некоторые примеры, когда используется объединение наборов данных.
Q В приложении имеется основной набор данных, с которым работает пользователь, и оно получает второй набор данных, который должен быть добавленным к первому. Это типичный сценарий взаимодействия приложения с XML Web-сервисом, который в результате своей работы возвращает приложению набор данных.
Q Ваше приложение получает наборы данных от двух различных компонент (от двух различных XML Web-сервисов), но далее пользователь должен работать с единым информационным массивом.
Чтобы копировать информацию одного набора данных в другой используется метод Merge. Вы можете регулировать процесс объединения данных:
Q добавить новые записи в один набор данных, копируя их из другого набора данных;
Qобновитьсостояниезаписейв одномнабореданных,наосновеинфор
мации другого набора данных. В этой ситуации второй набор данных содержит информацию не только о новых записях, но также и об измененных и удаленных записях, и вы хотите, чтобы в первом наборе данных были отражены все эти изменения;
Q копировать не только данные, но и определять, что делать, если наборы данных имеют разную структуру.
Для слияния наборов данных вызовите метод Merge для целевого набора данных, передав ему в качестве параметра исходный набор данных.
Следующий пример (листинг 2.29) показывает, как объединить два набора данных С установленным ПО умолчанию СВОЙСТВОМ PreserveChanges=false.
Листинг 2.29
' Visual Basic
targetDataset.Merge(sourceDataset)
// C#
targetDataset.Merge(sourceDataset);
Следующий пример (листинг 2.30) показывает, как объединить два набора данных с установленным свойством PreserveChanges=true.
Листинг 2.30
' Visual Basic
targetDataset.Merge(sourceDataset, True)
// C#
targetDataset.Merge(sourceDataset, true);
Завершение изменений в наборе данных
В наборе данных при внесении изменений в записи (обновление, вставка, удаление) поддерживается и первоначальная (оригинальная), и текущая версии записей. Кроме того, в свойстве RowState каждой записи установлен признак (указатель), находятся ли запись в первоначальном состоянии или она была изменена. Эта информация необходима, когда требуется найти определенную версию строки. Как правило, в приложениях возникает необходимость передачи между компонентами только измененных записей. После того, как проведена нужная обработка всех измененных записей, можно завершить процедуру обновления, вызвав метод набора данных AcceptChanges.
Следующий пример (листинг 2.31) показывает, как вызвать метод AcceptChanges для завершения изменений в таблице Customers после передачи обновлений источнику данных.
Листинг 2.31
' Visual Basic
"Customers")"Customers")OleDbDataAdapter1.Update(Dataset1,
"Customers")
"Customers")
Dataset1.Customers.AcceptChangea{)
// C#
OleDbDataAdapter1.Update(Dataset1, "Customers");
Dataset1.Customers.AcceptChanges();
Завершение слияния наборов данных
Для завершения слияния наборов данных нужно выполнить следующие действия:
вызовите метод слияния наборов данных Merge;
вызовите метод завершения обновления данных AcceptChanges.
Следующий пример (листинг 2.32) показывает, как завершить процедуру изменения набора данных после копирования в него информации из другого набора данных.
Листинг 2.32
' Visual Basic
Dataset1.Merge(Dataset2)
Dataset1.AcceptChanges()
// C#
Dataset1.Merge(Dataset2);
Dataset1.AcceptChanges();
Передача изменений набора данных в источник данных
После того, как содержание набора данных было изменено и эти изменения завершены (приняты), то в большинстве приложений следующим шагом необходимо передать эти изменения основной базе данных (источнику данных). В данном разделе описываются основные принципы обновления баз данных, источников данных, а также возможности обработки потенциальных ошибок.
Обновление баз данных из наборов данных
После того, как были сделаны изменения в наборе данных, их можно передать источнику данных. Обычно это делается путем вызова метода Update адаптера данных. Данный метод в цикле просматривает все записи таблицы и определяет, какие операции необходимо выполнить (обновление, добавление или удаление), и, если таковые вообще имеются, выполняет соответствующие команды.
Как обновления передаются источнику данных
Для простоты иллюстрации обновления базы данных предположим, что набор данных содержит одну таблицу, а в результате работы приложения из базы данных в объект DataSet было выбрано две строки (табл. 2.15).
Таблица 2.15. Строки объекта DataSet до обновления в них информации
RowState
CustomerID
Name
Status
(Unchanged)
c200
Robert Lyon
Good
(Unchanged)
c400
Nancy Buchanan
Pending
В приложении пользователь во второй строке изменяет статус клиента Nancy Buchanan с Pending на Preferred. В результате этого изменения значение свойства DataRow.RowState для второй строки изменится с Unchanged на Modified. Значение данного свойства для первой строки остается неизменным (unchanged). Результирующий вид таблицы данных в объекте DataSet показан в табл. 2.16.
Таблица 2.16. Строки объекта DataSet после обновления второй строки
RowState
CustomerID
Name
Status
Unchanged
c200
Robert Lyon
Good
Modified
c400
Nancy Buchanan
Preferred
В приложении после этого вызывается метод update для того, чтобы передать обновленный набор данных назад к базе данных. Данный метод поочередно просматривает каждую строку. Для первой строки, метод не применяет никакого SQL-запроса (команду DataCommand), потому что эта строка не изменялась с тех пор, как была получена из базы данных (она имеет при- знакUnchanged).
Однако для второй строки метод Update автоматически вызовет надлежащую команду данных (DataCommand) и обновит на ее основе соответствующую строку в базе данных. Синтаксис SQL-запроса будет зависеть от диалекта языка SQL, поддерживаемого основным хранилищем данных. Но независимо от синтаксиса сама структура SQL-запроса будет следующая.
Q Будет задействован SQL-запрос с предложением UPDATE. Адаптер данных знает (OleDbDataAdapter ИЛИ SQLDataAdapter), ЧТО Предложение UPDATE применяется для тех строк, свойства Rowstate которых имеет значение Modified.
Q В SQL-запрос будет включено предложение WHERE, указывающее, что обновляться будет строка, для которой CustomerID='c400'. Эта часть SQL-запроса отличает целевую строку от всех других строк, потому что поле CustomerID является первичным ключом таблицы базы данных. Информация для предложения WHERE будет получена не из текущей, а изоригинальной(первоначальной)версиизаписи
(DataRowVersion.Original), потому что в текущей версии записи пользователь мог изменить значение первичного ключа.
Q В SQL-запрос будет включено предложение SET, для того, чтобы установить новые значения столбцов в соответствующей записи таблицы базы данных.
Примечание
Если у адаптера данных в свойстве UpdateCommand было задано имя хранимой процедуры, то вместо SQL-запроса будет вызвана хранимая процедура с соответствующими параметрами.
Передача параметров
Значения колонок для записей, которые будут модифицированы в базе данных, обычно передаются через метки-заполнители. Когда вызывается на выполнение метод update адаптера данных, то он по сути дела выполняет SQL-инструкцию UPDATE, которая в свою очередь нуждается в присвоении меткам-заполнителям конкретных значений. Эти значения SQL-инструкция получает из коллекции параметров (Parameters) соответствующей команды данных (в данном конкретном случае задействована команда UpdateCommand адаптера данных).
Если для генерирования адаптера данных был задействован соответствующие мастера Visual Studio, то объект UpdateCommand будет содержать коллекцию параметров, каждый из которых корреспондируется с соответствующими метками-заполнителями в SQL-инструкции.
Для класса OleDbDataAdapter очень важен порядок расположения параметров и меток-заполнителей (говорят, что "они чувствительны к позиции"): то есть первая метка-заполнитель в SQL-инструкции получит значение из первого параметра коллекции, вторая из второго и т. д. Для класса SqlDataAdapter порядок расположения параметров не имеет значения, поскольку обращение к параметрам осуществляется по их именам, а не на основе их позиций в коллекции.
Свойство SourceColumn каждого параметра содержит ссылку на соответствующую колонку таблицы данных. Когда выполняется метод update адаптера данных, то он считывает значения столбцов из модифицируемых записей и присваивает эти значения меткам-заполнителям SQL-запроса.
При обновлении информации в базах данных инструкция UPDATE должна получать как новое, так и старое значение соответствующей колонки. Новое значение колонки нужно для того, чтобы подменить им устаревшее значение колонки. Старое значение колонки необходимо для того, чтобы найти в базе данных ту запись, которую нужно модифицировать. Поэтому существует два параметра для каждого значения колонки: один параметр для предложения SET, второй — для предложения WHERE. Оба параметра
получают значение от модифицируемых записей, но они используют различные версии значения столбца (с использованием свойства SqlParameter.SourceVersion). Параметр для предложения SET использует текущую версию, а параметр для предложения WHERE использует оригинальную версию.
Примечание
Вы можете также установить значения элементам коллекции Parameters самостоятельно в программном коде, для чего обычно используется обработчик события адаптера данных RowChanging,
Обработка исключительных ситуаций при обновлении источника данных из набора данных
После того, как набор данных был изменен и эти изменения приняты, приложение должно вернуть новые данные назад источнику данных. Чтобы модернизировать источник данных содержанием набора данных вызывается метод Update адаптера данных. Адаптер данных выполнит соответствующую команду (insert, update или delete), используя значение свойства Rowstate каждой строки набора данных.
Примечание
Поскольку попытка модернизировать источник данных содержанием набора данных может закончиться ошибкой, то обычно вызов метода update адаптера данных делается внутри блока Try...Catch.
Процедура модернизации источника данных зависит от требований конкретного приложения, но в любом случае должны быть выполнены следующие шаги.
Вызов метода Update адаптера данных должен выполняться внутри блока Try...Catch.
Если возникла исключительная ситуация, то нужно определить при обработке какой строки набора данных произошла ошибка.
Исправление возникшей проблемы в строке данных (либо программным способом, либо, представив пользователю ошибочную строку для внесения в нее изменений), и затем — повторная попытка модернизации источника данных.
Следующий пример (листинг 2.33) показывает, как делать модернизацию источника данных внутри блока Try...Catch содержанием набора данных с именемmyDataset.
Листинг 2.33
' Visual Basic
Try
oleDbDataadapter1.Update(myDataset)
Catch x As Exception
'Код обработки ошибочной ситуации.
End Try
// C# try {
oleDbDataAdapter1.Update(myDataset);
}
catch (Exception e)
{
// Код обработки ошибочной ситуации.
}
Обновление связанных таблиц
Если в наборе данных содержится несколько таблиц, то их необходимо модифицировать индивидуально, вызывая отдельно метод Update каждого адаптера данных. Если таблицы имеют реляционные отношения, то потребуется специфическое обновление базы данных. Обычно в этом случае изменяются и родительская и связанные дочерние записи набора данных. Например, при добавлении нового клиента формируется одна или более связанных записей заказов этого клиента. Если в самой базе данных заданы правила обеспечения целостности, то при обновлении возможно возникновение ошибок. Например, если переслать в базу данных вновь появившиеся дочерние записи раньше, чем была переслана родительская запись. Поэтому необходимо выполнять определенную последовательность в пересылке: сначала должны послаться новые родительские записи, а потом дочерние.
Наоборот, если вы удаляете связанные записи в наборе данных, необходимо посылать обновления в базу данных в обратном порядке: сначала от дочерней таблицы, потом от родительской. В противном случае при обновлении информации в базе данных возникнет ошибка, потому что правила обеспечения целостности не позволят удалить родительскую запись, пока существуют связанные дочерние записи.
Последовательность обновления связанных таблиц
При обновлении связанных таблиц набора данных очень важно соблюдать определенную последовательность, чтобы не нарушить целостность данных основного источника и не сгенерировать ошибочную ситуацию. Чтобы предотвратить возможные ошибки нарушения целостности данных необходимо модернизировать источник данных в следующей последовательности:
Q дочерняя таблица: удалить записи;
Q родительская таблица: добавить, изменить или удалить записи;
Q дочерняя таблица: добавить или изменить записи.
Для модернизации источника данных из набора данных, который содержит две или более связанных таблиц вызовите метод Update каждого адаптера данных.
Примечание
Чтобы уменьшать число обращений к источнику данных, можно объединить несколько наборов данных в один перед вызовом метода Update (если это допускает логика работы конкретного приложения).
Следующий пример (листинг 2.34) показывает, как модернизировать источник данных из набора данных, который содержит связанные таблицы. Чтобы следовать за вышеупомянутой последовательностью, создаются три временных набора данных дочерней таблицы, которые содержат только добавленные, только удаленные и только измененные записи. Метод Update вызывается для каждого поднабора данных внутри блока Try...Catch. Если при обновлении возникнут ошибки, то они будут перехвачены и обработаны также внутри этого блока (в обработчике исключительных ситуаций). После обновления источника данных вызывается метод AcceptChanges, который "принимает" сделанные изменения и, наконец, удаляются временные наборы данных, чтобы освободить ресурсы.
Листинг 2.34
' Visual Basic
Private Sub Update_Attempt()
' Набор ds1 содержит только удаленные записи дочерней таблицы- Dim ds1 as DataTable =%►
anyDataset.ChildTableName.GetChanges(DataRowState.Deleted)
' Набор ds2 содержит только добавленные записи дочерней таблицы.
Dim ds2 as DataTable = Ъ
anyDataset.ChildTableName.GetChanges(DataRowState.Added)
' Набор ds3 содержит только измененные записи дочерней таблицу.
Dim ds3 as DataTable =ъ
anyDataset.ChildTableName.GetChanges(DataRowState.Modified)
Try
'Удаление записей дочерней таблицы
DataAdapter2.Update(ds1)
' Добавление и удаление записей родительской таблицы DataAdapter1.Update(anyDataset, "ParentTable")
'Добавление записей в дочернюю таблицу
DataAdapter2.Update(ds2)
'Обновление записей дочерней таблицы
DataAdapter2.Update(ds3)
'Завершение процесса модернизации набора данных
anyDataset.AcceptChanges
'Удаление временных наборов данных
ds1.Dispose()
ds2.Dispose()
ds3.Dispose()
Catch x As Exception
' Обработчик ошибочных (исключительных) ситуаций.
End Try
End Sub
// C#
void Update_Attempt()
{
// Набор ds1 содержит только удаленные записи дочерней таблицы.
DataTable ds1= ъ
anyDataset.ChildTableName.GetChanges(DataRowState.Deleted);
// Набор ds2 содержит только добавленные записи дочерней таблицы. DataTable ds2= ъ
anyDataset.ChildTableName.GetChanges(DataRowState.Added);
// Набор ds3 содержит только измененные записи дочерней таблицы.
DataTable ds3= ъ
anyDataset.ChildTableName.GetChanges(DataRowState.Modified);
try
{
//Удаление записей дочерней таблицы
DataAdapter2.Update(ds1);
// Добавление и удаление записей родительской таблицы
DataAdapter1.Update{anyDataset,"ParentTable"};
// Добавление записей в дочернюю таблицу
DataAdapter2.Update(ds2);
// Обновление записей дочерней таблицы
DataAdapter2.Update(ds3);
// Завершение процесса модернизации набора данных
anyDataset.AcceptChanges();
// Удаление временных наборов данных
ds1.Dispose();
ds2.Dispose();
ds3.Dispose();
}
catch (Exception x)
{
// Обработчик ошибочных (исключительных) ситуаций.
}
)
Регенерация набора данных
Во многих случаях, после обновления источника данных, возникает необходимость обновить набор данных (выполнить его повторное заполнение). С одной стороны повторное обновление DataSet приводит к дополнительной загрузке канала связи, однако в некоторых случаях обновление технологически необходимо, в частности для того, чтобы получить изменения, сделанные в базе данных другими пользователями.
Q В наборе данных будут отражены изменения, которые могли быть сделаны в базе данных другими пользователями.
Q Получат значения те колонки, которые рассчитываются на уровне базы данных (колонки типа счетчик, значения колонок по умолчанию).
Q Произойдет обновление значение timestamp в записях набора данных (если необходим контроль параллелизма при одновременной работе с данными нескольких пользователей).
Можно обновить набор данных вручную, вызвав метод Fill адаптера данных, после того, как была обновлена база данных.
В качестве альтернативы, можно сконфигурировать адаптер данных таким образом, чтобы автоматически выполнить предложение SELECT в SQL- запросе или хранимой процедуре сразу после выполнения обновления базы данных. В этом случае адаптер данных создает два SQL-запроса на объекты UpdateCommand и InsertCommand. Первый запрос будет ВЫПОЛНЯТЬ обновление базы данных, а второй запрос (с предложением SELECT) -- повторное заполнение набора данных.
Контроль параллелизма
Поскольку наборы данных оторваны из источника данных, то нет постоянного соединения с исходной базой данных. Если с одной и той же информацией одновременно работает несколько пользователей, то важно осуществлять контроль параллелизма. Ведь пока один пользователь работает с записью набора данных, другой может в это же время модернизировать ту же запись. Если параллелизм не будет поддерживаться, то, после обновления базы данных, труды одного пользователя будут "затерты" действиями другого. В таких ситуациях перед возвратом обновления в базу данных необходимо обязательно проверить, не изменялась ли исходная запись с того момента, как она была загружена в DataSet. В том случае, если запись изменялась, необходимо добавлять программный код, позволяющий обработать возникшую ситуацию. Логика кода будет зависеть от требований конкретного приложения.
Обработка ошибок модернизации источника данных
При попытке модернизации данных могут возникнуть ошибки. Типичная ошибка заключается в том, что содержимое записи в базе данных может измениться с тех пор, как она была загружена в набор данных (изменение может внести другой пользователь). Независимо от причины ошибки необходимо реализовать процедуру ее обработки, чтобы обеспечить корректное обновление записи.
Чтобы определить запись, при обработке который возникла ошибка, ваше приложение должно определить номер этой записи, устранить причину возникновения ошибочной ситуации, и повторить попытку модернизации данных.
После того, как запущена на выполнение команда модернизации источника данных, в адаптере данных возникает событие RowUpdated для каждой записи, которую затрагивает процесс обновления. В обработчике данного события вы можете определить, была ли модернизация завершена успешно. Вы
можете также установить свойство status для задания дальнейших действий, т. е. должна ли команда update продолжить обрабатывать следующие записи или прекратить процедуру обновления после того, как возникла ошибка.
Для обработки ошибок обновления выполните следующее.
Создайте соответствующий обработчик для события RowUpdated.
Проверьте свойство status для события RowUpdated.
Примечание
При наличии ошибки свойство status будет иметь значение ErrorsOccurred.
Есливыхотитепродолжитьобновление,тозадайтесвойствуStatus
допустимое значение(изспискадопустимыхзначений
UpdateStatus), Выможете такжеиспользоватьсвойство
IgnoreUpdateErrors адаптера данных для продолжения обновления в случае возникновения ошибки.
Определите номер ошибочной строки через свойство RowError в обработчике ошибки. Эта информация содержится в свойстве HasErrors набора данных.
Следующий пример (листинг 2,35) иллюстрирует, как можно проверить успешность обновления данных строки в обработчике события RowUpdated. Если возникла ошибка, то свойство RowError строки данных устанавливается в состояние ошибки, при этом свойство HasErrors автоматически принимает значение true. В таком случае вы можете обработать ошибку с учетом ее типа и логики работы конкретного приложения. Дополнительно вы можете присвоить свойству status значение, позволяющее продолжать обрабатывать оставшиеся записи (с возможностью пропустить оставшиеся строки или пропустить только текущую строку).
Листинг2.35
' Visual Basic
Private Sub 01eDbDataAdapterl_RowUpdated(ByVal sender As Object,%>
ByVal e As System.Data.OleDb.OleDbRowDpdatedEventArgsъ
Handles OleDbDataAdapter1.RowUpdated
If e.Status=UpdateStatus.ErrorsOccurred Then
e.Row.RowError=e.Errors.Message
' Добавьте код обработки ошибки.'
End If
End Sub
// C#
private void OleDbDataAdapter1_RowUpdated(object sender, %- System. Data.OleDb.OleDbRowUpdatedEventArgs e)
{
if (e.Status==UpdateStatus.ErrorsOccurred)
{
e.Row.RowError=e.Errors.Message;
// Добавьте -код обработки ошибки.
}
}
Во второй главе вы познакомились с отделенным набором данных. Однако в ADO.NET это не единственная возможность работы с базой данных. Но об этом речь в следующей главе.
ГЛАВА 3
Прямой доступ к базе данных и стратегии доступа к данным
ADO.NET позволяет работать с базой данных не только через объект DataSet, но и напрямую. Для этого служат объекты DataCommand. Вместо того чтобы работать с отделенным набором данных, можно вносить исправления непосредственно в базу данных, минуя временное сохранение. Какой способ обращения с данными предпочтительней -- зависит от специфики приложения. В этой главе мы попробуем сформулировать стратегии доступа к данным.
Из материалов третьей главы вы узнаете:
Q как можно работать непосредственно с таблицами удаленной базы данных с ПОМОЩЬЮ объектов DataCommand;
Q какой стратегии доступа к данным необходимо придерживаться при создании различных типов клиентских приложений.
И начнем мы со знакомства с объектом DataCommand.
Прямой доступ к базе данных
В ADO.NET есть два основных способа, обеспечивающих взаимодействие приложения с данными: использование набора данных (DataSet), работа непосредственно с элементами базы данных (с таблицами, представлениями, хранимыми процедурами и т. п.). В "отсоединенной" модели работы с данными на основе DataSet вы создаете в памяти компьютера некое пустое хранилище, загружаете его данными, используя адаптер данных, работаете с этой информацией (сортируете, фильтруете, изменяете), и затем, по мере
необходимости, через тот же адаптер данных, возвращаете все изменения назад в исходную базу данных.
В качестве альтернативы можно работать непосредственно с базой данных. В этой модели используется объект DataCommand, в котором содержится SQL-запрос или имя хранимой процедуры. Команда запускается на исполнение, и если команда не возвращает результата (например, удаление записей), то все действия команды выполняются непосредственно над объектами базы данных (например, удаляется запись из таблицы). Если в результате работы команды из базы возвращается набор записей, то используется объект DataReader для выборки данных.
В некоторых случаях задача вообще не решается путем использования набора данных. Например, если требуется создать элемент базы данных (типа таблица), то это можно сделать только с помощью команд (объектов DataCommand).
Общие сведения об объекте DataCommand
Команда данных содержит ссылку на SQL-запрос или хранимую процедуру, которые собственно и реализуют конкретные действия. Команда данных — экземпляр классаOleDbCommandили класса SqlCommand. Как и многие другие подобные классы, OleDbCommand используется как средство доступа к любымданнымнаосновеOLEDB-провайдера, втовремякаккласс
SqlCommand оптимизирован для работы с SQL Server версии 7.0 и выше.
С использованием объекта DataCommand в приложении можно выполнить следующие действия,
О Исполнять команды SELECT, которые возвращают набор записей. Причем этот набор можно обрабатывать непосредственно, без его загрузки в набор данных DataSet. Для чтения результатов используются объекты OleDbDataReader ИЛИ SqlDataReader, которые работают В режиме readonly, forward-only (только чтение, только вперед) и могут быть связаны с компонентом визуального отображения данных. Эти объекты полезно использовать в тех случаях, когда имеет место ограничение на ресурсы памяти или требуется высокая скорость загрузки данных.
Q Выполнять DDL-команды (Database Definition Commands, команды определения базы данных), обеспечивающих создание, редактирование, удаление таблиц, хранимых процедур и других элементов базы данных.
Q Выполнять команды, обеспечивающие получение информации из каталогов баз данных.
Q Выполнять динамические SQL-команды, позволяющие модифицировать, вставлять или удалять записи непосредственно в базе данных, вместо то-
го, чтобы редактировать таблицы набора данных DataSet, а затем копировать эти изменения в базу данных.
Q Выполнять команды, которые возвращают скалярное значение, то есть единственное число или строку (результат поиска пароля пользователя, расчет суммы счета и т.п.).
Q Выполнять команды, которые возвращают данные из базы данных SQL Server (версия 7.0 и выше) в формате XML. Эта возможность используется в Интернет-приложениях. Например, когда нужно выполнить запрос и получить данные в формате XML, обратиться к XSLT-конвертору, чтобы преобразовать данные к HTML-формату и затем послать их браузеру.
Работа объектов DataCommand
Свойства объектов DataCommand содержат всю информацию, необходимую для выполнения команд.
Q Connection. Ссылка команды на объект connection, который обеспечивает установление связи с базой данных.
Q Имя или текст команды. Команда включает текст SQL-запроса или имя хранимой процедуры.
Q Parameters. Команда может потребовать, чтобы ей передали значения параметров (входные параметры). Кроме того, команда может иметь и возвращаемые параметры в виде одного или нескольких значений. Каждая команда имеет коллекцию параметров, которые вы можете настроить индивидуально для передачи или получения значений.
Для выполнения команды данных нужно вызвать тот метод, который соответствует возвращаемым результатам. Например, если вы собираетесь получить набор записей, то нужно использовать метод ExecuteReader, который возвращает записи объекту DataReader. Если требуется выполнить обновление, вставку или удаление записей, то требуется вызывать метод ExecuteNonQuery, который возвращает значение количества обрабатываемых строк.
Множественные результирующие наборы записей
Обычно при исполнении команда данных возвращает единственный результирующий набор. Однако команды данных могут выполнять и процедуры, которые возвращают множественные результирующие наборы. Это может быть реализовано несколькими способами. Например, вызов хранимой процедуры, которая возвращает множественные наборы записей. Или в команде может содержаться два или более SQL-запроса или хранимых процедур. В этом случае SQL-запросы или хранимые процедуры будут выпол-
няться последовательно, что приведет к получению множественных результирующих наборов.
Возвращение множественных наборов позволяет оптимально использовать единственное открытое соединение с базой данных в следующих ситуациях:
Q при выполнении одной командой нескольких запросов, каждый из которых возвращает отдельный набор записей;
Q при выполнении инструкции UPDATE или INSERT совместно с инструкцией SELECT. Первые выполняют обновление или добавление записей, последняя возвращает из источника данных обновленный набор записей, включая значения, которые автоматически устанавливаются на уровне базы данных (например, значения полей типа "счетчик").
Если вы определяете множественные инструкции или процедуры для команды, то все они должны иметь один и тот же тип. Например, можно выполнить последовательность SQL-запросов или последовательность хранимых процедур. Однако нельзя смешивать хранимые процедуры с SQL- запросами в одной и той же команде.
Выполнение команд данных
После конфигурирования свойств объекта DataCommand вы можете запустить команду на выполнение. Команды данных поддерживают четыре вида возвращаемых результатов.
Q Итоговый набор. В этом случае выполняется SQL-запрос или хранимая процедура, а возвращается одна или более записей. В этом случае в наборе данных может быть "текущей" только одна запись, доступ к которой МОЖНО получить с помощью объекта DataReader.
Q Число обработанных записей. Эта ситуация возникает тогда, когда выполняется SQL-запрос или хранимая процедура, которые модифицируют базу данных или изменяют ее структуру (например, удаляются записи, добавляются таблицы или хранимые процедуры).
Q Простое (скалярное) значение. В этом случае выполняется SQL-запрос или хранимая процедура, которые выполняют поиск, вычисляют агрегирующие функции.
Q Данные в формате XML. Эта возможность поддерживается в SQL Server версией 7.0 и выше.
Использование DataCommand адаптеромданных
Если вы уже работали с наборами данных и адаптерами данных, то большая часть описания работы с командами данных вам будет знакома. Фактиче-
ски, адаптер данных использует команды данных, чтобы выбирать и возвращать записи базе данных. Адаптеры данных могут содержать четыре объекта команды данных: SelectCommand, UpdateCommand, InsertCommand И DeleteCommand.
Когда вы используете адаптер данных, то фактически запускаете на исполнение ту или иную команду данных. Например, когда происходит вызов метода пи объекта DataAdapter, то фактически выполняется команда SelectCommand и используется объект DataReader для заполнения данными таблицы объекта DataSet, Точно так же, когда вызывается метод Update адаптера данных, то выполняется одна из команд (UpdateCommand, InsertCommand ИЛИDeleteCommand). Адаптер данных также проверяет, что командам передаются соответствующие параметры.
Использование объекта DataCommand
В ADO.NET с помощью объектов DataCommand имеется возможность работать непосредственно с элементами базы данных или любого другого источника данных (таблицы, представления, хранимые процедуры и т. п.) без использования объектов "посредников" (набор данных, адаптер данных).
Для использования DataCommand в Visual Studio необходимо выполнить определенную последовательность шагов, как на этапе разработки приложения, так и в период его работы на компьютере пользователя.
Для работы с объектом DataCommand вам необходимо выполнить следующие действия.
На этапе разработки приложения добавьте объект DataCommand к вашей форме или компоненту и в его конфигурации установите следующие параметры:
задайте, что будет использоваться в теле команды: SQL-запрос или хранимая процедура;
определите параметры, которые необходимы для работы команды.
Во время выполнения приложения, присвойте значения параметрам, которые необходимо передать объекту DataCommand. Обычно значения параметров присваиваются пользователем приложения через визуальные элементы формы или передаются от других компонент приложения.
Запустите команду на выполнение. При этом фактически будет выполнен SQL-запрос или хранимая процедура, связанная с объектом DataCommand. Имя оператора, который запустит команду данных на выполнение, будет зависеть от типа возвращаемых командой данных: набор данных DataSet, скалярное значение, количество обработанных записей или данные в XML-формате.
Считайте возвращенные командой значение (или значения) и используйте их в зависимости от специфики вашего приложения.
Добавление объекта DataCommand к форме или компоненту
Перед выполнением команды данных (DataCommand), необходимо добавить экземпляр класса OleDbCommand или SqlCommand к форме или компоненту и сконфигурировать его. В Visual Studio имеется набор визуальных средств, которые помогают разработчику выполнить эту процедуру на этапе разработки приложения.
Добавление объекта DataCommand к форме или компоненте можно выполнить следующим образом.
Добавьте объект connection на форму (если данный объект уже создан, то используйте существующее соединение).
Из вкладки Data окна Toolbox перетащите объект OleDbCommand или SqlCommand на вашу форму или компонент (рис. 3.1).
Примечание
Используйте объект SqlCommand, если вы хотите выполнить команды в базе данных SQL Server версии 7.0 и выше; для остальных источников данных используйте объект OleDbCommand.
^ Pointer У DataSet ^ OieDLDataAdapter ^ СМеОЬСоппесЬоп (^ OleDbCommand ^ SqlDataAdapter ^ SqlCunnectiun '^ SqiCommand ^ DataView^ Pointer У DataSet ^ OieDLDataAdapter ^ СМеОЬСоппесЬоп (^ OleDbCommand ^ SqlDataAdapter ^ SqlCunnectiun '^ SqiCommand ^ DataView
^ Pointer У DataSet ^ OieDLDataAdapter ^ СМеОЬСоппесЬоп (^ OleDbCommand ^ SqlDataAdapter ^ SqlCunnectiun '^ SqiCommand ^ DataView
^ Pointer У DataSet ^ OieDLDataAdapter ^ СМеОЬСоппесЬоп (^ OleDbCommand ^ SqlDataAdapter ^ SqlCunnectiun '^ SqiCommand ^ DataView
Рис. З.1. Объект SqlCommand в окне Toolbox
Установите следующие свойства для объекта DataCommand (табл. 3.1).
Таблица 3.1. Свойства объекта DataCommand
СвойствоОписание
NameNameИмя, с помощью которого можно обратиться к команде в программном коде
Name
Name
154
Глава 3
Таблица 3.1. (окончание)
Свойство
Описание
Connection
Имя объекта Connection, которое команда будет использовать для связи с базой данных. Можно выбрать имя существующего соединения из раскрывающегося списка
CommandType
Значение, определяющее тип выполняемой команды:
Text — SQL-запрос,
StoredProcedure — хранимая процедура.
TableDirect — получение полного содержания таблицы. (Этот значение доступно только для объектов OleDbCommand)
CommandText
Текст (содержание) выполняемой команды. Значение данного свойства зависит от того, какой тип команды был указан в свой- ствеCommandType:
если Text, то вводится текст SQL-запроса;
если StoredProcedure, то вводится имя хранимой
процедуры;
если TableDirect, то вводится имя таблицы
Parameters
Коллекция объектов класса OleDbParameter или SqlParameter. Вы можете передать данные команде, устанавливая свойства индивидуальных параметров
После того, как определены свойства команды данных, ее можно запустить на выполнение, предварительно передав ей значения параметров. При нажатии кнопки в строке свойства CommandText будет активизировано окно построителя запросов Query Builder.
Установка и получение параметров объекта DataCommand
Если в приложении используется объект DataCommand, который работает непосредственно с элементами базы данных, то выполняемые SQL-запросы и хранимые процедуры обычно требуют параметров. Например, простая инструкция обновления записи — update, требующая параметров, может иметь следующий вид:
UPDATE Employees
SET LastName=@LastName, FirstName=@FirstName, BirthDate=@BirthDate
WHERE (EmployeeID=@Emp_id)
Перед выполнением данного запроса, необходимо обязательно определить значения параметров (@LastName, @FirstName, @BirthDate И @Emp_id). Объ-
ект DataCommand поддерживают коллекцию Parameters, которая содержит набор объектов класса OleDbParameter или SqlParameter. Каждому параметру команды данных соответствует один объект в коллекции Parameters. Кроме того, если вызывается хранимая процедура, то возможно наличие дополнительного параметра, который будет принимать значение, возвращаемое процедурой.
Вы можете конфигурировать коллекцию Parameters объекта DataCommand, используя окно свойств Properties или в программном коде. На рис. 3.2 показано окно редактора коллекции параметров, которое автоматически вызывается при нажатии кнопки в строке свойств Parametrs в окне Properties.
Примечание
Параметрам можно дать осмысленные имена, через которые можно обращаться к ним в программном коде. Хотя для ссылки на параметры можно использовать их индексные значения в коллекции Parameters, но программный код будет более ясным и понятным, если к параметрам обращаться с помощью имен.
Рис. 3.2. Окно редактора коллекции параметров объекта DataCommand
Прежде, чем выполнять команду, необходимо установить значение для каждого параметра команды.
Для каждого параметра в коллекции Parameters задайте в свойстве Value то значение, которое нужно передать исполняемой команде.
Следующий пример показывает, как установить значения параметров перед выполнением команды, которая вызывает хранимую процедуру. В данном примере предполагается, что вы уже сконфигурировали коллекцию Parameters (в коллекции содержится три параметра с именами au_id, au_lname И au_fname). В данном примере такие свойства как CornrnandTex и CommandType задаются в программном коде, хотя они могут быть определены в окне Properties объекта DataCommand. Это сделано для большей наглядности и законченности приводимого в листинге 3.1 программного кода.
Листинг 3.1
' Visual Basic
With OleDbCommand1
.CommandText="UpdateAuthor"
.CommandType=Sygtem.Data.CommandType.StoredProcedure
.Parameters("au_id").Value=listAuthorID.Text
.Parameters("au_lname").Value=txtAuthorLName.Text
.Parameters("au_fname").Value=txtAuthorFName.Text
End With
OleDbConnection1.Open()
OleDbCoramand1.ExecuteNonQuery()
OleDbConnection1.Close()
// C#
OleDbCommand1,CommandText="UpdateAuthor";
OleDbCommand1,CommandType=System.Data.CommandType.StoredProcedure;
OleDbCommand1.Parameters["au_id"].Value=listAuthorID.Text;
OleDbCommand1.Parameters["au_lname"].Value=txtAuthorLName.Text;
OleDbCommand1.Parameters["au_fname"].Value=txtAuthorFName.Text;
OleDbConnection1.Open();
OleDbCommand1.ExecuteNonQuery();
OleDbConnection1.Close();
Получение возвращаемых значений
Хранимые процедуры часто возвращают значения назад к приложению, которое вызвало их на исполнение. Они могут передавать возвращаемые значения через параметр.
Получение значений, возвращенных процедурами через свойство value, происходит в несколько этапов.
Создайте параметр, свойству которого Direction присвойте значение Output или InputOutput. Удостоверьтесь, что тип данных этого параметра соответствует типу возвращаемого значения.
После выполнения процедуры, прочитайте свойство Value параметра, который возвращает значение.
Получите возвращаемое значение процедуры через свойство ReturnValue.
Создайте параметр, свойству Direction которого присвойте значение ReturnValue.
Примечание
Параметр, который возвращает значение, должен быть первым в коллекции Parameters.
Удостоверьтесь, что тип данных этого параметра соответствует типу возвращаемого значения.
Примечание
Инструкции update, insert и Delete в SQL-запросах возвращают целочисленное значение, указывающее количество записей, которые обработаны инструкцией. Вы можете получить число обработанных записей как возвращаемое значение метода ExecuteNonQuery.
Следующий пример (листинг 3.2) показывает, как получить значение, возвращаемое хранимой процедурой с именем CountAuthors. В этом случае предполагается, что первый параметр в коллекции Parameters называется retvalue И его свойство Direction имеет значение ReturnValue.
Листинг 3.2
' Visual Basic
Dim cntAffectedRecords As Integer
OleDbCommand1. CommandText="CountAuthors"
OleDbCommand1, CommandType=CommandType. StoredProcedure
OleDbConnection1.Open()
OleDbCommand1. ExecuteNonQuery ()
OleDbConnection1.Close()
cntAffectedRecords=CType(OleDbCommand1.Parameters("retvalue").Value, ъ Integer)
MessageBox.Show("Affected records=" & cntAffectedRecords.ToString)
// C#
int cntAffectedRecords;
oleDbcommand1.CommandText="CountAuthors";
oleDbConmand1.CommandType=CommandType.StoredProcedure;
oleDbConnection1.Open();
oleDbCommand1.ExecuteNonQuery();
oleDbConnection1.Close();
cntAffectedRecords=(int)(OleDbCommand1,Parameters["retvalue"].Value); MessageBox.Show("Affected records=" + cntAffectedRecords.ToString());
Выполнение команд, которые возвращают наборы данных
Бы можете использовать объект DataCommand, чтобы выполнить процедуру выборки информации непосредственно из базы данных, которая будет доступна только для чтения, В этом случае выполняется SQL-запрос или хранимая процедура, которая содержит инструкцию SELECT. Это аналогично тому, как заполняется набор данных через адаптер данных, за исключением того, что результирующий набор записей попадает в приложение, минуя "посредников".
Возвращенный набор записей помещается в объект DataReader (OleDbDataReader ИЛИ SqlDataReader). В цикле, путем перебора, МОЖНО получить доступ к любой индивидуальной записи полученного набора. Поскольку DataReader обеспечивает доступ К данным В режиме forward-only, read-only, то это достаточно быстрый и эффективный способ получения набора записей из базы данных.
Выполнение команд, которые возвращают набор записей, происходит следующим образом.
Добавьте объект DataCommand к вашей форме или компоненте.
Определите в свойстве объекта CommandText текст SQL-запроса или имя хранимой процедуры, которые возвращают набор записей.
Установите В свойстве CommandType значение CommandType.Text (ДЛЯ SQL-запроса) ИЛИ CommandType. StoredProcedure (для хранимой процедуры).
Если команда имеет параметры, то определите их.
Создайте объект DataReader как Экземпляр класса OleDbDataReader ИЛИ SqlDataReader, в зависимости от типа используемого соединения.
Откройте соединение, связанное с командой данных.
Вызовите метод ExecuteReader, адресуйте результаты работы команды объекту DataReader, созданному на шаге 5.
В цикле просмотрите полученные данные, используя метод Read.
Закройте объект DataReader.
Если больше не предполагается использовать метод ExecuteReader, то закройте соединение.
Следующий пример (листинг 3.3) показывает, как получить записи из таблицы Authors базы данных Pubs (SQL Server). Пример использует тип команды TableDirect и определяет имя таблицы Authors как текст команды. После выполнения команды (вызов метода ExecuteReader) организован цикл чтения записей в переменную s (создается строка с информацией об авторах, использующая в качестве разделителей пробел, символ табуляции и перевод строки), которая затем отображается в текстовом поле.
Листинг 3.3
' Visual Basic
DimdreaderAs System.Data.OleDb.OleDbDataReader
OleDbCommand1.CommandText="authors"
OleDbCommand1.CornmandType=CommandType.TableDirect
OleDbConnection1,Open()
dreader=01eDbCorrmandl.ExecuteReader(CommandBehavior.CloseConnection)
Dim s As String=""
While dreader.Read()
s &= dreader("au_id").ToString()
& vbTab & dreader ("au_fname")-ToString () %■
5 " " & dreader("au_lname").ToString & ControlChars.CrLf
End While
TextBox1.Text=s
dreader.Close()
// C#
System.Data.OleDb.OleDbDataReader dreader;
OleDbCommand1.CommandText="authors";
OleDbCommand1.CommandType=CommandType.TableDirect;
OleDbConnection1.Open();
dreader=01eDbCommandl.ExecuteReader(CommandBehavior,CloseConnection);
string s="";
while (dreader.Read())
{
s += dreader["au_id"].ToString() + "\t" ъ
+ dreader["au_fname"].ToString() + " " ъ
+ dreader["au_lname"].ToString () + "\n";
}
TextBoxl.Text=s;
dreader.Close();
Следующий пример (листинг 3.4) показывает два способа использования объекта DataReader для получения данных. В первой части примера объект DataReader загружает данные в компонент ListBox на Windows-форме (ТОЛЬКО ОДИН столбец author_id таблицы authors).
Во второй части примера рассматривается обработчик события SelectedIndexChanged объекта ListBox. Здесь в предложении SELECT SQL- запроса в качестве ключевого поля (параметра) для выбора единственной записи используется значение au_id. Этот параметр получает значение из списка авторов (объект ListBox1). Поскольку объект DataReader ожидает возвращения только одной записи, то информация из него считывается не в цикле (его метод Read вызывается только один раз). В примере проверяется, что имеется не менее одной записи, путем вызова метод Read в условном операторе IF- End If.
Два обработчика событий используют различные команды данных: в первом случае не используются параметры, во втором случае команде передается один параметр для идентификации автора.
г Листинг 3.4
' Visual Basic
Private Sub btnLoadListBox_Click(ByVal sender As System.Object,’Ь
ByVal e As System.EventArgs) Handles btnLoadListBox.Click
Dim dreader As System.Data.OleDb.OleDbDataReader
OleDbCommand1.CommandText="authors"
OleDbCommand1.CommandType=CoinmandType.TableDirect
OleDbConnection1.Open()
dreader=01eDbCommand1.ExecuteReader()
While dreader.Read ()
ListBox1.Items.Add(dreader("au_id"))
End While
dreader.Close()
OleDbConnection1.Close()
EndSub
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
Dim dreader As System.Data.OleDb.OleDbDataReader
OleDbCommand2. CommandText =
"SELECT au_id, au_lname, au_fname FROM authors WHERE au_id=?"
OleDbCommand2.CornmandType=CommandType. Text
OleDbCommand2.Parameters ( "au_id") . Value=ListBox1.Text
OleDbConnection1.Open()
dreader=0leDbCommand2.ExecuteReader()
If dreader.Read() Then
txtAuthorID.Text=dreader("au_id"),ToString()
txtAuthorLastName.Text=dreader("au_lname") .ToString ()
txtAuthorFirstName.Text=dreader("au_fname").ToString()
End If
dreader.Close()
OleDbConnection1.Close()
End Sub
// C#
private void.btnLoadListBox_Click(object sender, System.EventArgs e) (
System.Data.OleDb.OleDbDataReader dreader;
OleDbCommand1.CommandText="authors";
OleDbCommand1.CommandType=CommandType.TableDirect;
OleDbConnection1.Open() ;
dreader=OleDbCommand1.ExecuteReader();
while( dreader.Read())
{
ListBox1.Items.Add(dreader["au_id"]);
}
dreader.Close () ;
OleDbConnection1.Close() ;
Button6.Enabled=true;
}
private void ListBox1_SelectedIndexChanged(object sender,ъ
System.EventArgs e)
{
System.Data.OleDb.OleDbDataReader dreader;
OleDbCommand2.CommandText =
"SELECT au_id, au_lname, au_fname FROM authors WHERE au_id=?";
OleDbCommand2.CommandType=CommandType.Text;
OleDbCowmand2.Parameters["au_id"].Value=ListBox1.Text;
OleDbConnection1.Open();
dreader=OleDbCommand2.ExecuteReader();
if (dreader.Read())
{
txtAuthorID.Text=dreader["au_id"l.ToString();
txtAuthorLastName.Text=dreader["au_lname"].ToString();
txtAuthorFirstName.Text=dreader["au_fname"].ToString();
}
dreader.Close(};
OleDbConnection1.Close();
}
Выполнение обновления или модификации базы данных с использованием DataCommand
Некоторые типы команд данных (OleDbCommand или SqlCommand) при выполнении каких-либо действий над элементами базы данных не возвращают никаких данных кроме признака, что команда выполнена успешно. К ним относятся:
Q команды модификации структуры базы данных, которые используются для создания таблиц, хранимых процедур и других элементов с использованием языка описания структур базы данных (DDL);
Q Команды Обновления данных (Update, Insert И Delete).
Если в приложении используется набор данных DataSet, то нет необходимости выполнять обновление базы данных через объект DataCommand, поскольку эти функции может выполнить адаптер данных.
Оба типа приведенных выше команд возвращают целое число, указывающее успешность выполнения соответствующей операции. Возвращаемое значе-
ние различно — в зависимости от того, модифицируете ли вы записи таблицы, или модифицируете структуру базы данных с помощью DDL-команд:
О
Q если вы создаете новые элементы базы данных или изменяете ее структуру, то возвращаемое значение равно -1, если операция завершилась успешно;
Q если вы модифицируете записи, возвращаемое значение указывает количество записей, которые были обработаны соответствующей операцией.
В обоих случаях, если в процессе выполнения операции произошел сбой, то команда возвращает значение о.
Чтобы выполнить команду модификации базы данных, нужно проделать ряд шагов.
Добавьте команду данных к вашей форме или компоненту и сконфигурируйте выполняемые ею действия (сформируйте SQL-запрос или сошлитесь на хранимую процедуру).
Если команда имеет параметры, то определите их.
Если в команде есть параметры, то добавьте программный код для установки их значений.
Добавьте программный код, чтобы открыть соединение, связанное с командой данных.
Вызовите метод команды ExecuteNonQuery, присвоив результат работы команды целочисленной переменной.
Примечание
Данный метод возвращает одно целочисленное значение. Однако хранимая процедура может возвращать набор значений, для которых нужно определить коллекцию параметров Parameters,
Закройте соединение.
В следующем примере (листинг 3.5) показано, как создать новую таблицу в базе данных. Пример предполагает, что вы уже добавили к форме команду данных, соединение и сконфигурировали их. Действия, выполняемые командой, записываются в ее свойство CommandText. В данном случае используется SQL-инструкция CREATETABLE, которая создает таблицу из двух столбцов, один из которых является первичным ключом. После выполнения команда вернет значение -1, если таблица была успешно создана.
ЛистингЗ.5
.
' Visual Basic
Dim newtablecmd As String
Dim cmdresults As Integer
newtablecmd="CREATE TABLE LookupCodes (code_id smallint IDENTITY(1,1)^ PRIMARY KEY CLUSTERED, code_desc varchar(50) NOT NULL)"
OleDbCommand1. CommandType=CommandType.Text
OleDbCommand1.CommandText=newtablecmd
OleDbConnection1.Open()
cmdresults=OleDbCommand1,ExecuteNonQuery()
OleDbConnection1.Close()
MessageBox.Show("After creating the table, results=" &ъ cmdresults.ToString)
// C#
string newtablecmd;
int cmdresults;
newtablecmd="CREATE TABLE LookupCodes (code_id smallint IDENTITY(1,1)%> PRIMARY KEY CLUSTERED, code_desc varchar(50) NOT NULL)";
OleDbCommand1.CommandType=CommandType.Text;
OleDbCommand1.CommandText=newtablecmd;
OleDbConnection1.Open();
cmdresults=OleDbCommand1.ExecuteNonQuery();
OleDbConnection1.Close();
MessageBox.Show("After creating the table, results=" +^ cmdresults.ToString());
Следующий пример (листинг З.б) показывает, как использовать команду данных, чтобы модифицировать базу данных Pubs (SQL Server), вставляя новые записи в таблицу Authors. В данном случае, команда вызывает хранимую процедуру с именем NewAuthor, которая содержит инструкцию Insert Into с девятью значениями (параметрами) для новой записи автора. Команда OleDbCommand2 сконфигурирована таким образом, что имеет коллекцию параметров Parameters с девятью элементами, значения которых передаются в хранимую процедуру. Значения параметрам присваиваются в программном коде из текстовых полей формы. После открытия соединения вызывается метод ExecuteNonQuery, после чего соединение закрывается.
Листинг3.6
Г.~~—,^...^—J
' Visual Basic
Dim cmdresults As Integer
OleDbcommand2.CommandText="NewAuthor"
OleDbCommand2.CommandType=CommandType.StoredProcedure
OleDbCommand2.Parameters("au_id").Value=TextBox1. Text
OleDbCommand2.Parameters("au_lname").Value=TextBox2.Text
OleDbCommand2.Parameters("au_fname").Value=TextBox3.Text
OleDbCommand2.Parameters("phone").Value=TextBox4.Text
OleDbCommand2.Parameters("address").Value=TextBox5,Text
OleDbCommand2.Parameters("city").Value=TextBox6.Text
OleDbCommand2.Parameters("st").Value=TextBox7.Text
OleDbCommand2.Parameters("zip").Value=TextBox8.Text
OleDbCommand2.Parameters("contract").Value=CheckBox1.Checked
OleDbConnection2.Open()
Try
cmdresults=OleDbcommand2.ExecuteNonQuery()
Catch ex as Exception
MessageBox.Show("Failed to execute command, err=" & ex.Message)
End Try
OleDbConnection.Close()
MessageBox.Show("Number of records inserted=" s cmdresults.ToString)
// C#
int cmdresults=0;
OleDbCommand2.CommandText="NewAuthor";
OleDbCommand2.CommandType=CommandType.StoredProcedure;
OleDbCommand2.Parameters["au_id"].Value=TextBox1.Text;
OleDbCommand2.Parameters["au__lname"].Value=TextBox2.Text;
OleDbCommand2.Parameters["au_fname"].Value=TextBox3.Text;
OleDbCommand2.Parameters["phone"].Value=TextBox4.Text;
OleDbCommand2.Parameters["address"].Value=TextBox5.Text;
OleDbCommand2.Parameters["city"].Value=TextBox6.Text;
OleDbCommand2.Parameters["st"].Value=TextBox7.Text;
OleDbCommand2.Parameters["zip"].Value=TextBox8.Text;
OleDbCommand2.Parameters["contract"].Value=CheckBox1.Checked;
OleDbConnection2.Open();
try {
)
catch (Exception ex)
{
MessageBox.Show("Failed to execute command, err=" + ex.Message);
}
OleDbConnection,Close();
MessageBox.Show("Number of records inserted=" + cmdresults.ToString());
Задание команды Data Command, возвращающей одно значение
Достаточно часто в приложениях требуется выполнение команд, которые возвращают единственное (скалярное) значение. Типичные примеры: SQL- запрос возвращает результат работы агрегирующей функции (SUM, COUNT и тому подобное), хранимая процедура, получающая пароль и возвращающая разрешение на доступ к базе данных, или процедура, которая получает код изделия, а возвращает его наименование и т. д.
Чтобы задать команду, которая возвращает скалярное значение, нужно выполнить несколько этапов.
Добавьте объект DataCommand к форме или компоненту.
В свойстве CommandText объекта DataCommand определите SQL-запрос или имя хранимой процедуры.
Свойству CommandType задайте значение CommandType.Text (для SQL- запроса) ИЛИ CommandType. StoredProcedure (ДЛЯ Хранимой процедуры).
Если команда имеет параметры, то определите их.
Откройте соединение с источником данных, которое ассоциировано с данной командой.
Вызовите метод команды ExecuteScalar, присвоив результат его работы переменной соответствующего типа.
Закройте соединение с источником данных.
Следующий пример (листинг 3.7) показывает, как использовать команду данных, чтобы выполнить инструкцию SQL, которая возвращает скалярное значение. В SQL-запросе данной команды делается обращение к таблице Products (Изделия). В качестве критерия (параметра) поиска нужного изделия используется его идентификационный номер. Возвращается целочисленное значение, указывающее количество заготовок для заданного изделия (UnitsInStock).
Листинг 3,7I
' Visual Basic
Dim scalarcmd As String
Dim qtyinstock As Integer
scalarcmd="SELECT UnitsInStock FROM Products WHERE (ProductID=?)"
OleDbCommand3.ConmandType=CommandType. Text
OleDbCommand3.CommandText=scalarcmd
OleDbCommand3.Parameters("productid").Value=txtProductID.Text
OleDbConnection1.Open()
qtyinstock=CType(OleDbCommand3.ExecuteScalar(), Integer)
OleDbConnection1.Close()
MessageBox.Show("QtyinStock=" & qtyinstock.ToString)
// C#
string scalarcmd;
intqtyinstock;
scalarcmd="SELECT UnitsInStock FROM Products WHERE (ProductID=?)";
OleDbCommand3.CommandType=CommandType.Text;
OleDbCommand3,CommandText=scalarcmd;
OleDbCommand3.Parameters["productid"].Value=txtProductID.Text;
OleDbConnection1.Open();
qtyinstock=(int)(OleDbCommand3.ExecuteScalar());
OleDbConnection1.Close();
MessageBox.Show("QtyinStock=" + qtyinstock.ToString());
3.2. Стратегии доступа к данным
В ADO.NET используется отсоединенная модель доступа к данным. В этой модели открывается соединение с базой данных, делается выборка записей или выполняются другие операции с таблицами базы данных, после чего соединение сразу закрывается. В ADO.NET возможны две стратегии работы в рамках этой модели.
Первая стратегия предусматривает размещение данных в объекте DataSet. При этом данные размещаются в оперативной памяти компьютера в виде кэш-записей, с которыми можно работать в отрыве от источника данных. Чтобы использовать объект DataSet, создается экземпляр этого класса, который заполняется записями из источника данных через объект DataAdapter. Пользователь работает с записями через объект отображения
информации (например, DataGrid), который связывается с набором данных DataSet.
Вторая стратегия заключается в том, чтобы выполнять операции непосредственно в базе данных, не передавая записи на компьютер клиента. В этой стратегии выполняются команды данных (объект DataCommand), содержащие SQL-запросы или ссылку на хранимые процедуры. При этом происходит соединение с базой данных, запуск команды, выполняющей те или иные действия с записями базы данных, и затем закрытие соединения. Если команда возвращает набор записей (содержит инструкцию SELECT), то можно с помощью объекта DataReader получить эти записи и представить их пользователю через связанную с объектом DataReader компоненту визуального отображения данных. Это самый эффективный способ выборки информации, правда, она доступна только для чтения.
Каждая стратегия имеет определенные преимущества. Какую из них выбрать — зависит от характера задачи, решаемой конкретным приложением, и этот вопрос более детально рассматривается в следующих разделах.
Работа с данными через объект DataSet
Обычно в Visual Studio .NET используется объект DataSet для доступа к данным. Этот подход имеет ряд преимуществ.
Q Работа с несколькими таблицами. Набор данных может содержать несколько таблиц. Можно работать как с каждой таблицей индивидуально, так и устанавливать между ними реляционные отношения.
Q Работа с данными из разных источников. Таблицы в наборе данных могут содержать данные из различных источников (например, из различных баз данных, XML-файлов, электронных таблиц и т. д.). Как только данные попадут в объект DataSet, с ними можно манипулировать, устанавливать связи между таблицами, сортировать, фильтровать и выполнять все те же действия, которые допускаются для данных, поступивших из одного источника.
Q Перемещение данных между элементами приложения. Данные из объекта DataSet могут легко передаваться другим элементами приложения - объектам отображения информации, на уровень бизнес-логики, в исходную базу данных.
Q Перемещение данных между приложениями. Объект DataSet позволяет реализовать простой и эффективный обмен данными между различными приложениями. Наборы данных включают поддержку преобразования содержимого таблиц в XML-формат, чтение данных из XML-формата, работу с XML схемами.
Q Связывание данных. Если вы работаете с формами, то связывание объектов DataSet с объектами визуального отображения информации выполняется гораздо проще, чем связывание набора записей, полученного после работы DataCommand.
О Поддержка повторного использования данных. Набор данных позволяет вам многократно манипулировать полученными записями, без повторных обращений к исходному источнику данных (сортировка, фильтрация по различным признакам и критериям).
Q Простота программирования. Работая с DataSet, можно представить его структуру как набор объектов класса (например, к таблице customers в наборе данных можно обратиться как к объекту dataset.Customers). Это более легкий, ясный подход создания приложений, менее подверженный программным ошибкам. Кроме того, в Visual Studio реализовано достаточно много визуальных средств программирования с поддержкой IntelliSense и мастеров по конфигурации объектов работы с данными.
Непосредственная работа
с элементами базы данных
В качестве альтернативы можно напрямую взаимодействовать с базой данных (без использования объекта DataSet). В этой модели, используется объект DataCommand, который содержит SQL-запрос или ссылку на хранимую процедуру. При запуске команды на исполнение над таблицами базы данных выполняются определенные действия (выборка данных, добавление, удаление или обновление записей). Если команда возвращает набор записей (в SQL-запросе используется предложение SELECT), то к ним можно получить доступ посредством объекта DataReader (в режиме только чтение).
Такая модель доступа к данным имеет следующие преимущества.
О Высокая эффективность. Такие команды, как добавление, удаление записей выполняются непосредственно на уровне базы данных и не требуют передачи большого объема информации в приложение. Хранимые процедуры хранятся в базе данных в скомпилированном виде и не требуют ресурсов и времени для их компиляции и проверки синтаксиса.
Q Высокая степень контроля над данными. Используя команды, разработчик имеет прямой доступ к данным (без объектов посредников).
Q Меньшая потребность в оперативной памяти. Работая непосредственно с базой данных, нет необходимости загружать записи в оперативную память компьютера пользователя, соответственно для работы приложения требуется меньше ресурсов. Кроме того, меньше информации передается по каналам связи, что особенно важно для Интернет-приложений.
Q Уменьшение программного кода. При работе с объектом DataSet требуется программировать все процессы синхронизации таблиц набора данных в памяти компьютера с таблицами в базе данных. Например, после добавления записи в DataSet нужно выполнить эту операцию и в основном хранилище информации, кроме того, если в таблице есть поле типа "счетчик", то потребуется повторное считывание таблицы из основной базы данных в DataSet, чтобы передать приложению новое значение счетчика. При прямой работе с таблицами базы данных необходимость в программировании этих процессов отпадает.
Особенно эффективно использование модели прямого доступа к базе данных в Web-приложениях, когда требуется минимизировать объем информации, передаваемой по каналам связи.
Рекомендации по организации доступа к данным из приложений
В данном разделе даются рекомендации по стратегии доступа к данным при реализации определенных типов приложений.
Web-формы
При создании Web-приложений для доступа к данным рекомендуется использовать объекты DataCommand и DataReader. Поскольку страница Web- формы и содержащиеся на ней компоненты обновляются при каждом обращении пользователя к серверу, то использовать объект DataSet не эффективно, особенно если не предусмотрено его кэширование.
Однако использование набора данных целесообразно при следующих обстоятельствах:
Q необходима одновременная работа с несколькими таблицами, или работа с таблицами, получаемыми от различных источников данных;
Q требуется обмен данными с другим приложением или компонентом типа XML Web-сервис;
Q требуется длительная работа с записями, которые были получены от базы данных. Если в этом случае использовать DataCommand и DataReader, то это потребует длительной поддержки открытого соединения, что может негативно сказаться на эффективности работы приложения (особенно, если с ним потенциально могут работать большое количество пользователей);
Q если в приложении требуется обработка связанных таблиц;
Q если вы хотите использовать XML-формат для передачи или приема данных из другого приложения;
Q если во главу угла ставится простота программирования, а не эффективность работы приложения.
XML Web-сервисы
В XML Web-сервисах необходимо использовать ту же модель доступа к данным, что была описана предыдущем разделе. Здесь так же используются активные серверные страницы в виде Web-форм. Однако довольно часто XML Web-сервисы используются в трехуровневых приложениях для реализации бизнес-логики, что требует интенсивного обмена данными с другими частями приложения (база данных и приложение-клиент) через сеть.
В Web-сервисах рационально использовать DataSet:
О если ваш XML Web-сервис посылает и получает данные. Например, посылает DataSet как возвращаемое значение метода и получает DataSet как параметр метода. Это фундаментальная основа XML Web-сервисов (собственно то, для чего они и создавались);
Q если существует какая-либо причина, описанная в предыдущем разделе для Web-форм.
Использование DataCommand и DataReader оправдано при следующих обстоятельствах:
Q если XML Web-сервис возвращает скалярную величину;
Q если XML Web-сервис выполняет не операцию запроса, а команду языка описания данных (DDL-команду), например, создает новую таблицу;
Q если XML Web-сервис вызывает хранимую процедуру, чтобы выполнить набор операций в пределах базы данных.
Windows-формы
В Windows-формах предпочтительней использование набора данных. С помощью Windows-форм обычно реализуются приложения с достаточно сложной логикой обработки и представления данных. В отличие от Web-форм, Windows-формы не пересоздаются после каждой пользовательской операции надданными.
Здесь использование набора данных предпочтительно при следующих обстоятельствах:
Q если пользователь многократно выполняет различные операции с одним и тем же набором записей (редактирование, удаление, добавление, сортировка, фильтрация и т.п.);
Q если используются элементы визуального отображения данных Windows- форм, связанные с набором данных;
Q no любой из других причин, перечисленных выше в разделе "Web- формы".
Использование DataCommand и DataReader может быть разумным в следующих случаях:
Q если из базы данных возвращается скалярное значение;
Q если выполняется не операция запроса, а команда языка описания данных (DDL-команда), например, создание новой таблицы;
Q если возвращаемый набор данных требуется только отобразить в форме (в режиме только для чтения). Например, сформировать и представить пользователю отчет о работе некоторых подразделений фирмы за заданный период.
Итак, в материалах первых трех глав вы познакомились с новой моделью доступа к данным, изучили основные объекты, реализующие возможность соединение с базами данных, выборку информации, ее изменение и возвращение в источник данных. Теперь можно прейти к изучению вопросов, касающихся разработки приложений с использованием новых технологических подходов. И начнем мы с традиционных Windows-приложений.
ГЛАВА 4
Построение Windows-приложений с доступом к данным через ADO.NET
Большинство программистов имеют достаточно богатый опыт разработки Windows-приложений — это традиционные информационные системы, работающие с базами данных в режиме файл-сервер или клиент-сервер в рамках локальных сетей. Исходя из этого, мы начнем практическое знакомство с Visual Studio .NET с создания приложений именно данного типа.
Из материалов данной главы вы узнаете:
Q как создать Windows-проект и Windows-форму, являющуюся основой пользовательского интерфейса;
Q как реализовать доступ к данным в Windows-формах с использованием широко распространенного элемента управления DataGrid;
Q какие есть возможности доступа к данным в Windows-формах с использованием текстовых полей;
О как можно осуществить выборку и сортировку данных через запросы с параметрами;
Q как реализовать работу со связанными таблицами (с отображением их в разных элементах управления, а также в одном элементе управления DataGrid);
Q как реализовать добавление, удаление и обновление записей.
Создание Windows-приложения
В данном разделе описывается последовательность создания Windows- приложения.
Для создания Windows-приложения выполните следующие действия.
Запустите Visual Studio .NET, при этом на экране появиться стартовое окно (рис. 4.1).
Start
Get Started
What's New
Online Community
Headlines
Search Online
Downloads
xml web Services
Web Hosting
My Profile
Projects
Рис. 4.1. Стартовое окно при запуске Visual Studio .NET
Нажмите кнопку New Project. На экране появится окно выбора свойств создаваемого проекта (рис. 4.2).
В поле Projects Types выберите язык программирования (Visual Basic Projects , Visual C# Projects), который вы собираетесь использовать при написании приложения. В данном примере выбран язык Visual Basic.
В правой части окна — Templates — выберите шаблон, на основании которого будут созданы базовые элементы проекта. В данном примере указано Windows Application.
Теперь необходимо определиться с будущим именем проекта (поле Name). Поумолчаниюданному свойству устанавливаетсяимя
windowsAplication1.Оставим его без изменения.
В поле Location определяется путь к директории, в которой будут храниться файлы проекта. Это поле так же оставим без изменения.
Рис. 4.2. Окно выбора свойств создаваемого проекта
После нажатия кнопки ОК Visual Studio .NET создаст весь необходимый набор файлов и первую форму проекта с именем Form 1 (рис. 4.3).
Рис. 4.3. Окно дизайнера Windows-приложения
Windows-форма как основа интерфейса
В данном разделе вы научитесь строить и запускать простую Windows- форму.
Для создания Windows-формы выполните следующие действия.
Запустите Visual Studio .NET,
Создайте Windows-приложение с именем Helloworld.
В окне Properties формы Form1 установите значение свойства startPosition равным centerScreen (расположение формы в центре экрана).
Из окна Toolbox перенесите на форму Form1 кнопку (элемент управления Button).
Щелчком мыши выделите на форме кнопку Button1. В окне Properties установите значение свойства Text равным пуск. На рис. 4.4 приведены результаты вашихдействий.
Рис. 4.4. Ваша первая Windows-форма в окне дизайнера
Для написания программного кода вашего приложения выполните следующие действия.
Двойным щелчком мыши на созданной кнопке добавьте в программный код обработчик события Button1_Click.
В открывшемся редакторе кода в обработчике события Button1_Click добавьте следующие строки (листинг 4.1).
Листинг 4.1
' Visual Basic
MessageBox.Show ("Hello, World!")
// С#
MessageBox.Show("Hello, World!");
Для тестирования приложения.
Нажмите клавишу <F5> для запуска приложения.
Когда ваше приложение запустится, щелкните кнопку Пуск. Должно появиться сообщение "Hello, World!", как показано на рис. 4.5.
Рис, 4.5. Ваша первая Windows-форма в запущенном приложении
Закройте Windows-форму для возврата в Visual Studio.
Итак, вы создали первое работающее приложение с помощью Visual Studio .NET. Пока оно никак не связано с отображением информации из базы данных. Но не беда, это будет следующий шаг освоения нового инструментального средства. А пока пройдены первые два этапа: создание Windows-приложения и Windows-формы.
Доступ к данным в Windows-формах с использованием элемента управления DataGrid
В данном разделе объясняется последовательность создания Windows- формы и отображение данных, хранящихся в MS SQL Server. В качестве элемента отображения данных используется сетка (DataGrid).
Один из наиболее общих сценариев в разработках прикладных программ — отображение данных о форме посредством элемента управления DataGrid, сетки данных. Дальнейший пример иллюстрирует простую Windows-форму, которая отображает в сетке содержимое несвязанной таблицы базы данных. Сетка позволяет редактировать данные, и затем с помощью других объектов вы сможете внести сделанные изменения в базу данных. Этот пример иллю-
стрирует основные процедуры, которые нужно использовать при доступе к данным в Windows-формах.
Для того чтобы реализовать данный пример, нужно иметь доступ к базе данных Pubs, которая автоматически устанавливается при инсталляции MS SQL Server. Вам предстоит выполнить следующие шаги:
Q создать Windows-проект и, соответственно, Windows-фому;
Q создать соединение с базой данных Connection;
Q создать объект доступа к базе данных DataAdapter;
Q создать и сконфигурировать набор данных Dataset;
Q добавить на форму элемент управления DataGrid и связать его с набором данных DataSet;
Q добавить программный код для заполнения набора данных DataSet;
Q добавить программный код, который вернет в базу данных все изменения пользователя.
По завершению этого примера вы должны получить форму, которая выглядит подобно приведенной на рис 4.6.
au idaujnameaujnamephoneaddies*crty172-32-1176WhiteJohnson408 496-722310932 BiggeMenlo Park213-46-8915Green!Marjorie415 986-7020303 63rd St.Oakland238-95-7766CarsonCheryl415 548 7723589 Darwin LBerkeley267-41-2394O'LearyMichael408 286-242822 ClevelandSan Jose274-80 9391StraightDean415 834-29195420 CollegeOakland341-22-1782SmithMeander913 843-046210 MississippLawrence409-56 7 008BennetAbraham415 658 93326223 BatemaBerkeley427-17-2319DullAnn415836-71283410 BlondePalo Alto472-27-2349GrindesbvBurt707 938-6445PO Box 792Coveloau idaujnameaujnamephoneaddies*crty172-32-1176WhiteJohnson408 496-722310932 BiggeMenlo Park213-46-8915Green!Marjorie415 986-7020303 63rd St.Oakland238-95-7766CarsonCheryl415 548 7723589 Darwin LBerkeley267-41-2394O'LearyMichael408 286-242822 ClevelandSan Jose274-80 9391StraightDean415 834-29195420 CollegeOakland341-22-1782SmithMeander913 843-046210 MississippLawrence409-56 7 008BennetAbraham415 658 93326223 BatemaBerkeley427-17-2319DullAnn415836-71283410 BlondePalo Alto472-27-2349GrindesbvBurt707 938-6445PO Box 792CoveloЗагрузить I Обновить данныеЗагрузить I Обновить данные
au id
aujname
aujname
phone
addies*
crty
172-32-1176
White
Johnson
408 496-7223
10932 Bigge
Menlo Park
213-46-8915
Green!
Marjorie
415 986-7020
303 63rd St.
Oakland
238-95-7766
Carson
Cheryl
415 548 7723
589 Darwin L
Berkeley
267-41-2394
O'Leary
Michael
408 286-2428
22 Cleveland
San Jose
274-80 9391
Straight
Dean
415 834-2919
5420 College
Oakland
341-22-1782
Smith
Meander
913 843-0462
10 Mississipp
Lawrence
409-56 7 008
Bennet
Abraham
415 658 9332
6223 Batema
Berkeley
427-17-2319
Dull
Ann
415836-7128
3410 Blonde
Palo Alto
472-27-2349
Grindesbv
Burt
707 938-6445
PO Box 792
Covelo
au id
aujname
aujname
phone
addies*
crty
172-32-1176
White
Johnson
408 496-7223
10932 Bigge
Menlo Park
213-46-8915
Green!
Marjorie
415 986-7020
303 63rd St.
Oakland
238-95-7766
Carson
Cheryl
415 548 7723
589 Darwin L
Berkeley
267-41-2394
O'Leary
Michael
408 286-2428
22 Cleveland
San Jose
274-80 9391
Straight
Dean
415 834-2919
5420 College
Oakland
341-22-1782
Smith
Meander
913 843-0462
10 Mississipp
Lawrence
409-56 7 008
Bennet
Abraham
415 658 9332
6223 Batema
Berkeley
427-17-2319
Dull
Ann
415836-7128
3410 Blonde
Palo Alto
472-27-2349
Grindesbv
Burt
707 938-6445
PO Box 792
Covelo
Загрузить I Обновить данные
Загрузить I Обновить данные
Рис. 4.6. Форма с элементом управления DataGrid
Создание проекта и формы
Для создания проекта и формы сделайте следующие шаги.
Выберите меню File, укажите пункт New и затем выберите Project
В левой области открывшегося окна Project Types выберите Visual Basic Projects или Visual C# Projects и затем в правой области Templates щелкните на Windows Application.
Если у вас уже открыто какое-либо приложение, то необходимо установить переключатель Close Solution, чтобы автоматически закрыть его.
Примечание
В реальных проектах часто удобно использовать возможность одновременной работы с несколькими проектами. Тем не менее, в данном и последующих примерах закрывайте текущее открытое приложение при создании нового. Это обеспечит однозначное разделение прошедших и предстоящих действий.
Назовите проект уникальным именем, которое будет ассоциироваться у вас с выполняемыми действиями. Например, данный проект можно назвать SimpleGrid.
Когда вы назначили имя проекта, щелкните кнопку ОК.
Visual Studio создаст новый проект и отобразит Windows-форму в окне дизайнера.
Создание набора данных DataSet
Основным способом работы с базами данных в Windows-формах является использование набора данных DataSet. В приложениях DataSet — это некий контейнер (кэш), содержащий интересующие записи. Чтобы создать набор данных нужно выполнить ряд шагов.
Q Создать элементы,обеспечивающие доступ к базе данных:
connection и DataAdapter. Адаптер доступа к данным фактически содержит SQL-запросы, используемые для чтения, добавления, удаления и обновления информации в базах данных. Мастер поможет вам выполнить подключение к базе данных и сформировать набор необходимых запросов.
Q Создать схему данных. На этом этапе вы будете использовать Visual Studio для создания структуры DataSet, включающей набор таблиц и связей между ними.
Важно, чтобы вы прошли последовательно все процедуры примера из данного раздела. В противном случае вы не получите набора данных DataSet, который будет использоваться не только в этом, но и в последующих примерах.
Создание и конфигурирование элементов доступа
к данным Connection и DataAdapter
Чтобы получить данные на компьютер пользователя необходимо создать соединение с базой данных и элемент DataAdapter, который содержит SQL-
запросы и используется для заполнения данными элемента DataSet. Для создания и конфигурирования этих элементов будет использоваться соответствующий мастер Visual Studio.
Для создания элементов connection и DataAdapter выполните следующие действия.
ИзвкладкиDataокнаToolboxперетащитемышьюнаформуобъект
OleDbDataAdapter (рис. 4.7).
Рис. 4.7. Объект OleDbDataAdapter в окне Toolbox
Примечание
Вы также можете выполнить этот пример, используя SqlDataAdapter, который оптимизирован для работы с SQL Server версии 7.0 и выше. Мы использовали OleDbDataAdapter потому, что он является общим объектом и позволяет через ADO.NET иметь доступ ко всем OLE DB-совместимым источникам данных.
Запустится Data Adapter Configuration Wizard, который поможет вам создать и сконфигурировать два объекта Connection и DataAdapter.
В мастере сделайте следующие действия.
На второй странице выберите существующую (или создайте) связь с таблицей Pubs базы данных SQL Server (рис. 4.8).
На третьей странице определите, что вы хотите использовать SQL- запросы для доступа к базе данных Use SQL statements (рис. 4.9).
На четвертой странице создайте следующий SQL-запрос:
SELECT authors.* FROM authors
Для помощи в создании SQL-запроса, щелкните на кнопку Query Builder для вызова построителя запросов (рис. 4.10).
- • ' - - ' -f'- —‘ — *TTTt*»— -. ■ - . -
Adapter ConfiBUtalton Wizard
Choose Your Data Connection
The data adapter wii execute queries using this connection to load and update data.
Choose from the list of data connections currently In Server Explorer or add a new connection if the one you want is not listed.
Which data connection should the data adapter use?
Netv Connection...Netv Connection...Рис. 4.8. Создание или выбор объекта Connection для адаптера данныхРис. 4.8. Создание или выбор объекта Connection для адаптера данныхjAAA.pubs.dbo
Netv Connection...
Netv Connection...
Рис. 4.8. Создание или выбор объекта Connection для адаптера данных
Рис. 4.8. Создание или выбор объекта Connection для адаптера данных
Рис. 4.10. Окно формирования SQL-запроса
Примечание
В данном примере вы получите все строки из таблицы authors. В реальных приложениях обычно строят оптимизированные запросы, которые возвращают только определенные строки и столбцы. Как строится оптимизированный запрос, вы узнаете несколько позже из раздела "Работа с данными в Windows- формах с параметризованными запросами".
. В построителе запросов выберите в списке доступных таблиц базы данных Pubs таблицу authors и нажмите кнопку Add, щелчком на кнопке Close закройте окно Add Table (рис. 4.11).
В главном окне построителя запросов установите флажок All Columns. Это значит, что вы желаете получить значения всех столбцов исходной таблицы и нажмите кнопку ОК (рис. 4.12).
В окне Data Adapter configuration Wizard появится текст сформированного запроса (рис. 4.13).
В пятом окне мастер конфигурации покажет перечень сгенерированных им элементов объекта DataAdapter (рис. 4.14).
Нажмите на кнопку Finish для завершения работы мастера. После этого объекты OleDbConnection1 и OleDbDataAdapter1 будут добавлены в вашу форму.
Мастер создаст объектOleDbConnection1,содержащий информацию о том, как получить доступ к базе данных, и объект OleDbDataAdapter1, который содержит запрос, указывающий, какие колонки какой таблицы требуется получить из базы данных. Причем оба объекта не содержат самих данных. Следующим шагом необходимо создать еще один объект, который и примет выбранные из базы данные.
Рис. 4.11. Окно выбора таблицы базы данных в построителе SQL-запросов
Рис. 4.12. Выбор колонок таблицы в окне построителя запросов
Рис. 4.13. Текст сформированного запроса
Рис. 4.14. Перечень элементов, созданных мастером конфигурирования адаптера данных
Создание объекта DataSet
После того, как вы задали к какой базе данных необходимо подключиться и определись с информацией, которую желаете получить (через SQL-запросы адаптера данных), вы можете создать объект, который будет содержать сами данные — DataSet. При этом Visual Studio сгенерирует набор данных автоматически, базируясь на запросе, который был определен в адаптере данных.
Для создания набора данных выполните следующие действия.
В меню Data выберите пункт Generate DataSet.
Примечание j
Если меню Data не доступно, то щелкните мышью в любом месте формы, тогда форма получит фокус и меню станет доступно.
После этого появиться диалоговое окно Generate Dataset (рис. 4.15).
Рис. 4.15. Диалоговое окно Generate Dataset
В появившемсяокневампредложеносоздатьновыйDataSetсименем
DataSet1, который будет принимать из OleDbDataAdapter1 таблицу authors.
Убедитесь, что установлен флажок Add this dataset to the designer, и нажмите кнопку ОК.
В результате Visual Studio сгенерирует класс DataSet1 и схему, которая его описывает — файл DataSet1.xsd. Этот файл можно увидеть в окне Solution Explorer,
В итоге Visual Studio добавит к форме компонент DataSet1.
Итак, вы сделали абсолютно все, чтобы получить требуемую информацию из базы данных (при этом не написали ни строчки программного кода). Теперь необходимо добавить на форму элемент, который позволит отобразить полученную информацию — DataGrid.
Добавление элемента управления DataGrid для отображения данных
В этом разделе вы добавите на форму традиционный элемент управления DataGrid, который обычно используется для отображения всех записей, содержащихся в наборе данных. Как альтернативный вариант отображения информации можно использовать элементы управления TextBox, однако это потребует добавления на форму элементов, позволяющих выполнять навигацию (перемещение) по записям набора данных. При использовании DataGrid В этом нет необходимости.
Для добавления элемента управления DataGrid на форму выполните следующие действия.
Щелкните левой кнопкой мыши в любом свободном месте формы Form1, чтобы форма стала активной и получила фокус.
Из вкладки Windows Forms окна Toolbox, перетащите элемент DataGrid на форму (рис. 4.16).
Рис. 4.16. Элемент DataGrid в окне Toolbox
Нажмите клавишу <F4> для перехода в окно свойств элемента DataGrid.
В свойстве DataSource выберите DataSetll в качестве источника данных (не выбирайте DataSet11.authors).
В свойстве DataMember выберите таблицу authors.
Установив эти два свойства, вы фактически связали DataGrid с таблицей authors из набора данных DataSet1. После этих действий в сетке данных DataGrid появились столбцы с заголовками полей выводимых данных.
Измените размер DataGrid так, чтобы в сетке данных было видно несколько колонок и строк (рис. 4.17).
Рис. 4.17. Расположение элемента DataGrid на форме
Заполнение элемента управления
Data Grid данными
Несмотря на то, что между элементом DataGrid и набором данных DataSet на этапе проектирования установлена связь, заполнение сетки данными автоматически не происходит. Вы должны инициировать этот процесс, вызвав соответствующие методы в программном коде.
Для заполнения DataGrid данными необходимо выполнить следующие действия.
ИзвкладкиWindowsFormsокнаToolboxперенеситенаформуэлемент
управления Button,
Измените свойство кнопки Text с Button1 на Загрузить.
Двойным щелчком на кнопке создайте заготовку модуля обработки события click.
Очистите набор данных DataSet11 методом clear, затем заполните его данными, используя метод Fill элемента OleDbDataAdapter1.
Следующий программный код (листинг 4.2) иллюстрирует вызов этих методов.
.......,M......,...,—r.^—,-"—f—’——.— ■■■—<■..—•—<—.■••■■—.„.„г...,.„м„.^.......................-.-^^.,.,иж ~~.„.^-,
: Листинг 4.2
' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As ':■ System. EventArgs) Handles Button1.Click
DataSet11.Clear()
OleDbDataAdapter1.Fill(DataSet11)
End Sub
// C#
private void Button1_Click (object sender, System.EventArgs e)
{
DataSet11.Clear();
OleDbDataAdapter1.Fill(DataSetll);
}
Как видите, программные коды на Visual Basic и на С# практически ничем не отличаются (за исключением некоторых синтаксических особенностей С#). Запустите ваше приложение, нажмите кнопку Загрузить — и вы увидите результаты работы только что написанной программы (рис. 4.18).
au_id
au_lname
| aujname
phone
address
city*
►172-32-1176
White
Johnson
408 496-7223
10932 Bigge
Menb Park
213-46-8915
Green
Marjorie
415 986-7020
309 63rd St
Oakland
238-95-7766
Carson
Cheryl
415 548-7723
589 Dai win L
Berkeley —
,267-41-2394
O'Leary
Michael
408 286-2428
22 Cleveland
San Jose
274-80-9391
Straight
Dean
415 834-2919
5420 Colege
Oaklarxj
341-22-1782
Smith
Meander
913 843-0462
10 Mississipp
Lawrence
409-56-7008
Bennet
Abraham
415 658-9932
6223Batema
Berkeley
427-17-2319
Dull
Ann
415 836-7128
3410 Blonde
Palo Alto
1472-27-2349
<1
Grhdesbv
But
707 938-6445
P0 Box 792
Covelo -Zj 2J
Загрузить
Итак, в результате проделанной работы создана Windows-форма, в которой отображена информация, полученная из базы данных. При этом, заметьте, было написано всего 2 строчки программного кода (не фантасти- ка-ли!). Причем, вам уже не составит труда сделать все то же самое, используя другой язык программирования. Так что Visual Studio все более реально воплощает в жизнь лозунг: "Программисты всех языков — объединяйтесь!"
Если вас не совсем устраивает внешний вид элемента DataGrid, можете поэкспериментировать с его "раскраской". Для этого достаточно щелкнуть правой кнопкой мыши в любом месте DataGrid и из появившегося меню выбрать пункт Auto format. В открывшемся окне (рис. 4.19) можно выбрать любой из предложенных стилей и, запустив приложение, полюбоваться "своими" дизайнерскими способностями.
Рис. 4.19. Окно форматирования Auto format элемента DataGrid
Обновление информации в базе данных
Элемент управления DataGrid позволяет пользователю корректировать информацию непосредственно в сетке данных. Когда пользователь изменяет данные в DataGrid, автоматически обновляется и набор данных DataSet. Однако эти изменения не вносятся непосредственно в таблицы исходной базы данных (не забывайте, что вы работаете с несвязанной копией фрагмента базы данных).
Когда данные изменились в DataSet, вы должны инициализировать внесение этих изменений в исходную базу данных. Объект DataAdapter может выполнить эти действия через свой метод Update, который проверяет каждую запись в DataSet и, если были сделаны изменения, отправляет их в исходную базу данных.
В следующем примере вы добавите кнопку на форму, нажав которую пользователи смогут инициализировать процесс отправки изменений в базу данных.
Для задания кнопки обновления базы данных выполните следующие действия.
Из вкладки Windows Forms окна Toolbox, перенесите на форму элемент управления Button,
Измените СВОЙСТВО КНОПКИ Text С Button2 На Обновить данные.
Двойным щелчком на кнопке создайте заготовку модуля обработки события Click.
В нем, вызовите метод Update объекта OleDbDataAdapter1, который внесет изменения в базу данных.
Используйте объект MessageBox для вывода информации об успешном завершении операции обновления данных.
Программный код, показанный в листинге 4.3, иллюстрирует вызов этих методов.
Листинг 4.3
' Visual Basic
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As^ System. EventArgs) Handles Button2.Click
OleDbDataAdapter1.Update(DataSet11)
MessageBox.Show("Данные успешно обновлены!")
End Sub
// C#
private void Button2_Click(object sender, System.EventArgs e)
(
OleDbDataAdapter1.Update(DataSet11);
MessageBox.Show("Данные успешно обновлены!");
}
Попробуйте запустить приложение, загрузить данные в DataGrid, исправить некоторые записи и внести сделанные изменения в исходную базу данных (рис. 4.20).
Будем надеяться, что вам удалось через DataGrid внести свежую информацию в базу данных, и наш совместный труд не пропал даром. Следующим
нашим шагом будет знакомство с возможностями использования текстовых полей для доступа к данным и их корректировки.
Рис. 4.20. Возврат изменений пользователя в исходную базу данных
Доступ к данным в Windows-формах с использованием текстовых полей
Вначале несколько модифицируем форму предыдущего примера:
Q добавим несколько элементов управления TextBox для отображения информации;
Q установим связь этих элементов с уже созданным объектом DataSet;
Q добавим управляющие элементы Button, обеспечивающие навигацию (перемещение) по записям базы данных;
Q добавим элементы Label, отображающие надписи к текстовым полям, а также номер текущей записи.
В текстовые поля будем выводит следующую информацию из таблицы authors базы данных Pubs: ИМЯ — au_lname, фамилию — au_fname , город — city и код штата — state.
Для реализации вышеописанного выполните следующие действия.
- Добавьте на форму, созданную в предыдущем разделе, следующие элементы управления: 4 элемента TextBox, 2 элемента Button, 6 элементов Label.
Расположите их на форме, как показано на рис. 4.21.
Рис. 4.21. Расположение добавленных элементов управления на форме
Измените свойства этих элементов в соответствии с табл. 4.1.
Таблица 4.1. Значения свойств элементов управления
Элемент
Назначение
Свойство Name
Свойство Text
Label
Надпись "Имя"
Label1
Имя
TextBox
Имя (поле аи lname)
TextBox1
Label
Надпись "Фамилия"
Label2
Фамилия
TextBox
Фамилия (поле аи fname)
TextBox2
Label
Надпись "Город"
Label3
Город
TextBox
Город (поле city)
TextBox3
Label
Надпись "Код штата"
Label4
Код штата
TextBox
Код штата (поле state)
TextBox4
Label
Надпись "Номерзаписи"
Label5
Label
Номерзаписи
Label6
№
Button
Сдвиг на запись вверх
Button3
Вверх
Button
Сдвиг на запись вниз
Button4
Вниз
После выполненных действий вы получите форму следующего вида (рис. 4.22).
Рис. 4.22. Элементы управления формы после переустановки их свойств
Связывание элементов TextBox с набором данных
Четыре текстовых поля предназначены для отображения информации из одной записи набора данных. Для того чтобы содержимое текстовых полей автоматически обновлялось при смене записи, их необходимо связать с соответствующими колонками набора данных DataSet. Для связывания с данными обычно используется свойство элементов управления TextBox.
Для связи текстовых полей с DataSet выполните следующие действия.
Вернитесь в окно дизайнера формы.
Выделите элемент TextBox1 и нажмите кнопку <F4> для перехода в окно свойств этого элемента.
Найдите свойство DataBindings и раскройте его (рис. 4.23), щелкнув мышью на значке "+" в его вершине.
Рис. 4.23. Свойство DataBindings текстового поля
Из раскрывшегося списка выберите свойство Text, в пустой строке которого нажмите кнопку, после чего появится дополнительное окно со структурой объекта DataSetll.
Раскройте содержимое объекта DataSetll и выберите из таблицы authors то поле, с которым вы хотите связать с элементом формы TextBox1 (в данном случае мы связываем с au_lname). Щелкните мышью на au_lname. В результате этих действий свойству Text будет присвоено значение authors.au_lname объекта DataSet11 (рис. 4.24).
Рис. 4.24. Связывание текстового поля с колонкой таблицы объекта DataSet
Повторите шаги 2, 5 для остальных текстовых полей (TextBox2, TextBox3, TextBox4), связав их с элементами набора данных DataSetll — authors.au_fname, DataSet11— authors.city,
DataSet11 —authors.state.
После этих действий уже можно посмотреть результаты своего труда. Запустите приложение и заполните сетку данными, нажав кнопку Загрузить. Если все было сделано правильно, то вы увидите, что в текстовых полях отображается та же информация, что и в DataGrid (рис. 4.25).
Теперь попробуйте скорректировать информацию в текстовом поле, а затем передвинуться на другую строку в DataGrid. Ваша корректировка немедленно будет отражена в сетке данных. Это говорит о том, что действительно между текстовыми полями TextBox и колонками набора данных DataSet установлена связь. Однако ваши исправления не будут зафиксированы в исходной таблице базы данных, пока вы не нажмете кнопку Обновить данные, что подтверждает факт вашей работы в отрыве от исходной таблицы authors базы данных Pubs.
Если данные отображаются в элементе DataGrid, то навигация по записям осуществляется достаточно просто — либо мышью, либо клавишами со стрелками. При отображении данных в текстовых полях на форму необходимо добавлять элементы управления, обеспечивающие переход от одной записи к другой. Мы для этой цели добавили на форму две кнопки Вниз, Вверх.
au_idau_hameaujnamephoneaddresscrly
172-32-1176WeJohnson408 496-722310932 BiggeMenlo Park
213-46-8915 taeen |M««ie [415 986-7020 , 309 63rd St |OakJ<id
238-95-7766 Carson Cheryl 415 548-7723 589 Dawn L Berkeley — ;267-41-2394O'LearyMichael403 286-242822ClevelandSanJose
274-80 9391SlrarghlDean415 834-29195420 CollegeOakland
341-22-1782SmithMeander913 843-0462lOMtssrssippLawrence
409 56-7006BennerAbraham415 658-99326223BaemaBerkeley
Palo Alto CoveloPalo Alto Covelo427-17-2319DJAnn415 83671283410Blonde
Palo Alto Covelo
Palo Alto Covelo
472-27-2349GrndestwBurt707 938-6445PO Box 792
Заградить | Обновить данные
ВверхВверхИмя(GreenФамилия[мапопе
Вверх
Вверх
Город[OaklandКод штата(са
Номер записиHt
Рис. 4.25. Отображение данных в элементе DataGrid и текстовых полях
Номер текущей записи, можно получить (или задать) из свойства position объекта BindingContext. Изменяя значение этого свойства, вы будете перемешать указатель записи на нужную позицию. Для определения количества записей в таблице данных можно обратиться к свойству Count объекта BindingContext. Итак, добавим программный код к кнопкам, обеспечивающим навигацию по записям.
Двойным щелчком на кнопке Вверх (Button3) создайте обработчик события click. Добавьте программный код (листинг 4.4), обеспечивающий переход на предыдущую запись путем уменьшения на 1 свойства Position объекта BindingContext:
Листинг 4.4
' Visual Basic
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As^ System. EventArgs) Handles btnPrevious.Click:
Me.BindingContext(DataSetll, "authors").Position-=1
End Sub
// C#
private void Button3_Click(object sender, System.EventArgs e)
(
this.BindingContext[DataSet11, "authors"].Position-=1;
)
По аналогии для кнопки Вниз (Button4) добавьте программный код (листинг 4.5), обеспечивающий переход на следующую запись путем увеличения на 1 свойства Position объекта BindingContext:
Листинг 4.5 i
' Visual Basic
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e Asъ System. EventArgs) Handles btnPrevious.Click
Me.BindingContext(DataSet11, "authors").Position+=1
End Sub
// C#
private void Button4_Click(object sender, System,EventArgs e)
{
this.BindingContext[DataSet11, "authors"].Position+=1;
Запустите приложение и проверьте, что созданные кнопки действительно осуществляют перемещение по записям.
Отображение номера текущей записи
В завершении реализуем метод ShowPosition для отображения номера текущей записи и суммарного количества записей в наборе данных. Эту информацию будем отображать в элементе управления Label6.
Создайте метод (модуль) с именем ShowPosition. В этом модуле получите текущую позицию из свойства Position, а число записей - из свойства Count объекта BindingContext и отобразите их в элементе управления Label6. Программный код будет выглядеть следующим образом (листинг 4.6).
Листинг 4.6
' Visual Basic
PrivateSub ShowPosition ()
Dim iCnt As Integer'Количество записей
Dim iPos As Integer'Номер записи
iCnt=Me. BindingContext (DataSet11, "authors") .Count
If iCnt=0 Then
Label6.Text=" (No records) "
Else
iPos=Me.BindingContext(DataSet11, "authors").Position+1
Label6.Text=iPos.ToString & " из " & iCnt.ToString End If
End Sub
// C#
private void ShowPosition()
{
int iCnt;
int iPos;
iCnt=this.BindingContext[DataSet11, "authors"].Count;
iPos=this.BindingContext[DataSet11, "authors"].Position+1;
if(iCnt==0)
{
Label6.Text="(No records)";
}
else
{
Label6.Text=iPos.ToString() + " из " + iCnt.ToString();
} }
Добавьте вызов метода showposition в обработчик события click кнопки Buttons (листинг 4.7) .
Листинг 4.7
' Visual Basic
PrivateSubButton3_Click(ByValsenderAsSystem.Object,ByValeAsЪSys
tem. EventArgs) Handles btnPrevious.Click
Me.BindingContext(DataSet11, "authors").Position-=1
ShowPosition()
End Sub
// C#
private void Button3_Click(object sender, System.EventArgs e)
{ this. BindingContext [DataSetll, "authors"] .Position-=1;
ShowPosition();
}
Аналогично запрограммируйте действие кнопки Button4 ( листинг 4.8).
Листинг 4.8
.^^—:.„.....;............-.„—-...■■—„.;.-—;.........■_.'
' Visual Basic
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System. EventArgs) Handles btnPrevious.Click
Me.BindingContext(DataSet11, "authors").Position+=1
ShowPosition()
End Sub
// C#
private void Button4_Click(object sender, System.EventArgs e)
{
this.BindingContext[DataSet11, "authors"].Position+=1;
ShowPosition();
}
Запустите приложение и проверьте работу элементов, отображающих текущую запись набора данных.
Выборка и сортировка данных через запросы с параметрами
Традиционно при работе с информационными системами пользователю нужна не вся информация из базы данных. Например, требуется выбрать заказы только определенного клиента или книги одного автора и т. п. В этом случае пользователь вводит в определенные элементы формы (или выбирает из справочных таблиц) некую ключевую информацию, на основе которой формируется запрос, возвращающий только заказанные данные.
Использование запросов с параметрами обеспечивает вашему приложению более эффективную работу, позволяя получать отфильтрованные и отсортированные записи и значительно снизить сетевой трафик.
В следующем примере вы модифицируете Windows-форму, которая будет показывать только определенных авторов из базы данных Pubs SQL-севера. Пользователи будут вводить код штата США (например, СА для Калифорнии) и объект Dataset будет заполняться данными только тех авторов, которые проживают в данном штате. Для этого необходимо добавить на форму элемент, обеспечивающий пользователю ввод кода штата, модифицировать объекты доступа к данным таким образом, чтобы они возвращали только необходимые пользователю записи.
Для реализации этого примера вам необходимо иметь доступ к базе данных Pubs, которая устанавливается при инсталляции MS SQL Server.
Для реализации примера потребуется несколько шагов:
Q создание формы;
Q создание и конфигурирование набор данных, на этом этапе будет создан и SQL-запрос, который будет заполнять набор данных записями из базы данных;
Q добавление элементов отображения информации на форме;
Q добавление программного кода, который будет обновлять набор данных после того, как пользователь присвоит новые значения параметрам запроса;
Q добавление программного кода, чтобы обеспечить перемещение между записями набора данных.
Создание проекта и Windows-формы
На первом шаге создается Windows-форма в следующей последовательности.
Из меню File выберите подменю New и затем выберите пункт Project.
Появиться диалоговое окно New Project.
В дереве Project Types выберите тип проекта: Visual Basic Projects или Visual C# Projects, и в области Templates укажите вид приложения — Windows Application.
Еслиувасужеоткрытодругоеприложение,тоустановите переключа
тель Close Solution в окне New Project.
Задайте проекту новое имя, которое будет уникальным и отражать суть разрабатываемого приложения. Например, в данном случае назовем этот проект WinParameters. После задания имени проекта нажмите кнопку ОК.
После этого Visual Studio создаст проект и отобразит новую Windows-форму в окне дизайнера.
На следующем шаге добавьте к форме и сконфигурируйте набор данных в следующей последовательности.
Q Создайте адаптер данных, с использованием соответствующего мастера. Адаптер данных содержит SQL-запрос, который будет считывать информацию из таблицы базы данных и передавать ее объекту DataSet. Мастер поможет создать SQL-запрос, а также соединение с базой данных.
Q Сгенерируйте схему набора данных. При создании схемы Visual Studio создаст и новый, класс DataSet, который будет добавлeн к форме.
Создание и конфигурирование объектов DataConnection и DataAdapter
Для создания И конфигурирования объектов DataConnection И DataAdapter выполните следующие действия.
Из вкладки Data окна Toolbox, перенесите на форму объект OleDbDataAdapter.
Примечание
Вы можете также использовать объект SqlDataAdapter, который оптимизирован для работы SQL Server версии 7.0 и выше.
Будет запущен мастер Data Adapter Configuration Wizard, который поможет создать объекты DataConnection И DataAdapter.
В мастере выполните следующие действия.
На второй странице создайте или выберите соединение, указывающее на базу данных Pubs вашего SQL-сервера (рис. 4.26).
Рис. 4.26. Выбор соединения, указывающего на базу данных Pubs
На третьей странице укажите, что вы хотите использовать SQL- запрос для обращения к базе данных.
На четвертой странице создайте следующий SQL-запрос (рис. 4.27):
SELECT аи id, au_lname, state FROM authors WHERE (state=?)
Рис. 4.27. Формирование запроса в окне Query Builder
Вопросительный знак (?) представляет собой метку-заполнитель для параметра. (Если вы используете класс SqlDataAdapter, то на месте знака вопроса будет стоять переменная для принятия значения от параметра, например estate.)
Примечание
Для помощи формирования SQL-запроса нажмите Query Builder, чтобы запустить мастер формирования запросов Query Builder. Чтобы сформировать метку-заполнитель для параметра, введите вопросительный знак в столбец Criteria для поля state.
Мастер создаст соединение с базой данных (объект OleDbConnection) и адаптер данных (объект OleDbDataAdapter1).
Адаптер данных фактически будет содержать четыре SQL-запроса: один для выборки записей, который вы собственно и создали на основе предложения SELECT, а также три дополнительных запроса — для модификации, добавления и удаления записей (на основе предложений UPDATE, INSERT и DELETE).
В этом примере мы будем использовать только один запрос на выборку записей на основе предложения SELECT. Перечень параметров команды SelectCommand можно посмотреть В окне свойств (рис. 4.28).
Рис. 4.28. Доступ к коллекции параметров команды SelectCommand
Сам SQL-запрос с предложением SELECT будет храниться в свойстве SelectCommand адаптера данных. Свойство SelectCommand представляет собой объект команды данных (объект типа OleDbCommand), в котором содержится не только SQL-запрос, но и другая информация, необходимая для выполнения SQL-запроса. Наиболее важным элементом команды данных является коллекция параметров Parameters. Эта коллекция содержит набор параметров (типа OleDbParameter), причем каждый параметр соответствует одной из меток-заполнителей (поименованному параметру) SQL-запроса. В этом примере мы использовали одну метку-заполнитель, значит, в коллекции Parameters метке-заполнителю будет соответствовать единственный параметр — значение для поля state (рис. 4.29).
Рис. 4.29. Коллекция параметров команды SelectCommand
По умолчанию, Data Adapter Configuration Wizard при формировании параметров присваивает им имена соответствующих столбцов таблицы базы данных. В нашем примере задана только одна метка-заполнитель для столбца state, соответственно мастером будет создан один параметр с именем state. Позже мы узнаем, как присвоить значение этому параметру перед выполнением SQL-запроса.
Созданиенабораданных
После того, как созданы объекты соединения с базой данных и адаптер данных, можно создать набор данных. В Visual Studio можно сгенерировать набор данных автоматически, основываясь на SQL-запросе, который был создан в адаптере данных. Набор данных — это экземпляр класса DataSet, создаваемого на основе XML-схемы (xsd-файла), в которой описываются элементы данного класса (таблицы, колонки и ограничения).
Для создания DataSet нужно выполнить следующие шаги.
В меню Data выберите пункт Generate DataSet.
Примечание
Если меню Data не доступно, щелкните мышью в любом месте формы. Форма должна иметь фокус, чтобы это меню стало доступным.
Появится диалоговое окно Generate Dataset (рис. 4.30).
Рис. 4.30. Диалоговое окно Generate DataSet
Задайте набору данных имя dsAuthors, убедитесь, что установлен флажок Add this dataset to the designer и затем нажмите кнопку ОК.
После этого Visual Studio сгенерирует класс типизированного набора данных (dsAuthors) и схему, которая описывает его структуру. Схема будет содержаться в файле dsAuthors.xsd, который появится в окне Solution Explorer. Если вы в окне Solution Explorer нажмете кнопку Show All Files на верхней панели, то будет видно, что файл схемы имеет зависимый файл (с расширением vb или cs, в зависимости от используемого языка программирования), содержащий код, который определяет ваш новый класс набора данных (рис. 4.31).
</! Solution WmPwametrs (1 project)
■^1 Reference! bn
obj5 Assemblylnfo.vbaI dsAuthots.xsd43 dsAuttws.vb" Forml.vbobj5 Assemblylnfo.vbaI dsAuthots.xsd43 dsAuttws.vb" Forml.vb
obj
5 Assemblylnfo.vb
aI dsAuthots.xsd
43 dsAuttws.vb
" Forml.vb
obj
5 Assemblylnfo.vb
aI dsAuthots.xsd
43 dsAuttws.vb
" Forml.vb
Рис. 4.31. Окно Solution Explorerпосле нажатия кнопки Show All Files
Наконец, Visual Studio добавит к форме экземпляр этого класса набора данных (с именем DsAuthors1 в Visual Basic, или dsAuthors1 в С#).
К этому моменту мы создали все элементы, для того, чтобы получить информацию из базы данных и поместить ее в набор данных. Все готово для создания формы, на которой можно отобразить эти данные.
Добавление элементов отображения данных
Для реализации данного примера нужно расположить на форме элементы, с помощью которых пользователь сможет ввести значение штата (текстовое поле state), которое потребуется для выполнения запроса, и отобразить информацию об авторах, полученную из базы данных. Для отображения информации будут использоваться текстовые поля.
Добавьте к форме следующие элементы, дав им те имена, которые приведены в табл. 4.2.
Добавьте на форму элементы label (напротив каждого текстового поля) и внесите в них функциональное назначение каждого поля. Расположите элементы на форме как показано на рис. 4.32.
Построение Windows-приложений с доступом к данным через ADO.NET205
Таблица 4.2. Элементы управления и их свойства
Элементы
Назначение элемента
Имя элемента (Name)
Значение свойства Text
TextBox
Позволяетпользователям
вводить обозначение штата (критерий поиска авторов)
txtStateParameter
(Пустая строка)
Button
Выполняет запрос и заполняет набор данных
btnShow
Показать авторов
TextBox
Отображаетидентификатор
автора
txtAuthorID
(Пустая строка)
TextBox
Отображает фамилию автора
txtAuthorLName
(Пустая строка)
TextBox
Отображает штат, в котором живет автор (для демонстрации правильности работы запроса)
txtAuthorState
(Пустая строка)
Рис. 4.32. Расположение элементов отображения данных на форме
Добавление кода для заполнения набора данных
Когда форма появится на экране, набор данных будет пустой (он не заполняется автоматически). В данном примере процедура заполнения объекта DataSet данными будет активизироваться принудительно, когда пользователь нажмет кнопку Показать авторов. При ее нажатии будет выполняться запрос, указанный в адаптере данных, а результаты работы запроса будут помещаться в набор данных. Перед выполнением запроса ему нужно будет передать значение параметра (код штата). Значение па-
раметра будем брать из текстового поля TxtStateParameter, в которое пользователь будет вводить интересующий его штат. Для выполнения запроса будет вызываться метод Fill адаптера данных. Запрограммируйте эти действия.
Дважды щелкните кнопку Показать авторов, чтобы создать процедуру обработки события click. Добавьте код к обработчику этого события:
Q Установите значение единственного параметра, требуемого для выполнения SQL-запроса. Параметру присвойте то значение, которое пользователь введет В текстовом поле txtStateParameter.
Q Вызовите метод очистки набора банных clear. Если набор данных не очищать, то записи, возвращаемые SQL-запросом, будут каждый раз добавляться в конец набора данных при нажатии на кнопку Показать авторов.
Q Вызовите метод Fin адаптера данных, передавая ему в качестве параметра тот набор данных, который нужно заполнить.
Описанные выше действия приведены в следующем программном коде (листинг 4.9).
Листинг4.9
L-5—.- ;ш
' Visual Basic
Private Sub btnShow_Click(ByVal sender As System.Object, ByVal e As% System. EventArgs) Handles btnShow.Click
OleDbDataAdapter1.SelectCommand.Parameters("state").Value =ъ
txtstateParameter.Text
DsAuthors1.Clear()
OleDbDataAdapter1.Fill(DsAuthors1)
End Sub
// C#
private void btnShow_Click(object sender, System.EventArgs e)
{
OleDbDataAdapter1.SelectCommand.Parameters["state"].Value =%>
txtstateParameter.Text;
dsAuthors1.Clear();
OleDbDataAdapter1.Fill(dsAuthors1);
}
Связывание текстовых полей с набором данных
Три текстовых ПОЛЯ txtAuthorID, txtAuthorLName, txtAuthorState предназначены для того, чтобы отображать информацию из отдельных записей таблицы authors набора данных. Для того чтобы при смене записей значения текстовых полей обновлялись автоматически, необходимо связать столбцы таблицы данных с текстовыми полями. Механизм связывания гарантирует корректность обновления текстовых полей при смене записей.
Фактически можно связать любое свойство текстового поля с любым столбцом набора данных. В данном примере мы свяжем свойство Text текстового поля с именем столбца, который требуется отобразить.
Связывание текстовых полей с набором данных необходимо выполнить в следующей последовательности.
Вернитесь во вкладку дизайнера формы.
Выделите мышью первое текстовое поле (txtAuthorID) и нажмите клавишу <F4>, чтобы открыть окно свойств Properties.
Раскройте узел DataBindings свойства Text разверните узел авторов dsAuthors и из раскрывающегося списка выберите au_id (рис. 4.33).
Рис. 4.33. Связывание текстового поля с колонкой таблицы набора данных
Повторите шаги 2 и 3 для двух оставшихся текстовых полей, связав их с ПОЛЯМИтаблицыDsAuthors1.authors.au_lnameИ
DsAuthors1.authors,state.
Итак, мы реализовали возможность отображать содержание записей набора данных в текстовых полях. Однако у нас пока нет возможности перемещаться между записями набора данных.
Добавление навигации по записям
В заключении добавим к форме элементы, обеспечивающие навигации по записям объекта DataSet. В этом примере мы добавим две кнопки Предыдущая и Следующая, а также добавим текстовое поле, в котором будет отображаться номер текущей записи.
Для получения номера текущей записи таблицы данных используется свойство Position, которое доступно через объект BindingContext. Чтобы перемещаться по записям таблицы набора данных, нужно изменять значение этого свойства. Чтобы определить сколько записей находится в таблице данных, нужно получить значение свойства count объекта BindingContext.
Для добавления объектов навигации выполните следующие действия.
Добавьте к форме две дополнительные кнопки, установив их свойства в соответствии с табл. 4.3.
Таблица 4.3. Свойства элементов управления Button
Name (имя)Text (текст)
BtnNextСледующая
BtnPreviousПредыдущая
Создайте обработчик события нажатия кнопки Предыдущая. Добавьте программный код декремента (уменьшения на единицу) свойства position объекта BindingContext. Код будет выглядеть следующим образом (листинг 4.10).
Листинг 4.10
' Visual Basic
Private Sub btnPrevious_Click(ByVal sender As System.Object, ByVal e As^ System.EventArgs) Handles btnPrevious.Click
Me.BindingContext(DsAuthors1, "authors").Position-=l
End Sub
// C#
private void btnPrevious_Click(object sender, System.EventArgs e)
{
this.BindingContext[dsAuthors1, "authors"].Position-=l;
}
СделайтетожесамоедлякнопкиСледующая, толькоувеличьтезначе
ние свойства Position на единицу (листинг 4. И).
Листинг 4.1 1
'Visual Basic
Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e Asъ System. EventArgs) Handles btnNext.Click
Me.BindingContext(DsAuthors1, "authors"),Position+=l
End Sub
// C#
private void btnNext_Click( object sender, System. EventArgs e)
(
this.BindingContext[dsAuthors1, "authors"].Position+=l;
}
Отображение номера текущей записи
Наконец, вы можете создать ShowPosition метод отобразить позицию текущих записей.
Добавьте к форме элемент TextBox, и назовите его txtPosition (рис. 4.34).
Рис. 4.34. Расположение на форме элементов навигации по записям
Примечание
Присвойте свойству Enabled значение False, чтобы пользователи могли видеть номер текущей записи, но не могли изменить его значение.
Создайте в форме процедуру с именем ShowPosition. В этой процедуре получите количество записей в таблице и номер текущей записи от объ- ■
екта BindingContext и отобразите эти значения в текстовом поле. Программный код листинга 4.12 демонстрирует эти действия.
Листинг 4.12
' Visual Basic
Private Sub ShowPosition()
Dim iCnt As Integer
Dim iPos As Integer
iCnt=Me.BindingContext(DsAuthors1, "authors").Count
If iCnt=0 Then
txtPosition.Text="(No records)"
Else
iPos=Me.BindingContext(DsAuthors1, "authors").Position+1
txtPosition.Text=iPos.ToString & " of " & iCnt.ToString
End If
End Sub
// C#
private void ShowPosition()
{
int iCnt;
int iPos;
iCnt=this.BindingContext[dsAuthors1, "authors"].Count;
iPos=this.BindingContext[dsAuthors1, "authors"].Position+1;
if(iCnt==0)
{
txtPosition.Text=" (No records) ";
}
else
{
txtPosition.Text=iPos,ToString() + " of " + lent.ToString() ;
}
}
Добавьте обращение к процедуре ShowPosition в тех фрагментах приложения, где текущая запись могла измениться. Для данного примера это необходимо сделать в следующих местах:
После обращения к методу Fill в обработчике события click кнопки Показать авторов.
После изменения текущей записи в обработчике события click кнопок Предыдущая и Следующая. Например, законченный фрагмент кода для кнопки Предыдущая будет выглядеть следующим образом (листинг 4.13).
Листинг 4.13
' Visual Basic
Private Sub btnPrevious_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrevious.Click
Me.BindingContext(DsAuthors1, "authors").Position-=l
ShowPosition()
End Sub
// c#
private void btnPrevious_Click(object sender, System.EventArgs e)
{
this.BindingContext[dsAuthors1, "authors"].Position-=l;
ShowPosition(); }
Тестирование работы приложения
Вы можете теперь проверить работу данной формы, чтобы удостовериться, что она отображает именно те данные, которые вы запрашиваете при вводе параметра.
Для тестирования работы формы выполните следующие действия.
Нажмите клавишу <F5> для запуска формы.
Когда форма появится на экране, введите код штата Калифорния (СА) в соответствующем текстовом поле, и затем нажмите кнопку Показать авторов.
В текстовых полях будет отображена информация из базы данных о первом авторе, который живет в Калифорнии.
Нажимайте кнопки Предыдущая и Следующая, чтобы убедится в корректности перемещения по записям (рис. 4.35).
Рис. 4.35. Форма во время работы приложения
Введите значение нового кода штата в текстовое поле (например, UT для штата Юта), и затем нажмите кнопку Показать авторов.
Вы увидите, что будет отображен новый автор и изменится количество записей.
Есть некоторые дополнения, которые можно добавить в это приложение для удобства работы пользователя.
Q Не вводить коды штатов в текстовое поле, а выбирать их из раскрывающегося списка. Для этого необходимо добавить к форме еще один адаптер данных с SQL-запросом:
SELECT DISTINCT state FROM authors
Затем сгенерировать второй набор данных и связать его с элементом ListBox.
Q В случае отсутствия возвращаемых записей (в штате нет авторов) выдать соответствующее сообщение, для чего нужно проверить свойство Count объекта BindingContext на нулевое значение. Реализация проверки показана в листинге 4.14.
Листинг 4.14
' Visual Basic
Private Sub btnShow_Click(ByVal sender As System.Object, ByVal eAsф System. EventArgs) Handles btnShow.Click
OleDbDataAdapter1.SelectCommand.Parameters("state").Value =v-'txtState-
Parameter.Text
DsAuthors1.Clear()
OleDbDataAdapter1.Fill(DsAuthors1)
If Me.BindingContext(DsAuthors1, "authors").Count=0 Then
MessageBox.Show("Нет записей для штата" & txtStateParameter.Text) txtStateParameter.Focus()
Else
ShowPosition()
End If
End Sub
//C#
private void btnShow_Click(object sender, System.EventArgs e)
{
OleDbDataAdapter1.SelectCommand.Parameters["state"].Value = txtStateParameter.Text;
dsAuthors1.Clear();
OleDbDataAdapter1.Fill(dsAuthors1);
if (this.BindingContext[dsAuthors1, "authors"].Count==0) {
MessageBox.Show("Нет записей для штата " + txtStateParameter.Text);
txtStateParameter.Focus();
}
else
{
ShowPosition () ;
}
}
Q Отобразить информацию об авторах в сетке данных (DataGrid), а не в текстовых полях, чтобы видеть одновременно несколько записей.
Q Добавить кнопки, которые позволят пользователю добавлять, редактировать и удалять записи об авторах и т. п.
Работа со связанными таблицами в Windows-формах
Во многих приложениях необходимо работать с данными, которые отображают информацию из нескольких связанных таблиц (использовать реляционные отношения между родительской и дочерней таблицами). Например, пользователь имеет запись с информацией о клиенте и хочет видеть заказы, сделанные этим клиентом.
Разъединенная модель набора данных в Visual Studio позволяет работать не только с дискретными таблицами в вашем приложении, но и определять отношения между ними. Тогда можно использовать эти отношения, чтобы перемещаться между связанными записями.
Этот приложение иллюстрирует простой, но законченный пример работы со связанными таблицами в наборе данных. Мы создадим Windows-форму, в которой отображается информация об издательствах (родительская таблица), и об изданных ими книгах (дочерняя таблица).
Пример предполагает прохождение следующих шагов:
Q создание Windows-формы;
Q создание и конфигурирование набора данных, который содержит две таблицы, создание реляционных отношений между таблицами;
Q добавление элементов отображения данных и связывание их с соответствующими объектами хранения данных;
Q формирование программного кода, обеспечивающего заполнение набора данных;
Q тестирование работы формы.
Создание проекта и Windows-формы
Для создания проекта и Windows-формы выполните следующие действия.
Из меню File выберите подменю New и затем пункт Project.
Появится диалоговое окно New Project.
В дереве Project Types выберите тип проекта: Visual Basic Projects или Visual C# Projects, а в области Templates укажите вид приложения - Windows Application.
Если у вас открыто другое приложение, то установите переключатель Close Solution в окне New Project.
Задайте проекту новое имя, которое будет уникальным и отражать суть разрабатываемого приложения. Например, в данном случае назовем этот проект WinRelation. После задания имени проекта нажмите кнопку ОК.
На следующем шаге добавьте к форме и сконфигурируйте набор данных. В примере данного раздела набор данных будет содержать две таблицы: таблицу издательств (Publishers) и таблицу наименований книг (Titles). Обе таблицы присутствуют в базе данных Pubs, поставляемой вместе с SQL Server. Таблицы имеют реляционные отношения. Поле, идентифицирующее издательство (pub_id), является первичным ключом таблицы Publishers и внешним ключом к таблице Titles.
Конфигурирование DataConnection
и DataAdapter
Работа над созданием соединения и адаптера данных будет происходить следующим образом. Сначала необходимо сформировать адаптеры данных, которые содержат SQL-запросы, заполняющие наборы данных информацией на этапе работы приложения. Как часть этого процесса, автоматически будет создано соединение с базой данных. Для конфигурации адаптеров данных будет использоваться соответствующий мастер. Для данного приложения нужно будет создать два адаптера данных, один, чтобы заполнять данными таблицу Publishers, другой для получения данных из таблицы Titles.
Для создания соединения и адаптеров данных выполните следующие действия.
Из вкладки Data окна Toolbox перенесите на форму объект
OleDbDataAdapter.
Примечание
Вы можете также использовать объект SqlDataAdapter, который оптимизирован для работы SQL Server версии 7.0 и выше.
Будет запушен мастер Data Adapter Configuration Wizard, который поможет создать объекты DataConnection И DataAdapter.
В мастере выполните следующие действия:
На второй странице создайте или выберите соединение, указывающее на базу данных Pubs вашего SQL-сервера;
На третьей странице укажите, что вы хотите использовать именно SQL-запрос для обращения к базе данных;
На четвертой странице создайте следующий SQL-запрос (рис. 4.36):
SELECT pub_id, pub_name FROM publishers
Примечание
Для помощи формирования SQL-запроса нажмите Query Builder, чтобы запустить мастер формирования запросов Query Builder.
Щелкните кнопку Finish для завершения работы мастера.
Мастер создаст соединение с базой данных (объект OleDbConnection1) и адаптер данных (объект OleDbDataAdapter1), который будет содержать SQL-запрос для получения записей из таблицы Publishers.
Рис. 4.36. Формирование запроса в окне Query Builder
Перетащите на форму второй объект OleDbDataAdapter.
Снова будет запущен мастер Data Adapter Configuration Wizard.
В окне мастера выполните следующие действия.
Навторойстраницевыберитетожесамоесоединение, котороевы
использовали или создали для работы с таблицей Publishers.
Натретьейстраницеукажите,чтовыхотитеиспользоватьименно
SQL-запрос для обращения к базе данных;
На четвертой странице создайте следующий SQL-запрос для обраще
ния К таблице Titles.
SELECT title_id, title, pub_id, price FROM titles
Примечание
В предложение SELECT необходимо обязательно включить столбец pub_id.
Мастер добавит на форму еще один адаптер данных OleDbDataAdapter2.
На следующем этапе необходимо будет сгенерировать набор данных.
Создание набора данных DataSet
После того как созданы соединение с базой данных и адаптеры данных, можно создать набор данных. В Visual Studio можно сгенерировать набор данных автоматически, основываясь на SQL-запросах, которые были созданы в адаптерах данных. Набор данных — это экземпляр класса DataSet, создаваемого на основе XML-схемы (xsd-файла), в которой описываются элементы этого класса (таблицы, колонки и ограничения).
Для создания DataSet нужно выполнить следующие шаги.
В меню Data выберите пункт Generate DataSet.
Примечание
Если меню Data не доступно, щелкните мышью в любом месте формы. Форма должна иметь фокус, чтобы это меню стало доступным.
Появится диалоговое окно Generate Dataset.
Установите переключатель New и задайте набору данных новое имя - dsPublishersTitles.
Удостоверьтесь, что в списке таблиц, которые будут добавлены к набору данных (Choose which table(s) to add to the dataset), присутствуют две таблицы: Publishers и Titles (рис. 4.37), и рядом с ними стоят флажки.
Рис. 4.37. Включение в набор данных двух таблиц
Установите флажок Add this dataset to the designer и нажмите кнопку ОК.
В результате Visual Studio сгенерирует типизированный класс набора данных (DsPubliahersTitles) и схему, которая определяет структуру этого набора данных. Эта схема (файл DsPublishersTitles.xsd) появится в окне Solution Explorer.
Наконец, Visual Studio добавит к форме экземпляр нового класса набора данных (DsPublishersTitles1 или dsPublishersTitles1, в зависимости от того, какой язык программирования вы используете).
Создание реляционных связей между таблицами набора данных
В нашем наборе данных содержится две таблицы, которые в базе данных имеют отношения "один ко многим". Однако набор данных — это пассивный контейнер, который не может использовать те связи между таблицами, которые заданы в базе данных. В объекте DataSet реляционные отношения между таблицами нужно задавать явно, через специально предназначенный для этих целей объект.
Примечание
Обратите внимание, что в данном примере в наборе данных таблицы Publisher и Titles физически не объединяются между собой. Через два адаптера данных можно работать с этими двумя таблицами совершенно независимо (добавлять, удалять, модифицировать записи, перемещаться по записям и пр.). В тоже время имеется возможность установить реляционные отношения и рассматривать их как взаимосвязанный набор данных.
Для создания реляционных отношений между таблицами нужно выполнить следующие действия.
В Solution Explorer дважды щелкните левой кнопкой мыши на схеме набора данных, который вы только что создали (элемент DsPublishersTitles.xsd).
В окне XML Designer откроется вкладка Schema, в которой будут отражены две таблицы набора данных (рис. 4.38).
ИзвкладкиXMLSchemaокнаToolboxперетащитемышьюобъект
Relation на таблицу Titles (дочерняя таблица).
Откроется диалоговое окно Edit Relation со значениями параметров связи этих двух таблиц, установленными по умолчанию (рис. 4.39).
Start Page | Forml.vb [Design]* dsPublishersTitles.xsd |
^(pubiisbers^*^^(pubiisbers^*^I ?E pubjdstringE pub .namestringI ?E pubjdstringE pub .namestring
^(pubiisbers^*^
^(pubiisbers^*^
I ?E pubjdstring
E pub .namestring
I ?E pubjdstring
E pub .namestring
Рис. 4.38. Несвязанные таблицы в окне XML Designer
Рис. 4.39. Диалоговое окно Edit RelationРис. 4.39. Диалоговое окно Edit Relation
Рис. 4.39. Диалоговое окно Edit Relation
Рис. 4.39. Диалоговое окно Edit Relation
Подтвердите, что вы согласны со значениями, установленными по умолчанию в диалоговом окне Edit Relation (табл. 4.4).
Таблица 4.4. Значения параметров для установления реляционных связей
Параметр
Значение параметра (Value)
Name (имя)
Parent element (Родительский элемент)
Child element (Дочерний элемент)
Key Fields (Ключевое поле)
Foreign Key Fields (Поля внешнего ключа)
Create foreign key constraint only (Ограничение внешнего ключа)
Publisherstitles Publishers
Titles pub_id pub_id
не установлен
Остальные значения, не указанные в таблице 4.4, не важны для выполняемого примера.
Щелкните мышью кнопку ОК для закрытия диалогового окна Edit Relation.
В окне XML Designer появится изображение реляционного отношения между двумя таблицами (рис. 4.40).
I :.■ .’ ,■»- F?rirl -I, [L j ]• dsPublishersTitles.Ksd’|I :.■ .’ ,■»- F?rirl -I, [L j ]• dsPublishersTitles.Ksd’|
I :.■ .’ ,■»- F?rirl -I, [L j ]• dsPublishersTitles.Ksd’|
I :.■ .’ ,■»- F?rirl -I, [L j ]• dsPublishersTitles.Ksd’|
Рис. 4.40. Связанные таблицы в окне XML Designer
Если возникнет потребность изменить параметры связи между таблицами, то нужно щелкнуть правой кнопкой мыши на значке отношения и выбрать пункт Edit Relation в контекстом меню,
Сохраните схему и закройте окно XML Designer.
На этом этапе все готового для того, чтобы добавить к форме элементы отображения данных.
Добавление элементов отображения данных
В этом разделе мы добавим на форму несколько элементов управления: ListBox для отображения списка издательств и DataGrid для отображения
наименований книг выбранного издательства. Также добавим элементы Labels для описания элементов формы.
Отображение издательств в элементе ListBox
Элемент ListBox будет отображать названия издательств (содержание таблицы Publishers). Этот элемент позволяет отобразить несколько записей (список издательств).
Вернемся к нашей форме (с именем по умолчанию Form1), которая была открыта при создании проекта. Если вы еще находитесь в окне XML Designer, то переключитесь на вкладку дизайнера формы (выбрав соответствующую позицию табуляции в верхней части текущего окна).
Из вкладки Windows Forms окна Toolbox, перетащите на форму элемент ListBox.
Нажмите клавишу <F4> для перехода в окно Properties.
В свойстве DataSource выберите набор данных DsPublishersTitles1 или dsPubiishersTitles1 (в зависимости от языка программирования VB или С#) в качестве источника данных.
В свойстве DispiayMember активизируйте раскрывающийся список. Из списка выберите таблицу Publishers, разверните узел Publishers и затем выберите поле, содержащее наименование издательства — pub_name.
Когда эта процедура будет закончена, свойству DisplayMember будет присвоено значение — publishers.pub_name (рис. 4.41).
Рис. 4.41. Связывание элемента ListBox с полем таблицы набора данных
Таким образом вы связали элемент ListBox с полем наименования издательства pub_name таблицы издательств publishers.
Теперь добавим на форму элемент Label и свойству Text этого элемента присвоим значение наименование издательства (рис. 4.42).
Рис. 4.42. Расположение на форме элементов отображения данных
Отображение наименований книг в элементе DataGrid
Каждое издательство может иметь список изданных книг. Каждая книга имеет несколько атрибутов: наименование, автора, год издания и пр. Чтобы отобразить информацию о книгах нужно использовать элемент управления, который может отображать не только несколько записей, но и несколько столбцов. Для этих целей подходит элемент управления DataGrid. Для этого примера мы сконфигурируем DataGrid таким образом, чтобы он показывал только наименования книг, изданных выбранным издательством.
Свяжем DataGrid не С таблицей Titles, а С объектом publisherstitles, созданным ранее, который устанавливает реляционные отношения между таблицами Publishers и Titles. Объект publisherstitles представляет собой свойство таблицы Publishers. Во время работы приложения каждый раз, когда пользователь будет перемещаться к новому издательству (выбирая его в списке), будет срабатывать соответствующий метод объекта связи данных. При этом из дочерней таблицы будут отбираться только те записи, которые относятся к выбранной записи родительской таблицы.
Для добавления и связывания с данными объекта DataGrid выполните следующие действия.
Из вкладки Windows Forms окна Toolbox, перетащите на форму элемент DataGrid.
В свойстве DataSource выберите набор данных DsPublishersTitles1 или dsPublishersTitles1 (в зависимости от языка программирования VB или С#) в качестве источника данных.
Задайте свойству DataMember значение publishers.publisherstitles. Наберите это значение с помощью клавиатуры или выберите из выпадающего списка (рис. 4.43).
Рис. 4.43. Связывание элемента DataGrid с объектом реляционных отношений
Установка этих двух свойств связывает элемент DataGrid с объектом реляционных отношений между таблицами. При этом в сетке данных будут всегда отображаться дочерние записи с информацией о книгах издательства, установленного в родительской таблице.
Изменитеразмерысеткиданныхтак,чтобыможнобыловидетьне
сколько строк и столбцов (рис. 4.44).
Рис. 4.44. Расположение на форме элемента управления DataGrid
Заполнение набора данных
Хотя элемент отображения данных на форме связан с набором данных, он сам не заполняется данными автоматически. Этот процесс нужно активизировать из программного кода.
Для заполнения набора данных необходимо выполнить следующие действия.
Дважды щелкните мышью на форме, чтобы создать обработчик события загрузки формы Load.
В обработчике события загрузки формы очистите набор данных, который вы создали ранее (DsPublishersTities1), и затем вызовите метод. Fill для двух адаптеров данных, указав им в качестве параметра этот же набор данных. В результате этого будут заполнены данными обе таблицы (Publishers И Titles).
Ниже приведен соответствующий программный код (листинг 4.15).
I — j
Листинг 4.15
' Visual Basic
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e AsS>
System.EventArgs) Handles MyBase.Load
DsPublishersTitles1.Clear()
OleDbDataAdapter!.Fill(DsPublishersTitles1)
OleDbDataAdapter.Fill(DsPublishersTitles1)
End Sub
// C#
private void Form1_Load(object sender, System.EventArgs e)
{
dsPublishersTitles1.Clear();
oleDbDataAdapter1.Fill(dsPublishersTitles1);
oleDbDataAdapter2.Fill(dsPublishersTitles1);
}
Тестирование приложения
Теперь можно проверить работу форму, чтобы удостовериться в корректности ее работы.
Для проверки работы приложения выполните следующие шаги.
Нажмите клавишу <F5> для запуска приложения.
Когда форма будет отображена:
« проверьте, что в элементе управление ListBox отображаются наименования издательств;
• выбирая различные издательства, убедитесь, что в сетке данных отображаются книги только выбранных издательств (рис. 4.45).
/New Moon Books/New Moon Books■jrmef 6 Hailey■jrmef 6 HaileyudejdMC2222MC3021MC3026PS1372udejdMC2222MC3021MC3026PS1372pub_id 0877 0877 0877 0877pub_id 0877 0877 0877 0877titleSrkron Valey The Gourmet The Psycholo Computer PhtitleSrkron Valey The Gourmet The Psycholo Computer PhРис. 4.45. Отображение результатов работы приложенияРис. 4.45. Отображение результатов работы приложенияНаименование издательства
/New Moon Books
/New Moon Books
■jrmef 6 Hailey
■jrmef 6 Hailey
udejd
MC2222
MC3021
MC3026
PS1372
udejd
MC2222
MC3021
MC3026
PS1372
pub_id 0877 0877 0877 0877
pub_id 0877 0877 0877 0877
title
Srkron Valey The Gourmet The Psycholo Computer Ph
title
Srkron Valey The Gourmet The Psycholo Computer Ph
Рис. 4.45. Отображение результатов работы приложения
Рис. 4.45. Отображение результатов работы приложения
Algodata InfosystemsI Five Lakes Publishing
Итак, в примере этого раздела были решены две задачи: создан набор данных с двумя таблицами и отношениями между ними и создана Windows- форма, которая отобразила связанные данные. Можно несколько усовершенствовать этот пример:
Q изменить настройки и дизайн элемента DataGrid для улучшения его внешнего вида;
Q создать реляционные отношения динамически, в программном коде (в примере реляционные отношения создавались на этапе разработки приложения в XML Designer).
Представление связанных таблиц в элементе управления DataGrid
В предыдущем примере мы рассмотрели возможность работы со связанными таблицами базы данных с представлением их в различных визуальных элементах управления. Однако эту задачу можно решить с использованием единственного элемента управления, причем уровень иерархии связанных таблиц особой роли не играет. В Visual Studio для этих целей можно использовать элемент управления DataGrid, который имеет встроенный механизм отображения информации из таблиц, имеющих реляционные связи. В примере этого раздела мы рассмотрим три связанные между собой таблицы: Заказчики, заказы и детали заказа. Для выполнения этого примера воспользуемся базой данных Northwind, которая поставляется вместе с SQL Server, и где есть соответствующие таблицы: Customers, Orders И Order Details.
Модель набора данных в Visual Studio позволяет работать не только с отдельными таблицами в вашем приложении, но и определять отношения
между ними. Тогда можно использовать эти отношения, чтобы перемещаться между связанными записями.
Пример предполагает выполнение следующих этапов:
Q создание Windows-формы;
Q создание соединения с базой данных;
Q создание и конфигурирование адаптеров данных, которые обеспечивают взаимодействие с тремя таблицами базы данных;
Q добавление элемента управления DataGrid и кнопки (для загрузки и отображения данных);
Q формирование программного кода, обеспечивающего заполнение набора данных, формирования реляционных связей и связывание набора данных СDataGrid;
Q тестирование работы приложения.
Создание проекта и Windows-формы
Для создания Windows-формы выполните следующие действия.
Из меню File выберите подменю New, а затем пункт Project.
Появиться диалоговое окно New Project.
В дереве ProjectTypesвыберитетиппроекта— VisualBasicProjectsили
Visual C# Projects, и в области Templates укажите вид приложения — Windows Application.
Если у вас открыто другое приложение, то установите переключатель Close Solution в окне New Project.
Задайте проекту новое имя, которое будет уникальным и отражать суть разрабатываемого приложения. Например, в данном случае назовем этот проект win_Relation. После задания имени проекта нажмите кнопку ОК.
В примере этого раздела мы не будем создавать набор данных на этапе проектирования, Он будет создан динамически в ходе выполнения приложения. Однако сами таблицы должны быть доступны в приложении, для чего мы создадим три адаптера данных и один объект подключения к базе данных. Так же динамически будут созданы и реляционные связи между таблицами.
Конфигурирование объектов
DataConnection и DataAdapter
Сначала необходимо создать адаптеры данных, которые содержат SQL- запросы, заполняющие наборы данных информацией на этапе работы при-
ложения. Как часть этого процесса будет автоматически создано соединение с базой данных. Для конфигурации адаптеров данных будет использоваться соответствующий мастер. Для данного приложения нужно будет создать три адаптера данных для заполнения данными таблиц Customers, Orders и Order Details.
На вкладке Data окна Toolbox, дважды щелкните на объекте SqlDataAdapter.
Будет запущен мастер Data Adapter Configuration Wizard, который поможет создать объекты DataConnection И DataAdapter.
В мастере выполните следующие действия:
На второй странице создайте или выберите соединение, указывающее на базу данных Northwind вашего SQL-сервера.
На третьей странице укажите, что вы хотите использовать SQL- запрос для обращения к базе данных - установите Use SQL statements.
На четвертой странице создайте следующий SQL-запрос:
SELECT Customers.* FROM Customers
Примечание
Для помощи формирования SQL-запроса нажмите Query Builder, чтобы запустить мастер формирования запросов Query Builder.
Щелкните кнопку Finish для завершения работы мастера.
Мастер создаст соединение с базой данных (объект SqlConnectionl) и адаптер данных (объект SqiDataAdapter), который будет содержать SQL-запрос для получения записей из таблицы Customers.
Перетащите на форму второй объект SqlDataAdapter.
Снова будет запущен мастер Data Adapter Configuration Wizard.
В мастере выполните следующие действия:
На второй странице выберите то же самое соединение, которое вы использовали или создали для работы с таблицей customers.
На третьей странице укажите, что вы хотите использовать SQL- запрос для обращения к базе данных - установите переключатель Use SQL statements.
На четвертой странице создайте SQL-запрос, чтобы обращаться к
таблице orders:
SELECT Orders.* FROM Orders
Мастер добавит на форму еще один адаптер данных SqlDataAdapter2.
Перетащите на форму третий объект SqlDataAdapter. Снова будет запущен мастер Data Adapter Configuration Wizard.
Навторойстраницевыберитетожесамоесоединение, котороевы
использовали или создали для работы с таблицей Customers.
Натретьейстраницеукажите,чтовыхотитеиспользоватьSQL-
запрос для обращения к базе данных - установите переключатель Use SQL statements.
На четвертой странице создайте следующий SQL-запрос, чтобы обращаться К таблице Order Details.
SELECT [Order Details].* FROM [Order Details]
Мастер добавит на форму еще один адаптер данных SqlDataAdapter3.
На следующем этапе необходимо сгенерировать набор данных.
Добавление элементов управления
В этом разделе примера мы добавим на форму два элемента управления. Это будут DataGrid для отображения информации и Button для получения записей из базы данных.
На вкладке Windows Form окна Toolbox, выделите элемент управления DataGrid и перенесите его на форму.
Аналогично перенесите элемент управления Button. Войдите в окно Properties этого элемента и в поле свойства Text наберите значение Загрузить.
Расположите элементы управления на форме как показано на рис. 4.46. На этом работа с элементами управлении будет закончена. Все остальные действия будут выполнены в программном коде.
Рис. 4.46. Расположение элементов управления на форме
Заполнение набора данных и создание реляционных связей
В нашем наборе данных будет содержаться три таблицы, которые в базе данных имеют отношения "один ко многим". Однако, набор данных — это пассивный контейнер, который не может использовать те связи между таблицами, которые заданы в базе данных. В объекте DataSet реляционные отношения между таблицами нужно будет задавать явно, через его свойство Relations.
Для начала нужно будет создать экземпляр класса DataSet, открыть соединение и заполнить набор данных. Причем в объекте DataSet будет содержаться три самостоятельных таблицы: Customers, Orders и Order Details, Несмотря на то, что таблицы на уровне базы данных имеют реляционные связи, в DataSet этих связей не будет, все три таблицы будут совершенно независимы друг от друга. Реляционные связи нужно создать самим, воспользовавшись свойством Relations объекта DataSet. В нашем примере главной родительской таблицей является таблица с информацией о заказчиках — Customers. Для нее дочерней таблицей является таблица с информацией о заказах— Orders. Эти две таблицы имеют связующее ключевое поле CustomerID. В свою очередь таблица Orders является родительской таблицей по отношению к таблице с данными о деталях заказов— order Details. Эти две таблицы имеют связуюшее ключевое поле OrderID. Схема связей между таблицами приведена на рис. 4.47.
Рис. 4.47. Схема связей между таблицами Customers, Orders и Order Details
Элемент отображения данных на форме DataGrid не связан с набором данных и он не заполняется данными автоматически. Эти процессы нужно активизировать с помощью команд программного кода.
Дважды щелкните мышью на кнопке формы, чтобы создать обработчик события нажатия кнопки Button1 Click.
В обработчике события выполним следующие действия:
создадим экземпляр класса DataSet (набор данных ds);
откроем соединение;
заполним данными объект DataSet (набор данных ds);
закроем соединение;
создадим реляционную связь между таблицами Customers, orders;
создадим реляционную связь между таблицами orders и order
Details;
укажем объекту DataGrid в качестве источника данных набор данных ds;
зададим объекту DataGrid отобразить таблицу Customers.
Ниже приведен соответствующий программный код (листинг 4.16).
Листинг 4.16
' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, ByVal eAs^ Sys- tem.EventArgs) Handles Button1.Click
Dim ds As New DataSet()
SqlConnection1.Open()
SqlDataAdapter1.Fill(ds, "Customers")
SqlDataAdapter2.Fill(ds, "Orders")
SqlDataAdapter3. Fill(ds, "OrderDetails")
SqlConnection1.Close()
ds.Relations.Add("Заказы",ds.Tables("customers").ъ
Columns("CustomerID"),ь
ds.Tables("Orders").Columns("CustomerID"))
ds.Relations.Add("Детали заказа", ъ
ds.Tables ("Orders").Columns("OrderID"),^
ds.Tables("OrderDetails").Columns("OrderID"))
DataGrid1().DataSource=ds
DataGrid1().DataMember="Customers"
End Sub
// C#
private void Button1_Click (object sender, System.EventArgs e)
{
DataSet ds;
SqlConnection1.Open();
SqlDataAdapter1.Fill(ds, "Customers");
SqlDataAdapter2.Fill(ds, "Orders");
SqlDataAdapter3. Fill (ds, "OrderDetails");
SqlConnection1.Close();
ds.Relations.Add("Заказы", ъ
ds.Tables("customers").Columns("CustomerID"),ъ
ds.Tables("Orders").Columns("CustomerID"));
ds.Relations.Add("Детали заказа",^
ds.Tables("Orders").Columns("OrderID"),ъ
ds.Tables("OrderDetails").Columns("OrderID"));
DataGrid1().0ataSource=ds;
DataGrid1().DataMember="Customers";
}
Тестирование приложения
Теперь можно выполнить тестирование приложения, чтобы удостовериться в корректности ее работы и возможности отображения в DataGrid содержимого связанных таблиц.
Для проверки работы приложения выполните следующие действия.
Нажмите клавишу <F5> для запуска приложения.
Когда форма будет отображена на экране, вы увидите пустой элемент DataGrid. Нажмите кнопку Загрузить, после этого элемент управления DataGrid заполнится записями из таблицы customers, содержащей сведения о заказчиках (рис. 4.48).
Рис. 4.48. Отображение в DataGrid информации из родительской таблицы Customers
Наименования колонок объекта DataGrid получат значения от наименований соответствующих полей базы данных. В первой колонке будет располагаться указатель текущей записи и знак (+), позволяющий получить доступ к записям дочерних таблиц. Щелкните мышью на значке (+) в любой строке, в DataGrid появится дополнительная строка с ссылкой на содержимое дочерней таблицы (в нашем случае появиться ссылка с надписью Заказы (рис. 4.49).
Рис. 4.49. Отображение в DataGrid ссылки на дочернюю таблицу с информацией о заказах
Как видно из рис. 4.49, мы получили возможность просмотреть все заказы клиента с именем ANTON. Нажмите на ссылку Заказы, после этого запись с информацией о заказчике ANTON будет перенесена в верхнюю часть DataGrid, а в самом элементе управления появятся записи из дочерней таблицы Orders (рис. 4.50). В нашем случае будут отображены сведения о заказах, сделанных заказчиком ANTON.
Рис. 4.50. Отображение в DataGrid информации из родительской таблицы Customers и дочерней таблицы Orders
В левой крайней колонке снова будет виден значок с надписью (+), нажав на него, мы увидим еще одну строку со ссылкой Детали заказа (рис. 4.51).
1 Cuelomerr CuetomedO ANTON CnmpanyName. Antonio Moreno Iaweiia i CortactName. AntoreoMof№0 CT1 Cuelomerr CuetomedO ANTON CnmpanyName. Antonio Moreno Iaweiia i CortactName. AntoreoMof№0 CTOnfedD, CustomerlDEn^iy/ee#DOrderDafeRequiredD^le; ShppedDaleShpV»FfegNт a losesANTON327/11/9625Z12/9S02/12^6222a 10507ANTON715/04/9713/05/9722/04/9714745a 10535ANTON4134)5/9710/06/9721/05^711564ф 10573ANTON713/06/9717/07/9720/06/97384.84Ч Детали МММ |a 10677ANTON1224)9/9720Л0/9726/09/9734 03a 10682ANTON3254)9/9723/10/3701/10/972ЗЫЗVllfH АППJ™in тпзнпcn enOnfedD, CustomerlDEn^iy/ee#DOrderDafeRequiredD^le; ShppedDaleShpV»FfegNт a losesANTON327/11/9625Z12/9S02/12^6222a 10507ANTON715/04/9713/05/9722/04/9714745a 10535ANTON4134)5/9710/06/9721/05^711564ф 10573ANTON713/06/9717/07/9720/06/97384.84Ч Детали МММ |a 10677ANTON1224)9/9720Л0/9726/09/9734 03a 10682ANTON3254)9/9723/10/3701/10/972ЗЫЗVllfH АППJ™in тпзнпcn enЗагрузитьЗагрузитьJJ
1 Cuelomerr CuetomedO ANTON CnmpanyName. Antonio Moreno Iaweiia i CortactName. AntoreoMof№0 CT
1 Cuelomerr CuetomedO ANTON CnmpanyName. Antonio Moreno Iaweiia i CortactName. AntoreoMof№0 CT
OnfedD
, CustomerlD
En^iy/ee#D
OrderDafe
RequiredD^le; ShppedDale
ShpV»
FfegN
т a loses
ANTON
3
27/11/96
25Z12/9S
02/12^6
2
22
a 10507
ANTON
7
15/04/97
13/05/97
22/04/97
1
4745
a 10535
ANTON
4
134)5/97
10/06/97
21/05^7
1
1564
ф 10573
ANTON
7
13/06/97
17/07/97
20/06/97
3
84.84
Ч Детали МММ |
a 10677
ANTON
1
224)9/97
20Л0/97
26/09/97
3
4 03
a 10682
ANTON
3
254)9/97
23/10/37
01/10/97
2
ЗЫЗ
VllfH АПП
J™
in тпзнп
cn en
OnfedD
, CustomerlD
En^iy/ee#D
OrderDafe
RequiredD^le; ShppedDale
ShpV»
FfegN
т a loses
ANTON
3
27/11/96
25Z12/9S
02/12^6
2
22
a 10507
ANTON
7
15/04/97
13/05/97
22/04/97
1
4745
a 10535
ANTON
4
134)5/97
10/06/97
21/05^7
1
1564
ф 10573
ANTON
7
13/06/97
17/07/97
20/06/97
3
84.84
Ч Детали МММ |
a 10677
ANTON
1
224)9/97
20Л0/97
26/09/97
3
4 03
a 10682
ANTON
3
254)9/97
23/10/37
01/10/97
2
ЗЫЗ
VllfH АПП
J™
in тпзнп
cn en
Загрузить
Загрузить
J
J
Рис. 4.51. Отображение в DataGrid ссылки на дочернюю таблицус информацией о деталях заказов
То есть теперь, нажав на ссылку Детали заказа мы сможем получить содержимое любого заказа. При этом в верхней части DataGrid появится еще одна строка с указанием номера отображенного заказа (рис. 4.52).
Рис. 4.52. Отображение в DataGrid информации из родительских таблиц Customers, Orders и, дочерней таблицы Order DetailsРис. 4.52. Отображение в DataGrid информации из родительских таблиц Customers, Orders и, дочерней таблицы Order Details
Рис. 4.52. Отображение в DataGrid информации из родительских таблиц Customers, Orders и, дочерней таблицы Order Details
Рис. 4.52. Отображение в DataGrid информации из родительских таблиц Customers, Orders и, дочерней таблицы Order Details
Знак (+) в левой колонке исчез — это говорит о том, что у данной таблицы нет дочерних таблиц, и она в иерархии реляционных связей является по-
Справа и слева верхней части DataGrid появились две кнопки, которые позволяют просмотреть колонки родительских таблиц, не поместившиеся на
экран. В правом верхнем углу имеется стрелка, нажав на которую можно закрыть дочернюю таблицу и подняться на один уровень вверх (вернуть на экран содержимое родительской таблицы). Кроме того, данный DataGrid позволяет выполнить сортировку любой таблицы на любом уровне иерархии по любой колонке. Для этого достаточно щелкнуть мышью на заголовке колонки. После этого в заголовке колонки появится небольшая стрелка, указывающая порядок сортировки (по возрастанию или убыванию). При повторном щелчке на той же колонке порядок сортировки меняется на обратный.
Этот пример достаточно убедительно демонстрирует преимущество Visual Studio .NET. Нам удалось реализовать возможность отобразить в одном визуальном элементе три взаимосвязанные таблицы с возможностью их сортировки по любому признаку. При этом было написано всего 10 строк программного кода.
Добавление, удаление и обновление записей в Windows-формах
В заключение этой главы рассмотрим взаимосвязанные процедуры добавления, удаления и обновления записей. Это наиболее частые действия, которые выполняют пользователи при работе с базами данных. В качестве элемента отображения данных будет использоваться элемент управления DataGrid. Этот пример иллюстрирует Windows-форму, которая отображает в сетке содержимое таблицы базы данных. С помощью кнопок пользователь будет иметь возможность добавлять или удалять записи из таблицы базы данных, а элемент DataGrid позволит редактировать данные в любой (в том числе и добавленной) строке.
Для того чтобы реализовать пример этого раздела, нужно иметь доступ к базе данных Northwind, которая автоматически устанавливается при инсталляции MS SQL Server. Вам предстоит выполнить следующие шаги:
Q создать Windows-проект и, соответственно, Windows-фому;
Q создать соединение с базой данных connection;
Q создать объект доступа к базе данных DataAdapter;
Q создать и сконфигурировать набор данных DataSet;
Q добавить на форму элемент управления DataGrid и связать его с набором данных DataSet;
Q добавить на форму три элемента управления Button;
Q добавить программный код для заполнения набора данных DataSet;
Q добавить программный код, обеспечивающий функциональность кнопок Добавить, Удалить, Обновить.
Создание проекта и формы
Для создания проекта и формы сделайте следующие шаги.
Выберите опцию меню File, укажите New, и затем выберите Project.
В левой части открывшегося окна выберите Visual Basic Projects или Visual C# Projects, и затем в правой — Windows Application.
Если у вас уже открыто какое-либо другое приложение, установите переключатель Close Solution в окне New Project.
Назовите проект уникальным именем, которое будет ассоциироваться у вас с выполняемыми действиями. Например, данный проект можно на- зватьWinAddDel.
Когда вы назначили имя проекта, щелкните кнопку ОК.
Visual Studio создаст новый проект и отобразит Windows-форму в окне дизайнера.
Создание и конфигурирование элементов доступа к данным
Чтобы получить данные на компьютер пользователя необходимо создать соединение с базой данных и элемент DataAdapter, который содержит SQL- запросы, и используется для заполнения данными элемента DataSet. Для создания соединения с базой данных, адаптера данных и элемента DataSet выполните следующие действия.
Перейдите в окно Server Explorer.
Примечание
По умолчанию окно Server Explorer расположено в левой части экрана дизайнера в виде вкладки. Если эта вкладка не видна, то в меню View выберите пункт Server Explorer.
Если вы уже ранее создавали соединение с базой данных Northwind, то в окне Server Explorer появится элемент в узле Data Connections, обеспечивающий доступ к базе данных Northwind.
В Server Explorer разверните узел с таблицами Tables базы данных Northwind.
Найдите Таблицу Categories, выделите поля CategoryID, CategoryName, Description и перетащите их на вкладку дизайнера формы.
После этого на панели дизайнера появятся два объекта: SqlConnectionl и SqlDataAdapter1. Эти компоненты сконфигурированы для того, чтобы обеспечить передачу информации между набором данных (он будет создан чуть Позже) И Таблицей Categories базы данных Northwind.
Щелкните правой кнопкой мыши на объекте SqlDataAdapter1 и в появившемся контекстном меню выберите Generate Dataset. После этого откроется диалоговое окно Generate Dataset, в котором по умолчанию будет установлен переключатель New и указана ссылка на таблицу Categories. Нажмите кнопку ОК.
После этого на панели дизайнера появятся объект DataSetll. На этом этапе мы создали все объекты, необходимые для связи приложения с базой данных.
Далее мы добавим на форму традиционный элемент управления — DataGrid, который обычно используется для отображения всех записей, содержащихся в наборе данных. Для добавления элемента управления DataGrid на форму выполните следующие действия.
Щелкните левой кнопкой мыши в любом свободном месте формы Form1, чтобы форма стала активной и получила фокус.
ИзвкладкиWindowsFormsокнаToolboxперетащитеэлементDataGrid
на форму.
Нажмите клавишу <F4> для перехода в окно свойств элемента DataGrid.
В свойстве DataSource выберите DataSetll в качестве источника данных (не выбирайте DataSet11.Categories).
В свойстве DataMember выберите Categories.
Установив эти два свойства, вы фактически связали DataGrid с таблицей Categories из набора данных DataSetll. После этих действий в сетке данных DataGrid появились столбцы с заголовками полей выводимых данных.
ИзвкладкиWindowsFormsокнаToolbox,перетащитенаформутри
элемента Button и свойству Text этих элементов присвойте следующие значения: Button1 — Добавить, Button2 — Удалить, Button3 — Обновить.
Перерисуйте элемент управления DataGrid так, чтобы в сетке данных было видно несколько колонок и строк, и расположите элементы на форме в соответствии с рис. 4.53.
Рис. 4.53. Расположение элементов на форме
Формирование программного кода
Теперь перейдем к формированию программного кода. Начнем с загрузки формы. В обработчике события загрузки формы необходимо заполнить информацией набор данных DataSet (листинг 4.17).
Листинг 4.17
' Visual Basic
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As "v System. EventArgs) Handles MyBase.Load
SqlDataAdapter1.Fill(DataSet11)
End Sub
//C#
private void Form1_Load(object sender, System.EventArgs e)
{
SqlDataAdapter1.Fill(dataSet11);
}
Набор данных заполняется путем вызова метода Fill адаптера данных.
На следующих шагах последовательно сформируем программный код для обработки событий нажатия кнопок.
Для обеспечения возможности добавления записи будет использована ко- мандаSqlInsertCommand1адаптера данных. Для получения доступа к тексту этой команды выделите мышью объект SqlDataAdapter1, войдите в окно его свойств и найдите строку InsertCommand. Раскройте ее узел, щелкнув на значке (+), найдите свойствоCommandTextи нажмите кнопку в этой строке.
Откроется окно построителя запросов Query Builder с текстом соответствующего SQL-запроса (рис. 4.54).
INSERT INTO Categories
(CategoryName, Description)
VALLIES (©CategoryName, ©Description);
SELECT CategorylD, CategoryName, Description
FROM Categories
WHERE (CategorylD = ©©IDENTITY)
(v Regenerate parameters colectlon OK pr Cancel
Рис, 4,54. Формирование запроса в окне Query Builder
Из текста этого запроса видно, что для того чтобы добавить запись в таблицу categories, необходимо задать значения двум параметрам этого SQL запроса: @CategoryName и @Description. Это обстоятельство нужно учесть при формировании программного кода. Программный код обработки события нажатия кнопки Добавить приведен в листинге 4.18.
Листинг 4.18
' Visual Basic
Private Sub Button1_Click{ByVal sender As System.Object, ByVal e As Sys- tem.EventArgs) Handles Button1.Click
'Добавление записи
SqlDataAdapter1.InsertCoramand.Parameters( "@CategoryName").Value=""
SqlDataAdapter1.InsertCommand.Parameters("@Description").Value=""
SqlConnection1.Open()
SqlDataAdapter1.InsertCommand.ExecuteNonQuery()
SqlConnection1.Close()
DataSet11.Clear()
SqlDataAdapter1.Fill(DataSet11)
End Sub
//C#
private void button1_Click(object sender, System.EventArgs e)
{
//Добавление записи
SqlDataAdapter1.InsertCoiranand.Parameters["@CategoryName"].Value="";
SqlDataAdapter1.InsertCommand.Parameters["@Description"].Value="";
SqlConnection1,Open();
SqlDataAdapter1.InsertCommand.ExecuteNonQuery();
SqlConnection1.Close();
dataSet11.Clear();
SqlDataAdapter1.Fill(dataSet11);
}
В первых двух строках программного кода параметры (@CategoryName и @Description) команды InsertCommand адаптера данных SqlDataAdapter1 получают значения (в данном случае пустую строку). Затем открывается соединение с базой данных, исполняется команда InsertCommand (запись добавляется в базу данных) и соединение с базой данных закрывается. В следующих двух строках очищается от данных объект DataSetll и заполняется обновленной информацией из базы данных, путем вызова метода Fill адаптера данных. После этого добавленная запись появится в элементе отображения информации DataGrid.
Для обеспечения возможности удаления записи будет использована команда SqlDeleteCommand1 адаптера данных. Для получения доступа к тексту этой команды выделите мышью объект SqlDataAdapter1, войдите в окно его свойств и найдите строку DeleteCommand. Раскройте этот узел, щелкнув на указателе (+), найдите свойство CommandText и нажмите кнопку в этой строке. Откроется окно построителя запросов Query Builder с текстом соответствующего SQL-запроса. Измените текст этого запроса и приведите его к виду (рис. 4.55)
DELETE FROM Categories WHERE (CategoryID=@Original_CategoryID)
Рис. 4.55. Формирование запроса в окне Query Builder
Из текста этого запроса видно — для того чтобы удалить запись из таблицы categories, необходимо задать значения параметра @categoryID этого SQL- запроса. Значение CategoryID можно получить из текущей ячейки элемента отображения данных DataGrid (при этом будет удалена та запись, которую пользователь выделил в объекте DataGrid). Это обстоятельство нужно учесть при формировании программного кода. Программный код обработки события нажатия кнопки Удалить приведен в листинге 4.19.
Листинг 4.19
' Visual Basic
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e Asъ System. EventArgs) Handles Button2.Click
'Удаление записи
Dim row As Int16
Dim CategoryID As Int16
row=DataGrid1.CurrentCell.RowNumber
CategoryID=DataSet11.Categories(row).CategoryID
SqlDataAdapter1.DeleteCommand.Parametersъ
("@Original_CategoryID").Value=CategoryID
SqlConnection1.Open()
SqlDataAdapter1.DeleteCommand.ExecuteNonQuery()
SqlConnection1.Close()
DataSet11.Clear()
SqlDataAdapter1.Fill(DataSet11)
End Sub
//C#
private void button2_Click(object sender.System.EventArgs e)
{
//Удаление записи
int row ;
int CategoryID;
row=dataGrid1.CurrentCell.RowNumber;
CategoryID=dataSet11.Categories[row],CategoryID;
sqlDataAdapter1.DeleteCommand.Parameters*ъ
["@Original_CategoryID"].Value=CategoryID;
SqlConnection1.Open();
SqlDataAdapter1.DeleteCommand.ExecuteNonQuery();
SqlConnection1.Close();
dataSet11.Clear();
sqlDataAdapter1.Fill(dataSet11);
}
В первых двух строках программного кода выполняется объявление переменных: row - номер текущей строки элемента управления DataGrid, CategoryID — идентификатор удаляемой записи (категория товара). Затем переменная row получает значение текущей строки элемента DataGrid, переменная CategoryID получает значения идентификатора удаляемой записи (ИЗ строки С номером row таблицы Categories Набора данных DataSetll), Параметр @Originai_CategoryID команды DeleteCommand адаптера данных SqlDataAdapter1 получает значение из переменной CategoryID. Затем открывается соединение с базой данных, исполняется команда DeleteCommand (запись удаляется из базы данных) и соединение с базой данных закрывается. В следующих двух строках очищается от данных объект DataSetll и заполняется обновленной информацией из базы данных, путем вызова метода Fill адаптера данных. После этого удаленная запись исчезает из элемента отображенияинформации DataGrid.
Программный код обработки события нажатия кнопки Обновить приведен в листинге 4.20.
Листинг 4.20
' Visual Basic
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As^ System. EventArgs) Handles Button3.Click
'Обновление записей
SqlDataAdapter1.Update(DataSet11)
End Sub
//C#
private void button3_Click(object sender, System.EventArgs e)
{
sqlDataAdapter1.Update(dataSet11);
}
В этом фрагменте вызывается метод update адаптера данных SqlDataAdapter1. При этом все обновления, сделанные пользователем передаются в исходную таблицу базы данных.
Итак, мы познакомились с основными приемами получения и обновления данных в традиционных Windows-приложениях, когда пользователи работают в рамках локальной сети. Однако на сегодняшний день большинство компаний нуждаются в распределенных приложениях, когда не только филиалы компании, но и клиентура нуждается в доступе к единым информационным массивам через сеть Интернет. Для этих целей необходимо задействовать несколько иную технологию — Web-программирование и, в частности, активные серверные страницы (Active Server Pages, ASP). В Visual Studio .NET разработка Web-приложений выполняется в той же среде, что и Windows-приложений. Разработке ASP-приложений и Web-форм посвящены следующие главы.
ГЛАВА 5
Построение ASP-приложений с доступом к данным через ADO.NET
В этой и следующей главах будут рассмотрены вопросы создания страниц ASP.NET Web Form Page. И пусть понятие Web Form не смущает читателей. Возможности Web-форм гораздо шире, чем применение стандартных HTML-форм. В технологии .NET Web-формы состоят из двух составляющих. Первая из них — динамическая часть интерфейса пользователя, которая создается с помощью элементов управления. Они позволяют создавать "интеллектуальные" HTML-страницы и представляют, например, интерактивные таблицы с информацией из баз данных. Вторая составляющая Web- форм — логика приложения. Она представляет собой программный код, выполняемый, например, при нажатии кнопки на форме. В результате может, скажем, извлекаться информация из базы данных и заполняться этой информацией элемент управления (отображения данных).
В данной главе будут рассмотрены вопросы:
Q создания ASP-приложений и Web-форм;
Q работы с данными в Web-формах;
Q метод получения эффективного и быстрого доступа к данным в Web- формах без возможности их редактирования;
Q редактирования информации на уровне источника данных из Web- форм;
Q реализации доступа к данным через компонент пользователя.
Создание проекта и формы
И начнем мы с элементарного примера, который проиллюстрирует, как создать страницу с Web-формой, как добавить элемент управления к стра-
нице и создать программный код для этих элементов, который будет работать на сервере. В процессе работы над первым примером этой главы будут решены следующие задачи:
Q создание новой страницы с Web-формой;
Q добавление элемента управления и статического HTML-текста к странице;
Q создание обработчика события для элемента управления;
Q сборка и запуск приложения.
Когда пример будет закончен, ваша Web-форма будет иметь следующий вид (рис. 5.1).
'-.t rn-l i v ■ ■• "'■■ ' - Browve - Webforml |
1' ' ''I''I
Моя первая Web-форма
[Нажата кнопка Web-формы1
Button
Рис. 5.1, Внешний вид Web-формы в окне тестирования приложения
Первый шаг в реализации нашего первого Web-примера — создание Web- приложения и страницы с Web-формой.
Для создания проекта и формы выполните следующие действия.
В меню File выберите пункт New, затем выберите пункт Project.
В появившемся диалоговом окне New Project необходимо сделать следующее:
в области Project Types выберите тип проекта Visual Basic Projects или Visual C# Projects;
в области Templates выберите тип приложения ASP.NET Web Application;
в поле Location введите полный URL (адрес) для вашего приложения. Он должен включать указание протокола http://, имя сервера и имя проекта. У вас должен быть установлен Web-сервер (IIS) версии 5.0 и выше, а также .NET Framework. Если Web-сервер (IIS) установлен на вашем компьютере, то в качестве имени сервера можно задать http://localhost. Выберем для нашего проекта имя Web1 (рис. 5.2).
Project Types:Project Types:Templates:Templates:* ' ^ Visual Basic ProtectsLJ Visual C# ProtectsCj Setup and Deployment Projects♦ I Other ProjectsCd Visual Studio Solutions* ' ^ Visual Basic ProtectsLJ Visual C# ProtectsCj Setup and Deployment Projects♦ I Other ProjectsCd Visual Studio SolutionsWindowsApplication£ASP.NET WebApplfcatronWindowsApplication£ASP.NET WebApplfcatronClass libraryClass libraryWindowsControl LibraryWindowsControl Library^A5P.NET WebService^A5P.NET WebService|VB|VBWeb ControlLibraryWeb ControlLibrary
Project Types:
Project Types:
Templates:
Templates:
* ' ^ Visual Basic Protects
LJ Visual C# Protects
Cj Setup and Deployment Projects
♦ I Other Projects
Cd Visual Studio Solutions
* ' ^ Visual Basic Protects
LJ Visual C# Protects
Cj Setup and Deployment Projects
♦ I Other Projects
Cd Visual Studio Solutions
WindowsApplication
£
ASP.NET WebApplfcatron
WindowsApplication
£
ASP.NET WebApplfcatron
Class library
Class library
WindowsControl Library
WindowsControl Library
^
A5P.NET WebService
^
A5P.NET WebService
|VB
|VB
Web ControlLibrary
Web ControlLibrary
A project for creating an application with a Web user interface
Name:
location:location:| http://k>calhost/Web 1| http://k>calhost/Web 1Browse...Browse...
location:
location:
| http://k>calhost/Web 1
| http://k>calhost/Web 1
Browse...
Browse...
Project wil be created at http://localhost/Webl.
IMoreIMoreOK J CancelOK J CancelHelpHelp
IMore
IMore
OK J Cancel
OK J Cancel
Help
Help
Рис, 5.2. Окно создания нового Web-проекта
Примечание
Если у вас есть открытое приложение, то установите переключатель в положение Close Solution в окне New Project.
КогдавынажметекнопкуОК,будетсозданновый Web-проект,ион
будет размещен в корневом каталоге Web-сервера, который был задан на втором шаге. Кроме того, будет создана страница с Web-формой с именем WebForm1.aspx, которая будет отображена в окне Web Forms Designer.
Структура Web-формы
Рассмотрим, какую структуру имеет Web-форма, как она отображается в Web Forms Designer. Открывается Web Forms Designer тогда, когда вызывается файл с именем WebForm1.aspx. Страница Web-формы представлена двумя отдельными файлами.
Q Файл с расширением aspx содержит HTML-текст и элементы управления, которые обеспечивают интерфейс пользователя со страницей.
Q Отдельный файл с именем WebForm1.aspx.vb или WebForm1.aspx.cs (в зависимости от используемого языка программирования VB или С#) содержит программный код страницы (файл класса страницы). По умолчанию Solution Explorer не отображает файл класса страницы. Для дос-
II Solution Explorer - Web! 9 XII Solution Explorer - Web! 9 Xтупа к этому файлу нажмите кнопку Show АН Files на верхней панели Solution Explorer, затем разверните узел для WebForm1.aspx (рис. 5.3).
II Solution Explorer - Web! 9 X
II Solution Explorer - Web! 9 X
S3 $6@Q
Д Solution 'Webl' (1 project)
S ^ Webl
Й Is) References
S bin
i*H Assemtiylnfo.vb
&] Global.asax
Aj Styles.css
5» Web.conflg
^j Webl.vsdisco
ч WebForml.aspx
у WebForml.aspx.vb
Рис. 5.З. Файл с программным кодом Web-формы в окне Solution Explorer
В нижней части Web Forms Designer есть две вкладки: Design и HTML, которые показывают различные виды aspx-файла, с которым вы работаете.
Q Режим конструктора (Design) обеспечивает показ формы в том виде, как она будет выглядеть на экране (режим WYSIWYG). В этом режиме можно перетаскивать элементы управления на форму, менять их размеры и расположение, использовать окно Properties для конфигурирования их свойств.
Q В режиме HTML показывается та же форма, но в формате HTML. В данном режиме Web Forms Designer также поддерживает возможности Intellisense.
Вы можете работать с Web-формой в любом из этих двух режимов. Когда вы внесете какие-либо изменения в Web-форму в одном из этих режимов, при переключении в другой режим все эти изменения будут отображены. Немного позже мы остановимся на том, как работать с редактором программного кода Web-формы.
Добавление элементов управления и текста
По умолчанию Web-форма, с которой вы работаете, находится в режиме координатной сетки. В этом режиме вы можете перетаскивать на форму элементы управления и позиционировать их, используя абсолютные координаты х и у.
Однако при желании можно работать со страницей и по-другому — в режиме потока (flow layout mode), который используется на традиционных HTML-страницах, где элементы позиционируются сверху вниз. Каждый ре-
жим имеет свои преимущества: режим сетки облегчает позиционирование элементов, режим потока упрощает размещение статичного текста. В данном примере мы будем работать в режиме сетки. Сменить режим работы с Web-формой можно в окне ее свойств (рис. 5.4).
Рис. 5.4. Окно свойств Web-формы
Добавление элементов управления к Web-форме
Элементы управления Web-формы называют "серверными контролями", потому что, когда страница запущена, функции элементов управления выполняются на сервере. Когда пользователи взаимодействуют с контролем (например, нажимают кнопки), то код, связанный с этими кнопками, выполняется на сервере. В программном коде, расположенном на сервере, вы можете написать обработчики события для элементов управления, изменять их свойства и так далее.
Не каждый элемент на Web-форме является серверным контролем. Например, по умолчанию статический HTML-текст не является серверным контролем, и вы не можете управлять им в программном коде сервера. Даже стандартные HTML-контроли, например, HTML-кнопка submit, не является серверным контролем по умолчанию (эти HTML-элементы программируются на стороне клиента в виде сценариев, как и на любой обычной НТМL-странице)
Поэтому, чтобы работать с элементами управления на Web-форме, вы должны добавлять их к форме как серверные контроли. Существует два типа серверных контролен.
Q HTML-серверные контроли. Это элементы HTML, которые имеют отметку, что их программный код исполняется на сервере. Как правило, конвертируются традиционные HTML-элементы в серверные HTML- элементы (для чего должны быть определенные причины).
Q Web-серверные контроли. Это элементы управления, предназначенные для работы именно на Web-формах, и которые обеспечивают больше возможностей, чем серверные контроли HTML.
В реализуемом примере мы будем использовать по одному элементу каждого типа.
Для добавления HTML серверного контроля к Web-форме выполните следующие действия.
Переключитесь на вкладку Design в нижней части окна конструктора формы.
ИзвкладкиHTMLокнаToolboxперетащитенаформуэлементText
Field (рис. 5.5).
Можете переключиться на вкладку HTML (в нижней части окна дизайнера), чтобы увидеть, что ваше действие действительно добавило тег в HTML-код:
<INPUT style="Z-INDEX: 101; LEFT: 22px; POSITION: absolute; TOP: 17рх" type="text">
Переключитесь назад в режим дизайнера формы.
Преобразуйте созданный элемент к HTML серверному контролю, щелкнув на нем правой кнопкой мыши и выбрав из появившегося контекстного меню пункт Run As Server Control.
Отметка, появившаяся в левом верхнем углу элемента управления указывает, что этот элемент управления является серверным контролем (рис. 5.6).
Рис. 5.5. Элемент управления Text Field в окне ToolboxРис. 5.5. Элемент управления Text Field в окне ToolboxРис. 5.6. Признак серверного контроля виден в левом верхнем углу текстового поляРис. 5.6. Признак серверного контроля виден в левом верхнем углу текстового поляWebForml.espK* |WebForml.espK* |
Рис. 5.5. Элемент управления Text Field в окне Toolbox
Рис. 5.5. Элемент управления Text Field в окне Toolbox
Рис. 5.6. Признак серверного контроля виден в левом верхнем углу текстового поля
Рис. 5.6. Признак серверного контроля виден в левом верхнем углу текстового поля
WebForml.espK* |
WebForml.espK* |
В результате преобразования текстовое поле становится серверным контролем HtmlInputText, у которого присутствуют два новых атрибута.
Q Атрибут идентификации (id), который идентифицирует элемент управления в вашем программном коде. Для серверного элемента управления HtmlInputText этот атрибут по умолчанию принимает значение Text1.
QАтрибутrunatполучает значениеserver.Этоозначает,чтоэлементяв
ляется серверным контролем и становится доступным из серверного кода Web-формы.
Значения этих атрибутов вы можете увидеть в теге INPUT, если переключитесь на вкладку HTML дизайнера:
<INPUT style="Z-INDEX: 101; LEFT: 22рх; POSITION: absolute; TOP: 17px" type="text" id="Text1" name="Text1" runat="server">
Для добавления Web-серверного элемента управления к Web-форме из вкладки Web Forms окна Toolbox (не из вкладки HTML) перетащите на Web-форму элемент Button (рис. 5.7).
Toobo<-в X
Data
Web Forms 1^ Pointer A Label № TextBox
"b| Button «ь| UnkButton
Рис. 5.7. Элемент управления Button в окне Toolbox
Примечание
Вкладка Web Forms доступна только тогда, когда вы находитесь в режиме конструктора (Designer).
Таким образом мы создали серверный элемент управления (а не традиционную кнопку HTML). Если вы переключитесь в режим просмотра HTML- кода, то увидите следующий тег:
asp:Button id="Button1" style="Z-INDEX: 102; LEFT: 24px; POSITION: absolute; TOP: 74px" runat="server" Text="Button"></asp:Button >
Этот элемент (кнопка) не соответствует традиционному элементу HTML. Когда запускается Web-форма, на клиенте создается экземпляр класса Button Web-серверного элемента управления.
Добавление статичного HTML-текста на страницу
В режиме координационной сетки (grid layout mode) достаточно просто позиционировать элементы управления на Web-форме. Но как тогда разместить статичный HTML-текст? Поскольку все элементы на странице позиционированы с заданием точных координат х и у, вы не можете просто напечатать текст в любом месте страницы, как это можно было бы сделать в режиме потока (flow layout mode).
Проблема имеет простое решение — достаточно разместить на Web-форме HTML элемент управления Label, в который можно добавить статичный текст. После этого можно позиционировать текстовый элемент в любом месте страницы.
Для добавления статичного текста в режиме grid layout mode выполните следующие действия:
Из вкладки HTML окна Toolbox перетащите на Web-форму элемент Label (рис 5.8).
Рис. 5.8. Элемент управления Label в окне Toolbox
Расположите его в желаемом месте формы и сформируйте нужный размер элемента (рис. 5.9).
Рис. 5,9. Расположение элементов управления на форме
Щелкните мышью на элементе Label, чтобы установить на нем фокус, а затем щелкните еще раз. Здесь не нужно торопиться, так как должно быть сгенерировано два события click, а не одно событие Doubleclick.
После этого элемент Label переключится в режим ввода и редактирования текста, на что укажет появившаяся затененная граница элемента.
Напечатайтетекст,которыйвыхотитеразместитьнаWeb-форме,на
пример, "Моя первая Web-форма".
Выделите текст, щелкните на нем правой кнопкой мыши и в контекстном меню выберите пункт Build Style. Используя средства форматирования, выберите для него подходящий шрифт, размер, цвет и т.д. (рис. 5.10).
Рис. 5.10. Окно изменения свойств шрифта элемента управления Label
Щелкните мышью в любом месте формы, чтобы выйти из режима редактирования текста. У вас должна получится форма, аналогичная представленной на рис. 5.11.
WebForml.aspx* |
Моя первая Web-форма
г-——
Button
Рис. 5.11. Внешний вид Web-формы в окне дизайнера проекта
Создание обработчика события
Серверные элементы управления на Web-форме могут генерировать различные события. Многие события напрямую связаны с действиями, которые выполняют пользователи в браузере. Например, серверный элемент управления Button может вызвать событие click, когда пользователь нажимает кнопку на Web-форме.
Программный код обработки событий выполняется на сервере. Когда пользователь нажимает кнопку, страница отправляется назад на сервер. Затем ASP.NET Framework анализирует это событие, и если имеется обработчик соответствующего события, то он запускается автоматически. Когда программный код обработки события заканчивает свою работу, страница посылается назад браузеру со всеми изменениями, сделанными в результате работы обработчика события.
Для создания обработчика события Web-серверного элемента управления Button выполните следующие действия.
Дважды щелкните мышью на серверном элементе управления Button.
В результате этого будет создан шаблон процедуры обработчика события click для элемента управления Button. Программный код будет выглядеть следующим образом (листинг 5.1).
Листинг5.1
' Visual Basic
Private Sub Button1_Click(ByVal sender as System.Object, ByVal e as^ Sys- tem.EventArgs)HandlesButton1.Click
End Sub
// C|
private void Button1_Click(object sender, System.EventArgs e)
{
}
В обработчике события наберите программный код отображения сообщения в серверном элементе управления HtmlInputText через его свойство value. Пример приведен в листинге 5.2.
Листинг 5.2
' Visual Basic
Private Sub Button1_Click(ByVal sender as System.Object, ByVal e asЯр System. EventArgs) Handles Button1.Click
Text1.Value="Нажата кнопка Web-формы!"
End Sub
// С#
private void Button1_Click(object sender, System.EventArgs e)
{
Text1.Value=" Нажата кнопка Web-формы!";
}
Построение Web-приложения и запуск Web-формы
Прежде чем запустить на исполнение Web-форму, необходимо сначала скомпилировать приложение, после чего можно просмотреть страницу в любом браузере.
Для запуска Web-формы на исполнение сделайте следующие шаги:
В Solution Explorer щелкните правой кнопкой мыши на странице WebForm1.aspx и в контекстном меню выберите пункт Build and Browse.
Примечание
Если вы находитесь в режиме дизайнера приложения, нажмите <CTRL+F8>, чтобы выполнить команду Build and Browse.
После этого Visual Studio скомпилирует Web-страницу и отобразит ее во вкладке Browse tab.
Нажмите кнопку на вашей Web-форме.
Строка "Нажата кнопка Web-формы!" будет отображена в элементе TextBox (рис. 5.12).
'.-ерг . ...р. г ,еГ; znnLasp: ■ Browse - Webforml [
Моя первая Web-форма
|Нажата кнопка Web-формы!I
Button]
Рис. 5.12. Web-форма в режиме выполнения в окне Visual Studio
Чтобы выйти из режима исполнения Web-формы и вернуться в режим дизайнера, закройте вкладку Browse.
Можно также запустить приложение, нажав клавишу <F5>. Тогда будет запущен браузер, установленный на вашем компьютере, и в нем отобразится содержимое созданной Web-формы (рис. 5.13).
У Нмд *^| XJ g| , у ' Поиск Избранное ^ч Медиа
^^“•[tij^tov/^^Переход Ссыпки *
Моя первая Web форма
Нажата кнопка Web-формы1
I Button
48 Готово* J Местная интрасеть
Рис. 5.13. Web-форма в режиме выполнения в окне браузера
Работа с данными в Web-формах
Приложения, построенные на основе Web-форм, обеспечивают разнообразные варианты работы с данными. Пример, который вы выполните в данном разделе, иллюстрирует самый простой путь. Мы отобразим информацию из таблицы Categories базы данных Northwind в элементе DataGrid. Для этого мы создадим набор данных DataSet (кэш-контейнер в оперативной памяти компьютера), в который будет считана информация из базы данных. Затем свяжем созданный набор данных с элементом визуального отображения информации DataGrid, чтобы отобразить полученные данные. Следует отметить, что здесь используется Web-серверный элемент DataGrid, который принципиально отличается от того, который использовался на Windows- формах.
Примечание
Использование набора данных — это только один из вариантов доступа к данным в Web-формах, который не во всех случаях является оптимальным. Мы начнем именно с такого варианта, поскольку он является самым простым в реализации.
Для реализации примера вы должны иметь:
Q доступ к базе данных Northwin, которая поставляется вместе с SQL Server;
Q иметь права на размещения ASP.NET-приложений на компьютер, где установлен Web-сервер.
Работа над примером будет выполняться в несколько этапов:
Q создание Web-приложения и Web-формы;
Q создание и конфигурирование набора данных (эта процедура включает и создание запроса, который будет заполнять набор данных информацией из базы данных);
Q добавление к форме элемента DataGrid и связывание его с набором данных;
Q добавление программного кода для заполнения набора данных.
Создание проекта и формы
На первом этапе создадим Web-приложение и Web-форму.
ИзменюFileвыберитеподменюNewи щелкнитемышьюнапункте
Project.
В открывшемся диалоговом окне New Project выполните следующие действия:
в области Project Types укажите тип проекта Visual Basic Projects или Visual C# Projects;
в области Templates выберите ASP.NET Web-Application;
в поле Location введите полный URL вашего приложения. Он должен включать приставку http://, имя сервера и имя проекта. У вас должен быть установлен Web-сервер (1IS) версии 5.0 и выше, а также .NET Framework. Если Web-сервер (IIS) установлен на вашем компьютере, то в качестве имени сервера можно задать http://localhost. Задайте имя проекта, например, Web2.
Когда вы нажмете кнопку ОК, то будет создан новый Web-проект, который будет размешен в корневом каталоге Web-сервера, заданном выше. Кроме того, будет создана Web-форма с именем WebForm1.aspx.
Создание и конфигурирование набора данных
Как было отмечено в первой главе, набор данных может содержать несколько таблиц, но в примере данного раздела мы создадим набор данных, который будет содержать всего одну таблицу (categories). Для создания набора данных нужно сделать несколько шагов.
Q Создайте адаптер данных, используя соответствующего мастера. Адаптер данных содержит SQL-запросы для чтения и записи информации в базу данных. Мастер поможет создать необходимые SQL-запросы, а также создаст объект связи с базой данных.
Q Сгенерируйте схему набора данных. Visual Studio должен создать новый класс Dataset на основе информации из таблиц, к которым осуществляется обращение в базе данных. Когда будет сгенерирован класс DataSet, то экземпляр этого класса будет добавлен к форме.
Важно последовательно выполнить все процедуры текущего раздела, иначе ваше приложение не будет иметь необходимого объекта DataSet, без которого нельзя приступить к выполнению следующих шагов примера.
Создание и конфигурирование
объектов DataConnection и DataAdapter
Сначала нужно создать адаптер данных, который будет содержать SQL- запросы, позволяющие адаптеру взаимодействовать с источником данных. Как часть этого процесса будет создан и объект связи с базой данных. Для создания и конфигурации этих элементов можно использовать соответствующего мастера.
Для создания и конфигурирования адаптера данных выполните следующие действия.
Из вкладки Data окна Toolbox перетащите на форму элемент OleDbDataAdapter.
Примечание
Можно использовать и элемент SqlDataAdapter, который оптимизирован для работы с SQL-сервером версии 7.0 и выше. В этом примере применяется OleDbDataAdapter как более универсальное средство для работы с любыми источниками данных.
Появится окно мастера Data Adapter Configuration Wizard.
В мастере выполните следующие действия:
на второй странице мастера создайте или выберите подключение (Connection) к базе данных Northwind SQL-сервера;
Примечание
Вы должны иметь соответствующие права доступа к SQL-серверу. Рекомендуется использовать средства Windows для идентификации пользователя при создании подключения к базе данных. В качестве альтернативы можно определить имя пользователя и пароль непосредственно в объекте Connection, однако это ставит под угрозу
Connection, однако это ставит под угрозу защиту информации на SQL- сервере.
на третьей странице укажите, что вы хотите использовать именно SQL-запросы для обращения к базе данных;
на четвертой странице задайте следующий SQL-запрос:
SELECT CategoryID, CategoryName, Description FROM Categories
Для простоты формирования SQL-запроса нажмите кнопку Query Builder, чтобы запустить мастер построения запросов. При этом откроется диалоговое окно Query Builder (рис. 5.14).
Рис. 5.14. Формирование запроса в окне Query Builder
Примечание
В данном примере мы заполним набор данных всеми строками таблицы categories. В реальных приложениях создаются запросы, которые возвращают только определенные столбцы и строки таблиц.
Нажмите кнопку Finish.
Мастер создаст объект подключения к базе данных OleDbConnection1 содержащий информацию о том, как обратиться к вашей базе данных. Также будет создан адаптер данных OleDbDataAdapter1, который содержит тексты запросов для взаимодействия с базой данных.
После окончания работы мастера можно приступить к созданию набора данных.
Создание DataSet
После того как созданы объекты Connection и DataAdapter, Visual Studio может сгенерировать набор данных. Набор данных -- экземпляр класса DataSet, созданный на основе схемы набора данных (xsd-файл). В свою очередь схема набора данных описывает элементы этого класса (таблицы, столбцы таблиц и ограничения).
Для создания объекта DataSet выполните следующие действия.
Из меню Data выберите пункт Generate DataSet.
Примечание
Если меню Data не доступно, то нужно щелкнуть мышью в любом месте формы для передачи ей фокуса.
Появится диалоговое окно Generate DataSet.
Установите переключатель New и введите имя объекта ds Categories.
В списке под надписью Choose which table(s) to add to the dataset должна быть выбрана Таблица Categories (рис. 5.15).
Generate a dataset that includes the specified tables.
Choose a dataset:
C Existing [*|
f* New: IdsCategones
Choose which table(s) to add to the dataset:
v*. Categories(OlcDbDataAdapter!)
R? Add this dataset to the designer.
OKCancel
Рис. 5.15. Окно создания объекта DataSet
Установите флажок Add this dataset to the designer и нажмите кнопку ОК.
В результате Visual Studio сгенерирует типизированный класс набора данных (dsCategories) и схему, которая определяет структуру этого набора данных (файл схемы именем dsCategories.xsd появиться в окне Solution Explorer).
Примечание
В Solution Explorer нажмите на панели кнопку Show All Files, чтобы увидеть сопутствующий файл схемы (..vb или cs-файл), в котором содержится код, определяющий ваш новый класс набора данных.
И, наконец, Visual Studio добавит к форме экземпляр нового класса набора данных (DsCategories1).
На этом этапе мы сделали все, чтобы обеспечить передачу информации из базы данных в набор данных.
Добавление объекта DataGrid для отображения данных
В примере раздела мы будем использовать Web-серверный элемент управления DataGrid ДЛЯ отображения информации ИЗ таблицы Categories. Можно использовать элементы управления DataList или Repeater, однако DataGrid конфигурируется гораздо проще.
Для добавления и конфигурирования элемента управления DataGrid выполните следующие действия.
ИзвкладкиWebFormsокнаToolboxперетащитенаформуэлемент
управления DataGrid (рис. 5.16).
Рис. 5.16. Элемент управления DataGrid в окне Toolbox
В нижнейчастиокнаPropertiesнажмитенассылкуAutoFormatи в от
крывшемся окне выберите один из имеющихся стилей, например, Professionall (рис. 5.17).
Рис, 5.17. Окно AutoFormat элемента управления DataGrid
Свойству DataSource выберите из списка значение DsCategories1 (в качестве источника данных).
Свойству DataMember задайте значение Categories (из списка). В данном примере список будет состоять всего из одной таблицы (рис. 5.18).
Щ «999999*|Щ «999999*|BorderColor Borderstyle Borderwidth CeiPaddng CellSpacing Columns CssClass DataKeyField DataMember DataSourceBorderColor Borderstyle Borderwidth CeiPaddng CellSpacing Columns CssClass DataKeyField DataMember DataSourceDataGridl System.Web.Ul.WebCohtrols vj
Щ «999999*|
Щ «999999*|
BorderColor Borderstyle Borderwidth CeiPaddng CellSpacing Columns CssClass DataKeyField DataMember DataSource
BorderColor Borderstyle Borderwidth CeiPaddng CellSpacing Columns CssClass DataKeyField DataMember DataSource
3
0
(Colecbon)
Categories
J DsCateqoriesl v|
Рис. 5.18. Привязка к данным элемента управления DataGrid
Установка двух этих свойств связывает таблицу с именем categories набора данных DsCategories1 с сеткой данных DataGrid1.
Заполнение набора данных
и отображение информации в DataGrid
Хотя объект DataGrid и связан с набором данных, но сам набор данных является пустым — ведь он не заполняется автоматически. Чтобы заполнить набор данных, нужно в программе вызвать метод Fill адаптера данных. И даже после того, как набор данных будет заполнен, элемент управления DataGrid не отобразит данные. Для вывода информации нужно в программном коде явно связать DataGrid с источником данных.
Для заполнения набора данных и отображения информации в элементе DataGrid выполните следующие действия.
Дважды щелкните мышью на форме для перехода в режим редактора программного кода Web-формы (Code Editor).
В обработчике события загрузки страницы Page_Load вызовите метод Fill адаптера данных, передав ему в качестве параметра имя заполняемого набора данных:
OleDbDataAdapter1.Fill(DsCategories1)
Вызовите метод DataBind элемента управления DataGrid1 для явного связывания сетки данных с источником данных.
DataGrid1.DataBind()
Нет необходимости заполнять набор данных и связывать его с сеткой данных каждый раз, когда страница с Web-формой отправляется на сервер и возвращается назад клиенту. Эту процедуру достаточно сделать один раз, когда страница первый раз передается на компьютер клиента. Поэтому приведенные выше методы нужно вызвать только один раз, используя для организации этого процесса условный оператор IF и свойство страницы IsPostBack. Программный код будет выглядеть следующим образом (листинг 5.3).
pgpwww^i*», —^^—.™„... — "
Листинг 5.3
;...J™.:..™:
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As % System. EventArgs) Handles MyBase.Load
If Not IsPostBack Then
OleDbDataAdapter!.Fill{DsCategories1)
DataGrid1.DataBind()
End If
End Sub
H c#.
private void Page_Load(object sender.System.EventArgs e) {
if ( !IsPostBack)
{
OleDbDataAdapter!.Fill(dsCategories1);
DataGrid1.DataBind();
}
}
Тестирование приложения
После добавления программного кода запустим наше приложение на выполнение.
Сохраните проект.
В окне Solution Explorer щелкните правой кнопкой на имени проекта и выберите пункт контекстного меню Build and Browse.
Содержимое таблицы Categories будет отображено в сетке данных (рис. 5.19).
tL ■ j s . -. I :■ Browse - Webforml I
Category ID [ CategoryName I Description
22CondimentsCondiments33ConfectionsConfections456456Dairy Products Grains/CerealsDairy Products Grains/CerealsMeat/PouhryProduceMeat/PouhryProduce88SeafoodSeafoodI Soft dnnks. coffees, teas, beers, and ales. Sweet and savory sauces, relishes, spreads, and seasoningsDesserts. candies, and sweetbreadsCheesesBreads, crackers, pasta, and cerealPrepared meatsI Dned fruit and bean curdSeaweed and fishI Soft dnnks. coffees, teas, beers, and ales. Sweet and savory sauces, relishes, spreads, and seasoningsDesserts. candies, and sweetbreadsCheesesBreads, crackers, pasta, and cerealPrepared meatsI Dned fruit and bean curdSeaweed and fish
2
2
Condiments
Condiments
3
3
Confections
Confections
4
5
6
4
5
6
Dairy Products Grains/Cereals
Dairy Products Grains/Cereals
Meat/Pouhry
Produce
Meat/Pouhry
Produce
8
8
Seafood
Seafood
I Soft dnnks. coffees, teas, beers, and ales
. Sweet and savory sauces, relishes, spreads, and seasonings
Desserts. candies, and sweetbreads
Cheeses
Breads, crackers, pasta, and cereal
Prepared meats
I Dned fruit and bean curd
Seaweed and fish
I Soft dnnks. coffees, teas, beers, and ales
. Sweet and savory sauces, relishes, spreads, and seasonings
Desserts. candies, and sweetbreads
Cheeses
Breads, crackers, pasta, and cereal
Prepared meats
I Dned fruit and bean curd
Seaweed and fish
Рис. 5.19. Отображение данных в элементе управления DataGrid
Работа с данными, доступными только для чтения
В Web-приложениях часто требуется только отобразить данные, необходимые пользователям (без возможности их редактирования). Типичные при-
меры: каталоги продукции, прайс-листы, законодательные акты и т. д. Пользователям достаточно дать возможность задавать критерии поиска и получать результаты поиска в виде данных, доступных только для чтения.
В этом случае работа с данными может быть реализована более эффективными способами. В частности, нет необходимости кэшировать информацию (не нужно создавать объекты DataSet и DataAdapter). Для доступа к данным достаточно иметь два компонента: соединение с источником данных и команду данных. Кроме того, в таких случаях необходимо задействовать еще один специальный компонент — устройство считывания данных (data reader), который может выбрать полученные из источника данных записи и передать их к другому компоненту (например, объекту отображения информации). Устройство считывания данных разработано для быстрой обработки информации и работает в режиме read-only, forward-only (только чтение, только вперед), а это, как известно, чрезвычайно быстрый и эффективный режим доступа к данным.
В примере данного раздела будет показано, как создать Web-форму с серверным элементом управления DataGrid, который использует устройство считывания данных, чтобы отобразить информацию, доступную только для чтения.
Для реализации данного примера вам необходимо иметь:
а доступ к базе данных Pubs SQL-сервера;
Q права на создание и размещение ASP.NET приложений на вашем Web- сервере.
Реализация примера разбита на несколько этапов:
Q создание Web-формы;
Q добавление необходимых компонент доступа к данным;
Q добавление элемента управления DataGrid для отображения данных и определение его свойств;
Q добавление программного кода для выборки отображения данных.
Создание проектаи формы
На первом этапе создадим проект и Web-форму.
Для создания проекта и формы выполните описанные ниже действия.
•
В меню File выберите пункт New, а затем — Project.
В появившемся диалоговом окне New Project необходимо сделать следующее:
в области Project Types выберите тип проекта Visual Basic Projects или Visual C# Projects;
в области Templates выберите тип приложения ASP.NET Web Application;
в поле Location введите полный URL вашего приложения. Он должен включать приставку http://, имя сервера и имя проекта. У вас должен быть установлен Web-сервер (IIS) версии 5.0 и выше, а также .NET Framework. Если Web-сервер (IIS) установлен на вашем компьютере, то в качестве имени сервера можно задать http://localhost. В качестве имени проекта укажите Web3.
Если у вас есть открытое приложение, то установите переключатель в положение Close Solution в окне New Project.
Добавление компонентдоступа кданным
Чтобы реализовать получение данных, доступных только для чтения, необходимо создать объект подключения к базе данных и команду данных. Команда данных включает в себя SQL-запрос, который выполняет процедуру выборки данных. Кроме того, команда данных может ссылаться на хранимую процедуру, однако в этом примере будет использоваться простой SQL- запрос с инструкцией SELECT.
Создание и конфигурирование объекта Connection
Начнем пример с добавления на форму объекта Connection, обеспечивающего соединение с базой данных, из которой будет считываться информация.
Для создания Connection выполните следующие действия.
Из вкладки Data окна Toolbox перетащите на форму элемент OleDbConnection (рис. 5.20).
Примечание
В данном примере можно использовать также и элемент SqlDataAdapter, который оптимизирован для работы с SQL-сервером версии 7.0 и выше. Мы же применяем OleDbDataAdapter как более универсальное средство для работы с любыми источниками данных.
Выделите на форме элемент Connection и в окне Properties нажмите кнопку в поле свойства ConnectionString (рис. 5.21).
Toolbox-Q XToolbox-Q XData
Toolbox-Q X
Toolbox-Q X
^ Pointer
£3 DataSet
fgj OteDbOataAdapter | ^ OteDbConnection
^5 OleDbCommand '^ SqlDataAdaptet
•j$ SqlConnection
'^ SqiCommand
Уу DataView
Рис. 5.20. Элемент OleDbConnectionРис. 5.21. Свойство ConnectionString
в окне Toolboxв окне свойств элемента
OleDbConnection
В открывшемся списке будут отображены все существующие объекты connection и пункт New Connection.
Если отсутствует подключение с базой данных pubs SQL-сервера, то выбираете New Connection.
Рис. 5.22. Диалоговое окно формирования свойств связи с даннымиРис. 5.22. Диалоговое окно формирования свойств связи с даннымиПоявится диалоговое окно Свойства связи с данными (Data Link Properties) (рис. 5.22).
Рис. 5.22. Диалоговое окно формирования свойств связи с данными
Рис. 5.22. Диалоговое окно формирования свойств связи с данными
Создайте подключение, указав имя вашего SQL-сервера и базу данных Pubs, а затем нажмите кнопку ОК.
Примечание
Вы должны иметь соответствующие права доступа к SQL-серверу. Рекомендуется использовать средства Windows для идентификации пользователя при создании подключения к базе данных. В качестве альтернативы можно определить имя пользователя и пароль непосредственно в объекте Connection, однако это ставит под угрозу защиту информации на SQL-сервере.
Информация с параметрами подключения к базе данных будет сохранена В свойстве ConnectionString объекта Connection.
Итак, мы определили подключение к базе данных, теперь необходимо добавить команду данных с SQL-запросом для выборки нужной информации.
Для создания объекта Command и SQL-запроса выполните следующие действия.
Из вкладки Data окна Toolbox перетащите на форму объект OleDbCommand (рис. 5.23).
Примечание
Вы можете использовать объект SqlCommand, который оптимизирован для работы с SQL-сервером версии 7.0 и выше. Мы же используем OleDbCommand как более универсальное средство работы со всеми источниками данных.
Выберите объект command и в окне Properties нажмите кнопку в строке свойства Connection, затем выберите подключение, которое мы создали на предыдущем шаге (рис. 5.24).
Toolbox-е XToolbox-е XPropertiesО XPropertiesО XData]^ Pointer э?| DataSet '^ OleDbDataAdapter !i^ OleDbConnection ■ ^ OleDbCommand '$Ь SqlDataAdapter ?^ SqlConnection $ SqlCommand 6^7 DataViewData]^ Pointer э?| DataSet '^ OleDbDataAdapter !i^ OleDbConnection ■ ^ OleDbCommand '$Ь SqlDataAdapter ?^ SqlConnection $ SqlCommand 6^7 DataViewOleDbCommand 1 System.Data.OleDb.OleDt jJИ (Dynamicproperties) (Name)OleDbCommand 1CommandText CommandTImeout30CommandTypeTextВ ConnectionOleDbConnection1ModfiersFamilyParameters(Collection)UpdatedRowSourceBothOleDbCommand 1 System.Data.OleDb.OleDt jJИ (Dynamicproperties) (Name)OleDbCommand 1CommandText CommandTImeout30CommandTypeTextВ ConnectionOleDbConnection1ModfiersFamilyParameters(Collection)UpdatedRowSourceBothРис. 5.23. Объект OleDbCommandв окне ToolboxРис. 5.23. Объект OleDbCommandв окне ToolboxРис. 5.24. Задание значения свойствуConnection объекта OleDbCommandРис. 5.24. Задание значения свойствуConnection объекта OleDbCommand
Toolbox-е X
Toolbox-е X
PropertiesО X
PropertiesО X
Data]
^ Pointer э?| DataSet '^ OleDbDataAdapter !i^ OleDbConnection ■ ^ OleDbCommand '$Ь SqlDataAdapter ?^ SqlConnection $ SqlCommand 6^7 DataView
Data]
^ Pointer э?| DataSet '^ OleDbDataAdapter !i^ OleDbConnection ■ ^ OleDbCommand '$Ь SqlDataAdapter ?^ SqlConnection $ SqlCommand 6^7 DataView
OleDbCommand 1 System.Data.OleDb.OleDt jJ
И (Dynamicproperties) (Name)OleDbCommand 1
CommandText CommandTImeout30
CommandTypeText
В ConnectionOleDbConnection1
ModfiersFamily
Parameters(Collection)
UpdatedRowSourceBoth
OleDbCommand 1 System.Data.OleDb.OleDt jJ
И (Dynamicproperties) (Name)OleDbCommand 1
CommandText CommandTImeout30
CommandTypeText
В ConnectionOleDbConnection1
ModfiersFamily
Parameters(Collection)
UpdatedRowSourceBoth
Рис. 5.23. Объект OleDbCommandв окне Toolbox
Рис. 5.23. Объект OleDbCommandв окне Toolbox
Рис. 5.24. Задание значения свойствуConnection объекта OleDbCommand
Рис. 5.24. Задание значения свойствуConnection объекта OleDbCommand
В свойстве CommandText нажмите кнопку, чтобы открыть диалоговое
окно Query Builder.
ИспользуяQuery Builder, сформируйте следующий SQL-запрос
(рис. 5.25):
Select au_id, au_fname, au_lname, phone From authors
Рис. 5.25. Формирование запроса в окне Query Builder
Примечание
1В данном случае мы указали все строки из таблицы authors. В реальных приложениях обычно создается параметризированный запрос, который возвращает только определенные столбцы и записи таблицы.
Когда вы закроете диалоговое окно Query Builder, текст SQL-запроса будет помещен В СВОЙСТВО CommandText,
Мы создали компоненты доступа к данным. Теперь необходимо добавить элементы управления, которые обеспечат визуальное отображение данных.
Добавление элементов отображения данных
Мы будем использовать серверный элемент управления DataGrid, чтобы отобразить на Web-форме полученную из базы данных информацию.
Для добавления и конфигурирования элемента управления DataGrid выполните следующие действия.
Из вкладки Web Forms окна Toolbox перетащите на форму элемент управления DataGrid.
В нижней части окна Properties, щелкните ссылку AutoFormat, после чего откроется окно выбора стиля внешнего вида DataGrid. В данном примере в окне AutoFormat выберем стиль Simple 2 (рис. 5.26).
Рис. 5.26. Выбор стиля Simple 2 в окне AutoFormat элемента управления DataGrid
Во всех предыдущих примерах при конфигурировании свойств объекта DataGrid в первую очередь устанавливалось значение свойства DataSource. Сейчас мы не будем устанавливать его значение в дизайнере формы, а сделаем это позже в программном коде. Мы также не будем явно конфигурировать столбцы сетки, они будут сформированы динамически. Ваша Web- форма должна будет иметь следующий вид (рис. 5.27).
-•Ж- ... Webf<Kml.«pM | ■ J , : ли -b
Рис. 5.27. Внешний вид Web-формы в окне дизайнера
Добавление программного кода
для выборки и отображения данных
Чтобы реализовать быстрый и оптимальный доступ к данным, необходимо выполнить SQL-запрос, который мы создали в команде данных. Доступ к полученной информации можно реализовать через "считыватель" данных (объект DataReader). Все это можно сделать в программном коде.
Для добавления программного кода выполните следующие шаги.
Дважды щелкните на Web-форме для открытия редактора кода и найдите обработчик события Page_Load.
Напишите код для выполнения следующих действий:
создайте переменную для экземпляра объекта OleDbDataReader;
откройте соединение;
запустите команду данных на исполнение. Для этого вызовите метод
ExecuteReader команды данных oleDbCommand1, который выполнит SQL-запрос в команде данных и возвратит набор записей, который будет помещен в объект считывания данных OleDbDataReader;
установите в качестве значения свойства datasource элемента управления DataGrid1 ссылку на экземпляр объекта OleDbDataReader. Мы не могли сделать этого раньше в дизайнере формы, потому что экземпляра объекта считывания данных OleDbDataReader на тот момент не существовало;
свяжите элемент управления DataGrid с объектом считывания данных;
закройте OleDbDataReader;
закройте соединение. Это очень важный шаг. Соединение остается открытым на то время, когда происходит выборка записей из базы данных. Когда эта процедура завершена, необходимо закрыть соединение и освободить ресурсы сервера, которые были задействованы под обслуживание этого соединения.
Программный код, приведенный в листинге 5.4, реализует вышеупомянутые шаги.
Примечание
Для большей ясности в коде явно создана переменная Reader для объекта считывания данных.
Листинг 5.4 u.™— л—................................—
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, ByVal e Asъ System. EventArgs) Handles MyBase.Load
If Hot IsPostBack Then
oleDbConnection1.Open()
Dim Reader As System, Data.OleDb.OleDbDataReader
Reader=oleDbCommand1.ExecuteReader()
DataGrid1.DataSource=Reader
DataGrid1.DataBind()
Reader.Close()
oleDbConnection1.Close()
End If
End Sub
// C#
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack) {
OleDbConnection1.Open();
System.Data.OleDb.OleDbDataReader Reader;
Reader=oleDbCommand1.ExecuteReader();
DataGrid1.DataSource=Reader;
DataGrid1.DataBind();
Reader.Close();
oleDbConnection1.Close() ;
}
}
Тестирование приложения
После добавления кода можно запустить приложение на выполнение.
Для запуска Web-формы выполните следующие действия.
Сохраните проект.
В окне Solution Explorer щелкните правой кнопкой мыши на Web-форме и выберите в контекстном меню пункт Build and Browse. Для запуска приложения можно также нажать клавишу <F5> или нажать кнопку Start на панели инструментов.
Содержимое таблицы authors должно отобразится в сетке данных (рис. 5.28).
Рис. 5.28. Отображение данных в элементе DataGrid на этапе выполнения приложения
Редактирование информации на уровне источника данных из Web-форм
В Web-формах обеспечивается одностороннее связывание элементов управления с источником данных. Такая архитектура позволяет достаточно просто реализовать отображения информации на стороне клиента, однако при этом не поддерживается обновление информации на сервере. Поскольку в большинстве Web-приложений требуется только чтение и отображение информации, а не их модификация, то одностороннее связывание дает возможность строить достаточно "легкие" приложения, не требующие мощных ресурсов для работы на сервере.
Однако во многих приложениях возникает потребность ввода или редактирования информации на стороне клиента и возврат этих изменений в источник данных. Существует несколько способов обновления источника данных. Если используется набор данных, то можно записать все измененные записи в отдельный набор данных, а затем вызвать соответствующий метод адаптера данных, чтобы вернуть все модифицированные записи из набора данных в базу данных, В качестве альтернативы можно с компьютера клиента выполнять модификацию информации непосредственно в базе данных, без каких либо объектов-посредников, используя для этих целей SQL-запросы или хранимые процедуры.
Пример, который мы выполним в этом разделе, иллюстрирует как раз второй способ. Нами будет создана Web-форма, которая обменивается инфор-
мацией с базой данных через SQL-запросы. В этом примере будет задействована таблица categories базы данных Northwind SQL-сервера. Мы реализуем процедуру выборки информации, ее редактирования и передачу отредактированных записей назад в базу данных.
На данном примере будет проиллюстрирована реализация нескольких действий:
О создание объектов команды данных, содержащих SQL-запросы;
Q совместное использование SQL-запросов и объектов считывания данных (DataReader) для выборки записей из базы данных;
Q создание параметризированных запросов;
Q определение параметров запросов и выполнение запросов.
Для реализации этого примера необходимо:
Q иметь доступ к тестовой базе Northwind, поставляемой с SQL-сервером;
Q иметь права на создание и размещение ASP.NET-приложений на используемом Web-сервере.
Выполнение примера разбито на несколько этапов:
Q создание Web-формы;
Q добавление необходимых компонентов для работы с данными;
Q добавление элементов управления для отображения информации;
Q добавление программного кода для чтения и обновления информации.
Создание проекта и формы
На первом этапе создадим Web-приложение и Web-форму.
Для создания проекта и формы выполните следующие действия.
В меню File выберите пункт New и элемент Project.
В открывшемся диалоговом окне New Project выполните следующее:
в левой части Project Types выберите тип проекта Visual Basic Projects или Visual C# Projects;
В области Templates выберите тип приложения ASP.NET Web Application;
в поле Location введите полный URL для вашего приложения. Он должен включать http://, имя сервера и имя проекта. У вас должен быть установлен Web-сервер (IIS) версии 5.0 и выше, а также .NET
Framework. Если Web-сервер (IIS) установлен на вашем компьютере, то в качестве имени сервера можно задать http://localhost. Назовите проект Web4.
Когда вы нажмете кнопку ОК, то новый Web-проект будет создан иразме- щен в корневом каталоге Web-сервера, который был вами задан. Кроме того, будет создана страница Web-формы с именем WebFortn1.aspx, которая будет отображена в окне Web Forms Designer.
Добавление компонент для доступа к данным
Чтобы работать с данными, нужно иметь подключение к базе данных, из которой вы хотите получить информацию. Также необходимо иметь объекты команд данных (для чтения информации из базы данных в виде SQL-запроса с инструкцией SELECT, для модифицирования данных в виде SQL-запроса с инструкцией UPDATE). Объекты команд данных будут иметь параметры, которым нужно присвоить значения перед запуском команд на исполнение. Команды данных могут ссылаться и на хранимые процедуры (вместо SQL- запросов), но в этом примере будут использоваться SQL-запросы.
Создание и конфигурирования соединения с базой данных Connection
На первом шаге создадим соединение с базой данных — объект Connection.
Для создания connection выполните следующие действия.
Из вкладкиData окна Toolbox перетащите на форму объект
SqlConnection (рис. 5.29).
Toolbox-a X
Data-
It Pointer a?| DataSet ^ OleDbDataAdapter 1^ OleDbConnecbon *') OleDbCommand ^ SqlDataAdapter tj^ SqlCormection *^ SqlCommand ^ DataView
Рис. 5.29. Объект SqlConnection в окне Toolbox
Примечание
В данном примере мы используем объект SqlConnection, который оптимизирован для работы с SQL-сервером версии 7.0 и выше. Если в своих приложе-
ниях вы будете обращаться к другим источникам данных, то используйте OleDbConnection, который обеспечивает соединение с более широким спектром источников данных.
Выделите созданное соединение и в окне свойств Properties нажмите КНОПКУ В строке свойства ConnectionString.
Появится список существующих объектов соединения и пункт New Connection.
Если вы ранее не создавали соединение с базой данных Northwind SQL-сервера, то выберите New Connection.
Появится диалоговое окно Свойства связи с данными (Data Link Properties).
В нем задайте имя SQL-сервера, выберите базу данных Northwind и нажмите кнопку ОК (рис. 5.30).
Рис. 5.30. Диалоговое окно формирования свойств связи с данными
Примечание
Вы должны иметь соответствующие права доступа к SQL-серверу. Рекомендуется использовать средства Windows для идентификации пользователя при
создании подключения к базе данных. В качестве альтернативы можно определить имя пользователя и пароль непосредственно в объекте Connection, однако это ставит под угрозу защиту информации на SQL-сервере.
Информация с параметрами подключения к базе данных будет сохранена в Свойстве Connectionstring объекта Connection.
Итак, мы определили подключение к базе данных. Теперь к форме необходимо добавить команды. Нам потребуется три команды данных, каждая из которых будет содержать различные запросы:
Q для получения значений идентификаторов категории (CategoryID);
Q для выборки интересующей категории (на основе значения ее идентификатора);
Q для присвоения выбранной категории нового значения.
Для создания команды получения идентификаторов категории выполните следующие действия.
Из вкладки Data окна Toolbox перетащите на форму объект SqlCommand (рис. 5.31).
Todbox-a X |
Data
It Pointer
1э?| DataSet
4V, OleDbDataAdapter
'1, OleDbConnection
^ OleDbCommand
SqlDataAdapter
r^f SqKonnectioo
'{’? SqlCommand
^ DataVew
Рис. 5.31. Объект SqlCommand в окне Toolbox
Присвойте команде новое имя cmdCategoriesAll.
Выделите созданную команду, и в окне свойств Properties нажмите кнопку в строке свойства connection. Выберите соединение, которое вы создали ранее (для этого нужно открыть узел Existing).
В строке свойства CommandText нажмите кнопку для открытия диалогового окна построителя запросов Query Builder.
Используя Query Builder, сформируйте следующий SQL-запрос: SELECT CategoryID, CategoryName, Description FROM Categories
ПозавершениюэтойработызакройтедиалоговоеокноQueryBuilder
(рис. 5.32).
Рис. 5.32. Формирование запроса в окне Query Builder
Текст созданного SQL-запроса будет помещен в строку свойства коман- дыCommandText.
Процедура создания следующей команды несколько сложнее, поскольку потребует создания параметров.
Для создания команды получения одной записи таблицы categories выполните следующие действия.
Перетащите на форму второй объект SqlCommand и присвойте его свойству Connection Значение SqlConnection1.
Задайте Команде ИМЯ cmdCategoriesById.
В строке свойства CommandText нажмите кнопку для открытия диалогового окна построителя запросов Query Builder.
С помощью Query Builder сформируйте следующий SQL-запрос (рис. 5.33):
SELECT CategoryID, CategoryName, Description
FROM Categories
WHERE (CategoryID=@categoryid).
Примечание
Переменная @categoryid является "поименованной переменной". Имя этой переменной может быть любым, оно будет использовано чуть позже, когда по-
требуется определение значений параметров запроса. Префикс "@" перед именем требуется для SQL-сервера, в качестве признака поименованного параметра.
Рис. 5.33. Формирование запроса с параметрами в окне Query Builder
Последняя команда включает инструкцию UPDATE для того, чтобы передать внесенные пользователем изменения назад в базу данных.
Для создания команды обновления записи таблицы Categories базы данных выполните следующие шаги.
Перетащите на форму еще один объект SqlCommand и присвойте свойст- вуConnection этого объекта значение SqlConnection1.
Задайте ИМЯ Объекту cmdCategoriesUpdate.
Задайте свойству команды CommandText текст следующего запроса:
UPDATE Categories
SET CategoryName=@categoryname,
Description=@categorydescription
WHERE (CategoryID=@categoryid)
На этом мы закончим создание компонент для работы с базой данных.
Добавление элементов управления
Нам понадобятся следующие элементы управления на форме: раскрывающийся список для выбора идентификатора категории, текстовые поля для отображения и редактирования данных, кнопка для передачи изменений в базу данных.
Для добавления элементов управления к форме выполните следующие действия.
Из вкладки Web Forms окна Toolbox перетащите на форму элементы управления и сконфигурируйте их свойства (согласно табл. 5.1).
Таблица 5.1. Значения свойств элементов управления Web-формы
Элементы
Назначение
Свойства
DropDownList
Позволяет пользователю выбирать нужную категорию из списка
ID: ddlCategoryID
AutoPostBack: true
TextBox
Позволяет пользователям ровать имя категории
редакти-
ID: txtCategoryNarne
TextBox
Позволяет пользователям ровать описание категории
редакти-
ID:txtCategoryDe
scription
Button
Передает исправления, сделанные пользователем в базу данных
ID: btnSave
Text: Сохранить
Добавьте метки (Lebel) к текстовым элементам управления для описания их назначения.
Ваша форма должна иметь следующий вид (рис. 5.34).
v.art -«,е WebForml.aspx* | WebFon. : -<. vb*
■ fllnbound■ fllnboundи;Сохранитьи;Сохранитьи
■ fllnbound
■ fllnbound
и;
Сохранить
и;
Сохранить
Категория
Й
Имя категории
у Д
Описание категории
Рис. 5.34. Расположение элементов управления на форме
Добавление программного кода для отображения и обновления данных
На этом этапе работы над примером мы добавим программный код, который выполнит следующие три задачи.
Q Во время первой инициализации (загрузки) страницы нужно заполнить данными раскрывающийся список (категории). Так как первый элемент списка (идентификатор категории) будет выбран автоматически, нужно отобразить в текстовых полях одну запись из таблицы Categories.
Q Когда пользователь выберет новый идентификатор категории из раскрывающегося списка, то необходимо запомнить, какой идентификатор был выбран. Далее, используя полученное значение, необходимо выполнить SQL-запрос, который вернет одну запись из таблицы Categories и разместить ее в текстовые поля.
Q Когда пользователь нажмет кнопку, то необходимо получить все изменения в записи, сделанные пользователем, и передать их назад в базу данных.
Начальная загрузка данными раскрывающегося списка при инициализации Web-формы
Чтобы заполнить раскрывающийся список, необходимо выполнить запрос, который вернет все записи из таблицы Categories. Эту процедуру нужно сделать один раз, при первой загрузке Web-страницы в браузер пользователя. После этого значения элементов списка сохранятся в элементе управления.
После выполнения запроса мы будем использовать считыватель данных (объект SqlDataReader) для выборки полученных записей. Элемент DataReader обеспечивает чрезвычайно быстрый доступ к данным и требует минимальных ресурсов компьютера (правда он обеспечивает работу с данными только в режиме read-only, forward-only),
Для добавления программного кода заполнения раскрывающегося списка выполните следующие действия.
Дважды щелкните в любом месте Web-формы, чтобы открыть редактора кода и найдите обработчик события page_Load.
Напишите программный код для выполнения следующего:
проверьте значение свойства страницы IsPostBack, чтобы определить, загружается ли она первый раз. В случае соблюдения этого условия последовательно выполните следующие шаги;
создайте объектную переменную dreader для экземпляра класса SqlDataReader;
откройте соединение;
вызовите метод ExecuteReader объекта cmdCategoriesAll, Который выполнит SQL-запрос и поместит результаты запроса в объектную переменную dreader;
создайте переменную, которую будете использовать для того, чтобы заполнить текстовые поля информацией из первой записи полученных данных;
организуйте цикл для перебора всех полученных записей;
внутри этого цикла заполните данными раскрывающийся список (поместив туда значение поля идентификатора категории);
только для первой записи присвойте полученные значения соответствующим текстовым полям (определив их свойство Text);
закройте экземпляр объекта считывания данных dreader;
закройте соединение. Это важный шаг, позволяющий освободить задействованные на соединение ресурсы компьютера.
Листинг 5.5 показывает программный код, где реализованы описанные выше шаги.
Листинг 5.5
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As^ System. EventArgs) Handles MyBase.Load
If Not IsPostBack Then
Dim dreader As SqlClient.SqlDataReader
SqlConnection1.Open()
dreader=cmdCategoriesAll.ExecuteReader()
Dim firstrow As Boolean=True
While dreader.Read()
ddlCategoryID.Items.Add(New ListItem(dreader(0).ToString()))
If firstrow Then
txtCategoryName.Text=dreader(1).ToString
txtCategoryDescription,Text=dreader(2).ToString
firstrow=False
End If
End while
dreader.Close()
SqlConnection1.Close()
End If
End Sub
// C#
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
System.Data.SqlClient.SqlDataReader dreader;
sqlConnection1.Open();
dreader=cmdCategoriesAll.ExecuteReader();
bool firstrow=true;
while(dreader.Read())
{
ddlCategoryID.Items.Add(new ListItem(dreader[0].ToString()));
if (firstrow)
{
txtCategoryName.Text=dreader[1].ToString();
txtCategoryDescription.Text=dreader[2].ToString();
firstrow=false;
}
}
dreader.Close();
SqlConnection1.Close();
)
}
Отображение записи, соответствующей выбранному пользователем идентификатору категории
Раскрывающийся список отображает идентификаторы категорий. Когда пользователь выбирает один из элементов списка, то есть когда происходит событие SelectedIndexChanged, необходимо отобразить запись таблицы categories, запрошенную пользователем.
Когда вы создавали раскрывающийся список, то значению его свойства AutoPostBack было присвоено значение true. Это значит, что страница будет возвращаться на сервер, как только пользователь сделает выбор элемента из списка.
Чтобы получить затребованную пользователем запись необходимо выполнить SQL-запрос с предложением WHERE, который должен вернуть из табли-
цы выбранную пользователем запись. Чтобы передать в запрос идентификатор категории, выбранный пользователем, необходимо присвоить выбранное пользователем значение параметру запроса. Иными словами, необходимо определить значение параметра (объект SqlParameter), который является частью команды данных.
Для добавления программного кода выборки из базы данных затребованной пользователем записи выполните следующие действия.
Дважды щелкните раскрывающийся список, чтобы открыть редактор кода И создать обработчик события SelectedIndexChanged(выбор
элемента списка).
Напишите программный код для выполнения следующего:
получите значение элемента, выбранного пользователем из раскрывающегося списка;
присвойтепараметру@categoryidкомандыданных
cmdCategoriesById значение, выбранное пользователем в раскрывающемся списке;
откройте соединение;
создайте объектную переменную -экземпляр класса SqlDataReader (считыватель данных) и вызовите метод ExecuteReader объекта команды данных cmdCategoriesById, чтобы выполнить команду. Поскольку нужно вернуть всего лишь одну запись, передайте методу соответствующий флаг(CommandBehavior.SingleRow);
используйте метод Read считывателя данных, чтобы присвоить значения из полученной записи текстовым полям (для отображения данных);
закройте считыватель данных (DataReader);
закройте соединение (connection).
Листинг 5.6 показывает программный код обработчика события SelectedIndexChanged, где реализованы вышеупомянутые шаги.
Листинг 5.6
I -—
' Visual Basic
Private Sub ddlCategoryID_SelectedIndexChanged(ByVal sender As% Sys- tem.Object, ByVal e As System.EventArgs) Handles^> ddlCate- goryID. SelectedIndexChanged
Dim categoryid As String
categoryid=ddlCategoryID.SelectedItem.Text
cmdCategoriesById.Parameters("@categoryid").Value=categoryid
SqlConnection1.Open()
Dim dreader As SqlClient.SqlDataReader
dreader=cmdCategoriesById.ExecuteReader(CommandBehavior.SingleRow)
If dreader.Read() Then
txtCategoryName.Text=dreader(1)
txtCategoryDescription.Text=dreader(2)
End If
dreader.Close()
SqlConnection1.Close()
End Sub
// C#
private void ddlCategoryID_SelectedIndexChanged(object sender, ъ Sys- tem.EventArgs e)
{
string categoryid;
categoryid=ddlCategoryID.SelectedItem,Text;
cmdCategoriesById,Parameters["@categoryid"].Value=categoryid;
SqlConnection1.Open();
System.Data.SqlClient.SqlDataReader dreader;
dreader=cmdCategoriesById.ExecuteReader(CommandBehavior.SingleRow);
if (dreader.Read())
{
txtCategoryName.Text=dreader[1].ToString();
txtCategoryDescription.Text=dreader[2].ToString();
}
dreader.Close();
SqlConnection1.Close();
}
Обновление записей
И наконец, мы добавим программный код, который вернет в базу данных те изменения, которые внесет пользователь в полученную запись. Команда обновления данных всегда имеет параметры и перед запуском такой команды на исполнение всем ее параметрам необходимо присвоить значения. Команда данных с инструкцией UPDATE не возвращает записей.
Для обновления записей в таблице базы данных выполните следующие шаги.
I.ДваждыщелкнитенакнопкеСохранить,чтобысоздатьобработчиксо
бытия Click.
Напишите программный код для выполнения следующего:
присвойте трем параметрам команды обновления данных значения из соответствующих элементов управления Web-формы;
откройте соединение;
вызовите метод ExecuteNonQuery команды обновления данных cmdCategoriesUpdate;
закройте соединение.
Листинг 5.7 показывает программный код обработчика события click, реализующий вышеупомянутые шаги.
Листинг 5.7 ~ ..L.uн.!.—^..^...^.^~-:.; ;.; м^»;.ш;54^а^*^«***^..2.;..............■i
' Visual Basic
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e Asъ
System.EventArgs) Handles btnSave.Click
With cmdCategoriesUpdate
.Parameters("@categoryid"),Value=ddlCategoryID.SelectedItem.Text
.Parameters("@categoryname").Value=txtCategoryName.Text
.Parameters("@categorydescription").Value = ^
txtCategoryDescription.Text
End With
SqlConnection1.Open()
cmdCategoriesUpdate.ExecuteNonQuery()
SqlConnection1.Close()
End Sub
// C#
private void btnSave_Click(object sender, System.EventArgs e)
{
cmdCategoriesUpdate.Parameters["@categoryid"].Value =%>
ddlCategoryID.SelectedItem.Text;
cmdCategoriesUpdate.Parameters["@categoryname"].Value =ъ
txtCategoryName.Text;
cmdCategoriesUpdate.Parameters["@categorydescription"].Value =ъ
txtCategoryDescription.Text;
SqlConnection1.Open();
cmdCategoriesUpdate.ExecuteNonQuery(};
SqlConnection1.Close();
}
Тестирование приложения
Теперь мы можем проверить работу нашего приложения.
В Solution Explorer щелкните правой кнопкой мыши на странице и выберите пункт Build and Browse или нажмите клавишу <F5>.
Когда страница будет загружена, удостоверьтесь, что раскрывающийся список содержит перечень идентификаторов категории и что первая запись таблицы базы данных отображена в текстовых полях.
Выберите несколько различных категорий в списке.
В текстовых полях должны быть показаны новые записи (рис. 5.35).
Рис. 5.35. Приложение, запущенное в окне браузера
Примечание
Если при выборе нового элемента в раскрывающемся списке не происходит смена записи в текстовых полях, то удостоверьтесь, что свойство AutoPostBack элемента управления DropDownList имеет значение true.
Сделайте изменения в текстовых полях и затем нажмите кнопку Сохранить.
Переместитесь на любую другую запись, а затем вернитесь к измененной и убедитесь, что сделанные изменения действительно занесены в базу данных.
5.5. Создание Web-приложения с доступом
к данным через компонент пользователя
В этом разделе мы создадим Web-приложение для покупки книг on-line. Затем встроим в него бизнес-компонент, который подсчитает налог на добавленную стоимость (НДС) на сделанную покупку. При этом элементы доступа к данным будут встроены в компонент, созданный специально для этих целей. Для получения необходимой информации элементы Web-формы будут обращаться к данному компоненту.
Наше Web-приложение предоставит пользователям интерфейс доступа к таблицам базы данных через Интернет. На Web-форме будут размещены объекты DataSet, DataGrid и DataView, через которые МОЖНО получить доступ к таблице базы данных. Также будет использован компонент, обеспечивающий соединение с базой данных.
Создание Web-формы
Для создания Web-формы выполните следующие действия.
В меню File выберите пункт New, после чего щелкните мышью на элементе Project.
Откроется диалоговое окно New Project.
В области Project Type выберите Visual Basic Projects или Visual C# Projects, а под надписью Templates выберите ASP.NET Web Application.
Назовите проект MyWebForm, оставьте заданный по умолчанию Web- сервер или введите имя сервера в поле Location.
Нажмите кнопку ОК.
Соответствующий мастер создаст необходимые для проекта файлы, включая следующие:
WebForm1. aspx — содержит визуальные компоненты Web-формы;
WebForm1.aspx.cs ИЛИ WebForm1.aspx.vb— файл С программным кодом, который содержит код для обработки событий и других программируемых функций. Чтобы увидеть этот файл в Solution Explorer, нажмите значок Show All Files и затем разверните узел WebForm1.aspx.
Примечание
Если отсутствует окно Solution Explorer, то откройте меню View и выберите там пункт Solution Explorer.
Для добавления компонента, обеспечивающего доступ к данным, выполните следующие действия.
В окне Solution Explorer нажмите правую кнопку на имени проекта.
В контекстном меню выберите Add, после чего нажмите на Add Component.
Появится диалоговое окно Add New Item и элемент Component Class, расположенный в правой области окна, будет выбран по умолчанию (рис. 5.36).
Рис. 5.36, Создание компонента в окне Add New Item
Примечание
Если вы используете Visual Basic, то дополнительный элемент с именем Module будет присутствовать в правой области окна.
Оставьте заданное по умолчанию имя Component1 и нажмите Open.
Если вы не изменяли имя компонента, то будет создан новый файл в вашем проекте с именем Component1.cs или Component1.vb в зависимости от выбранного языка программирования. Откроется вкладка Component Designer, на которой представляется возможность работы с созданным файлом.
Создание и конфигурирование элементов доступа к данным
В примере данного раздела мы будем использовать набор данных DataSet для того, чтобы поместить информацию из базы данных на HTML- страницу, передаваемую клиенту.
Для добавления и конфигурирования элементов доступа к источнику данных выполните следующие действия.
В меню View выберите пункт Toolbox.
Из вкладки Data окна Toolbox, перетащите элемент sqlDataAdapter в окно Component Designer (рис. 5.37).
ToolboxЧа X
Data
^ Pointer @1 DataSet ^ OleDbDataAdapter 8^ OleDbConnectlon Ф OleDbCommand ^ SqlDataAdapter Й8 SqlConnection '^ SqlCommand §7 DataView
Рис. 5.37. Элемент sqlDataAdapter в окне Toolbox
появится окно мастера конфигурации объекта DataAdapter.
Нажмите кнопку Next для перехода к следующей странице мастера Choose Your Data Connection, на ней установите переключатель New Connection, если вы еще не создавали соединение с базой данных Pubs, или сошлитесь на созданное ранее соединение.
Если вы выбрали New Connection, то откроется диалоговое окно Свойства связи с данными (Data Link Properties). Если же вы сослались на созданное ранее соединение, то пропустите шаг 4.I /
На вкладке Connection диалогового окна Data Link Properties выполните следующее:
введите имя сервера, на котором расположена база данных Pubs;
введите информацию, необходимую для подключения к серверу;
выберите базу данных Pubs из списка доступных баз;
проверьте подключение к базе, нажав кнопку Test Connection;
щелкните кнопку ОК для завершения работы мастера.
Имя объекта связи с базой данных (объекта Connection) появится в раскрывающемся списке.
Примечание
Если вы не знаете имя пользователя и пароль для доступа к базе данных Pubs SQL-сервера, то обратитесь к администратору сети или базы данных.
Нажмите кнопку Next для перехода к следующей странице — Choose a Query Type.
Установите переключатель Use SQL statements и нажмите кнопку Next.
На появившейся странице Generate the SQL Statements нажмите кнопку Query Builder.
В списке Tables диалогового окна Add Table отметьте таблицу titles, нажмите кнопку Add, а затем — Close.
В результате этого таблица titles будет добавлена к SQL-запросу.
В диалоговом окне Query Builder отметьте следующие поля: title_id, title, price, notes и pubdate, затем нажмите кнопку ОК для создания SQL-запроса и возврата на страницу мастера Data Adapter Configuration Wizard (рис. 5.38).
Рис. 5.38. Создание запроса в окне Query Builder
10 Зак 87.3
На странице Generate the SQL Statements будет показан сформированный SQL-запрос.
Нажмите кнопку Finish, чтобы выйтииз мастера DataAdapter
Configuration Wizard. При этом в окно Component Designer будут добавлены следующие объекты:
SqlDataAdapter1
SqlConnection1
В качестве альтернативы можно создать объекты sqlDataAdapter1 и SqlConnectionl, используя окно Server Explorer. Для этого нужно развернуть дерево серверов SQL Servers, найти на нем нужный сервер, базу данных Pubs и таблицу titles. Далее нужно развернуть таблицу titles, выделить нужные столбцы и перетащить их на окно Component Designer.
Вы можете просмотреть сгенерированный код в процедуре InitializeComponent файла Component1.cs или в подпрограмме initializeComponent файла component1.vb. Сделать это можно, переключившись в режим просмотра программного кода, щелкнув правой кнопкой мыши на файле Component1.cs или component1.vb в Solution Explorer и выбрав в контекстном меню пункт View Code.
П. Сохраните проект, выбрав пункт Save All в меню File.
Созданиенабораданных
Для создания и заполнения набора данных выполните следующие действия.
Если Component Designer невидим, то перейдите в него двойным щелчком на файле component1.cs (или component1.vb) в Solution Explorer.
В меню Data выберите пункт Generate DataSet.
Откроется диалоговое окно Generate DataSet.
Установите переключатель по положение New. В соответствующем текстовом поле введите имя набора данных — myDataSet (рис. 5.39).
Убедитесь,чтосброшенфлажокAddthisdataset tothedesigner и нажми
те кнопку ОК.
Файл myDataSet.xsd появится в окне Solution Explorer.
Вы можете рассмотреть XML-схему и код, которые описывают объект myDataSet, дважды щелкнув мышью на myDataSet.xsd в Solution Explorer. Обратите внимание, что закладки DataSet и XML расположены в левом нижнем углу XML Designer (рис. 5.40).
Рис. 5.39. Создание набора данных в окне Generate DataSet
stilt >\ICO WebFoml an.1. ' Cvi(-ur. /14, [IS:. myDetaSetxsd* |
deities м**юаа55|*""*
Yf"ttiejdstring^
Гtitlestring
Epricedecimal
Lnotesstring—
EpubdatedateTime* |
Рис. 5.40. Представление таблицы в окне XML Designer
Связывание объекта DataGrid
с набором данных
В данном разделе мы добавим набор данных к Web-форме, заполним его данными и свяжем с объектом отображения информации DataGrid.
Для добавления набора данных к форме выполните следующие действия.
В окне Solution Explorer дважды щелкните на файле WebForm1.aspx для переключения на Web-форму.
В меню View выберите Toolbox.
Перетащите элемент DataSet из вкладки Data окна Toolbox на Web- форму.
Откроется диалоговое окно Add Dataset.
Переведите переключатель в положение Typed dataset (типизированный набор данных) .
Выберите имя набора данных MyWebForm.myDataSet из выпадающего списка и нажмите кнопку ОК (рис. 5.41).
Рис. 5.41. Формирование набора данных в окне Add Dataset
В результате этих действий будет добавлен набор данных с именем myDataSet1 К Web-форме.
Для заполнения данными объекта DataSet выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на элементе Component1.cs (или Component1.vb) и выберите из выпадающего меню пункт View Code.
Добавьте следующий код к классу component1 (листинг 5.8).
ЛИСТИНГ 5.8
' Visual Basic
Public Class Component1
Inherits System.ComponentModel.Component
' Добавленный код
Public Sub FillDataSet(ByVal dSet As myDataSet)
sqlDataAdapter1.Fill(dSet)
End Sub
' Конец добавленного кода
End Class
// C#
public class Component1 : System.ComponentModel.Component {
// Добавленный код
public void FillDataSet(myDataSet dSet)
{
sqlDataAdapter1.Fill(dSet) ;
}
//Конец добавленного кода
}
Переключитесь в режим работы с программным кодом Web-формы, щелкнув правой кнопкой мыши на файле WebForm1.aspx в Solution Explorer и выберите в контекстном меню пункт View Code.
Откроется программный код, связанный с файлом WebForm1.aspx.cs (или WebForm1.aspx.vb).
Объявите экземпляр класса на уровне webForm1, как показано в листинге 5.9.
^H.^.t.«.t.........f...«..www-w.ww..,,......... ГЛУ.Т—”.—ГЛ ^.^w..~w-ew~.wwew.*—we» - w..w,.,....-. ....w ........^
Листинг5.9
iлл::'.;.„„„„^.«...^.l^j^^...,,^m:'w~w^*^.~ w—J-J. w*uL&'»J
' Visual Basic
Public Class WebForm1
Inherits System.Web.UI.Page
' Добавьте строку
.Pr.o.tected myComponent As New Component1()
// C#
public class WebForm1 : System.Web.UI.Page
I
// Добавьте строку
protected Component1 myComponent=new Component1();
Измените обработчик события загрузки страницы Page_Load (листинг 5.10).
ft -’:
Листинг 5.10
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, Ъ
ByVal e As System.EventArgs) Handles MyBase.Load
' Добавленный код
If Not IsPostBack Then
MyComponent,FillDataSet(myDataSet1)
End If
' Конец добавленного кода
End Sub
// C#
private void Page_Load (object sender, System.EventArgs e)
{
// Добавленный код
if (! IsPostBack)
{
myComponent.FillDataSet(myDataSet1);
}
//Конец добавленного кода
}
Примечание j
Фрагмент кода, включенный в блок условного оператора IF, работает только один раз при значении условия равного true, когда браузер первый раз получает Web-страницу.
Для добавления и конфигурирования объекта DataGrid выполните следующие действия.
В окне Solution Explorer дважды щелкните мышью на файле WebForm1.aspx для переключения в режим дизайнера Web-формы.
В меню View выберете Toolbox.
Перетащите на Web-форму элемент управления DataGrid из вкладки Web Forms окна Toolbox (рис. 5.42).
Surt P-w WebFormLespK* | 2«ixxk<<iU vbtDtr^^r C-^v'’ r t .'Л-* 'VetAarnil ■ v
I)'ColumnOColumn!Column2abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcI)'ColumnOColumn!Column2abcabcabcabcabcabcabcabcabcabcabcabcabcabcabc
I)'
ColumnO
Column!
Column2
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
I)'
ColumnO
Column!
Column2
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
abc
Рис. 5.42. Элемент управления DataGrid в окне дизайнера формы
Щелкните правой кнопкой мыши на элементе DataGrid и выберите Property Builder в контекстном меню.
Откроется диалоговое окно DataGrid1 Properties. На вкладке General установите свойству DataSource значение myDataSet1, свойству DataMember значение titles, свойству Data Key Field значение title_id (рис. 5.43).
Рис. 5.43. Окно формирования свойств элемента управления DataGridРис. 5.43. Окно формирования свойств элемента управления DataGrid
Рис. 5.43. Окно формирования свойств элемента управления DataGrid
Рис. 5.43. Окно формирования свойств элемента управления DataGrid
На вкладке Columns выполните следующее.
снимите флажок Create columns automatically at runtime.
Перелистайте вниз список Available Columns до узла Button Column.
Разверните узел Button Column, выберите пункт Select, затем нажмите кнопку со стрелкой вправо, расположенную между двумя списками, добавив тем самым ее в правый список (рис. 5.44).
Рис. 5.44. Добавление элемента Select к элементу управления DataGrid
Напечатайте "Наименование книги" в поле Header Text. Выберите в списках Sort Expression и Text Field значение title (рис. 5.45).
Рис. 5.45. Изменение свойств колонки, заполняемой командой SELECT
Добавьтестолбецpriceиздерева AvailableColumns,выбравегоина
жав кнопку со стрелкой вправо.
В элементе Header Text, представляющем заголовок колонки напечатайте "Цена";
В поле Data formatting expression напечатайте строку форматирования денежного формата "{0:С}" (рис. 5.46).
Рис, 5.46. Изменение свойств колонки price
Нажмите кнопку ОК.
Теперь DataGrid будет показывать только две колонки title и price из набора данных DataSet (рис. 5.47).
Немного измените внешний вид элемента DataGrid, для чего нажмите ссылку Auto Format в нижней части окна свойств Properties и выберите стиль Professional 3 (рис. 5.48).
Переключитесь в режим просмотра программного кода Web-формы. Свяжите данные со столбцами DataGrid, добавив вызов метода DataBind в обработчик события Page_Load. Программный код будет выглядеть следующим образом (листинг 5.11).
^ iii'.v?- Webform Laspx* | Component! t Hv । / '."omporertl ’b* | Webftuml >;p>. *4 ■
: :-8...:.::....::
;; Наименование книгиЦена
:: abco.oop.
abc0.10р.
. abc0,20p.
: abc0,30p.
:: abc0,40p.
Рис, 5.47. Элемент управления DataGrid после изменения свойств колонок
Рис. 5.48. Внешний вид элемента управления DataGrid после изменения стиля
Листинг 5.11
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object,4>
ByVal e As System.EventArgs) Handles MyBase.Load
If Not IsPostBack Then
myComponent.FillDataSet(myDataSet1)
DataGrid1.DataBind()' Добавьте эту строку
End If
End Sub
// C#
private void Page_Load{object sender.System.EventArgs e)
{
if (!IsPostBack)
{
myComponent.FillDataSet(myDataSet1);
DataGrid1.DataBind(); // Добавьте эту строку
}
}
Для тестирования приложения выполните следующие действия:
В меню Build выберите пункт Build Solution;
В меню Debug выберите пункт Start Without Debugging.
Созданное приложение отобразит информацию из базы данных на Web- форме в браузере. Столбец с названием книги содержит гиперссылку (рис. 5.49). В следующем разделе мы используем эту гиперссылку для отображения более детальной информации о каждой из книг.
♦г;!' По»* л Вид l*Dtic-Hlh- •> • ••- ж^гif
i। x jПоиск Избрало® V^f* ^диа
Адр» ^ http://loc*o$t/MyWebFofmAVebFofml.e$px"* ’ Я Переход 7?. пь^ *
Наименование книги[Цена
The Busy Executive's Database Guide19,99p
Cooking with Computers Surreptitious Balance Sheets ll,95p
You Can Combat Computer Stress)2,99p.
Straight Talk About Computers19,99p
Silicon Valley Gastronomic Treats15,99p
The Gourmet Microwave2,99p.
The Psychology of Computer Cooking19,99p.
But Is It User Friendly'?22,95p
*j Местная интрасеть
Рис. 5.49. Отображение данных в элементе DataGrid на этапе работы приложения
5.5. Фильтрация данных в Web-форме
Развивая пример, мы создадим дополнительную область, которая позволит просмотреть более полную информацию о книге, отображенной в текущей записи объекта DataGrid. Для этого мы используем объект DataView.
Для добавления объекта DataView к форме выполните следующие действия.
Переключите Web-форму в режим дизайнера.
В меню View выберите пункт Toolbox.
Перетащите на Web-форму элемент управления DataView из вкладки Data окна Toolbox (рис. 5.50).
Новый объект dataView1 будет добавлен к невидимой части Web- формы.
Выделите объект dataView1 и перейдите в окно Properties, выбрав пункт Properties Window в меню View.
Разверните узел Data и выделите свойство Table. Задайте имя таблицы, выбрав titles в раскрывающемся списке, как показано на рис. 5.51.
Рис, 5.50. Элемент управления DataView в окне Toolbox
Рис. 5.51. Связывание элемента DataView с таблицей данныхРис. 5.51. Связывание элемента DataView с таблицей данныхИМЯ myDataSet1.titles появляется рядом со свойством Table.
Рис. 5.51. Связывание элемента DataView с таблицей данных
Рис. 5.51. Связывание элемента DataView с таблицей данных
На следующем шаге добавим элементы управления Label, которые будут связаны с колонками объекта DataView.
Для добавления элементовуправления Label выполните следующиедействия.
Для полей title-id, title, price и pubdate, которые имеются в объекте DataSet, перетащите на Web-форму элемент управления Label из вкладки Web Forms окна Toolbox.
Поочередно выделите каждый элемент Label и свяжите их с полями набора данных в описанной ниже последовательности.
Перейдите в окно Properties выделенного элемента Label, выбрав Properties Window в меню View.
Нажмите кнопку в строке DataBindings (рис. 5.52).
Рис. 5.52. Свойство DataBindings в окне свойств элемента Label
Появится диалоговое окно Labeln DataBindings (где n — номер элемента Label).
Выберите свойство Text в дереве Bindable Properties, затем раскройте узел dataView1 в правой части окна и выделите нужный столбец (рис. 5.53).
Рис. 5.53. Диалоговое окно Label1 DataBindings
Выберите подходящий формат отображения данных из раскрывающегося списка Format. Например, вы можете использовать денежный формат Currency для поля price и один из доступных форматов даты для pubdate.
Нажмите кнопку ОК.
Добавьте текст для описания содержимого каждой созданной метки, созданной выше, используя для этого элементы HTML Label. Элементы HTML Label представляют собой обычные надписи, в которые можно вписать "Идентификатор книги", "Название книги", "Дата издания", "Цена". Чтобы выполнить эту процедуру откройте окно Toolbox и перетащите на Web-форму элементы управления Label из вкладки HTML. Разместите эти элементы на форме, затем введите текст (в данном примере необходимо создать четыре надписи).
Созданная Web-форма должна иметь вид как на рис. 5.54.
Рис. 5.54. Расположение элементов управления на Web-форме
•
На следующем шаге добавим программный код, чтобы изменять содержимое объекта dataView1 (фильтрация данных) при изменении активной строки В DataGrid.
Для фильтрации набора данных выполните следующие действия.
Дважды щелкните левой кнопкой мыши на объекте DataGrid1.
При этом будет создан шаблон обработчика события смены строки DataGrid1_SelectedIndexChanged И будет активизирована панель дизайнера для редактирования программного кода.
В обработчик события DataGrid1_SelectedIndexChanged добавьте код, позволяющий установить фильтр dataView1.RowFiдter так, чтобы была выбрана только одна строка из набора данных (листинг 5.12).
Г "гт™ -ттттт* •■■—■”—
Ё Листинг 5.12 -S™.™„
' Visual Basic
MyComponent.FillDataSet(myDataSet1)
Dim index As Integer
Dim key As String
index=DataGrid1.SelectedIndex
key=DataGrid1.DataKeys(index).ToString()
dataView1.RowFilter=DataGrid1.DataKeyField & "='" & key & "'"
// C#
myComponent.FillDataSet(myDataSet1);
int index=DataGrid1.Selectedlndex;
string key=DataGrid1,DataKeys[index].ToString();
dataView1.RowFilter=DataGrid1.DataKeyField+"='"+key+"'";
Здесь выполняются примерно те же действия, как и при задании условия выборки в предложении WHERE SQL-запроса для выбора одной строки таблицы. Сначала в переменную index заносится номер текущей строки объекта DataGrid1. Свойство DataKeys, которое было определено при создании объекта DataGrid, является по сути дела идентификатором строки (в данном примере ключевой колонкой объекта DataGrid является колонка title_id — она же является первичным ключом в таблице базы данных). В следующей строке кода строковой переменной key присваивается значение ключевой колонки объекта DataGrid. И наконец, объект dataView1 фильтруется по значению этого ключа (в данном объекте остается только одна запись).
СвяжитекаждуюметкуLabelсданными,вызываяметодDataBindэтих
Меток В обработчике события DataGrid1_SelectedIndexChanged. Это нужно сделать после того, как изменилось значение фильтра (листинг 5.13).
Листинг 5.13
' Visual Basic
Label1.DataBind()
Label2.DataBind()
Label3.DataBind()
Label4.DataBind()
// C#
Label1.DataBind();
Label2.DataBind();
Label3.DataBind();
Label4.DataBind();
Соберитезаново изапуститепроект. Когдавы будетев элементе
DataGridнажиматьна ссылку(наименованиекниги), тов текстовых
полях появится дополнительная информация о выбранной книге (рис.5.55).
Рис. 5,55. Внешний вид Web-формы на этапе работы приложения
Создание объекта с бизнес-логикой
В данном разделе мы создадим объект с бизнес-логикой, который реализован в виде класса на Visual Basic или С#. Этот класс будет содержать процедуру, которая осуществляет вычисление цены книги с учетом налога на добавленную стоимость (20%).
Создание объекта с бизнес-логикой на Visual Basic
Для создания объекта на Visual Basic выполните описанные ниже шаги.
В Solution Explorer щелкните правой кнопкой мыши на элементе MyWebForm.
В контекстном меню выберите Add, а затем нажмите Add Class.
Откроется диалоговое окно Add New Item.
В нем замените заданное по умолчанию имя класса с ciass1.vb на MypaymentRules.vb и нажмите кнопку Open (рис. 5.56).
Рис. 5.56. Создание класса а окне Add New Item
Будет создан класс MyPayment Rules.vb.
Есликодклассаеще не виден,тодваждыщелкнитенаименикласса
MyPaymentRules.vb в Solution Explorer и добавьте следующий код (листинг 5.14).
Листинг 5.14
' Visual Basic
Public Class MyPaymentRules
' Начало кода
Dim price As Double
Public Function Calc(ByVal price)
Return price+0.2*price
End Function
' Конец кода
End Class
Создание объекта с бизнес-логикой на С#
Для создания объекта на С# выполните описанные ниже шаги.
В Class View дважды щелкните на элементе MyWebForm.
В контекстном меню выберите Add, а затем нажмите Add Class.
Откроется диалоговое окно мастера С# Add Class Wizard.
В диалоговом окне задайте классу имяMyPaymentRules и нажмите кнопку Finish.
ВClassViewщелкнитеправойкнопкоймышинаэлементе
MyPaymentRules.
В контекстном меню выберите Add и затем нажмите Add Method.
Откроется диалоговое окно мастера С# Add Method Wizard.
В текстовом поле Method Name введите имя класса Calc.
В раскрывающихся списках выберите следующее:
Parameter type: double
Parameter name: price
Return type: double
Нажмите сначала кнопку Add и затем Finish.
Метод, приведенный в листинге 5.15, будет добавлен к классу MyPaymentRules,
Листинг 5.15
// с#
public double Calc(double price)
{
return 0;
}
Измените инструкцию return следующим образом:
return price+0.2*price;
Использование объекта с бизнес-логикой
В этом разделе на Web-форму мы добавим новый элемент Label, где будет отображена цена книги с учетом НДС.
Для обращения к объекту с бизнес-логикой выполните следующие действия.
ПеретащитенаWeb-формуэлементуправленияLabelизокна Toolboxс
вкладки WebForms (будет создана метка с именем Label5).
В этом элементе будет отображаться цена книги с учетом НДС.
Свяжите свойство Text элемента управления Label5 со столбцом price объекта DataView1.
При этом не нужно задавать определенный формат, мы укажем его в программном коде.
Перетащите на Web-форму элемент управление Label из окна Toolbox с вкладки HTML и расположите его рядом с Web-элементом Label5. Напечатайте в нем текст "Цена с НДС"
Откройте содержимое файла WebForm1.aspx.cs (или WebForm1.aspx.vb) и добавьте следующийкодвконцеобработчикасобытия
DataGrid_SelectedIndexChanged (листинг 5.16).
Листинг 5.16
' Visual Basic
' Объявление экземпляра класса Dim pr As New MyPaymentRules()
' Вызов процедуры Calc
Try
Dim price As decimal
price=myDataSet1.titles(index).price
Label5.Text=String.Format("{0:С}", pr.Calc(Convert.ToDouble(price)))
Catch
' Если значение price пустое Label1.Text="Цена не задана" Label5.Text="НДС не определен" End Try
// C#
// Объявление экземпляра класса
MyPaymentRules pr=new MyPaymentRules();
// Вызов процедуры Calc try
{
decimal price=myDataSet1.titles[index].price;
Label5.Text=String.Format("{0:C}",
pr.Calc(Convert.ToDouble(price))); }
catch
{
// Если значение price пустое Label1.Text=" Цена не задана"; Label5.Text=" НДС не определен";
}
Сохраните проект, соберите заново приложение и запустите его на выполнение.
Когда вы будете перемешаться по строкам элемента Grid, то в текстовых полях будет отображаться информация о книгах, включая цену с учетом НДС(рис.5.57).
Рис. 5.57. Внешний вид Web-формы на этапе работы приложения
В следующей главе мы продолжим знакомство с созданием Web-форм. И начнем мы с создания модуля проверки правильности введенной информации.
ГЛАВА 6
Дополнительные возможности ASP-приложений
В этой главе будет продолжено рассмотрение создание страниц ASP.NET Web Form Page. В ней мы затронем вопросы, касающиеся удобства интерфейса пользователя на Web-страницах.
В данной главе будут рассмотрены проблемы:
Q проверки корректности вводимых данных на Web-формах;
Q использования серверного элемента управления DataGrid для просмотра и редактирования данных;
Q создания постраничного доступа к данным с использованием элемента управления DataGrid;
Q добавления, удаления и обновления записей в базе данных из Web- форм.
Проверка корректности вводимых данных на Web-формах
Как и на любой форме, где пользователь вводит какую-либо информацию, на Web-форме тоже требуется проверка корректности вводимых данных (использование только допустимых символов, правильный формат, соблюдение допустимого диапазона и т. д.). Чтобы упростить эту задачу, нужно использовать специальные элементы управления, предназначенные для контроля проверки правильности входной информации, созданные специально для Web-форм (validation controls). Элементы управления validation Controls позволяют реализовать проверку типов вводимых данных, диапа-
зонов чисел, устанавливать шаблоны вводимых значений и тому подобное простым заданием свойств этих элементов. Эти элементы сами выполняют необходимую проверку и дают возможность отобразить сведения об ошибках пользователей.
В первом разделе главы мы создадим простую Web-форму, которая обеспечивает возможность ввода регистрационных данных пользователя. Страница включает текстовые поля для ввода имени пользователя, даты рождения, пароля и повторения пароля. Мы добавим контроль проверки правильности данных, чтобы убедиться, что пользователи ввели значения во все поля и что они отформатированы правильно.
Чтобы реализовать данный пример, вы должны иметь права для создания и размещения ASP.NET приложений на компьютере, где установлен используемый Web-сервер.
Пример реализуется в несколько этапов:
Q создание базовой Web-формы, добавление элементов для ввода данных и меток, идентифицирующих эти элементы;
Q добавление элементов-контролей для проверки правильности введенной информации: имени пользователя, даты и идентичность паролей;
Q тестирование приложения.
На первом этапе необходимо создать форму, к которой позже будут добавлены соответствующие элементы управления.
Созданиебазовойформы
Для создания формы выполните следующие действия.
В меню File выберите подменю New и пункт Project.
В диалоговом окне New Project сделайте следующее:
в дереве Project Types выберите тип проекта Visual Basic Projects или Visual C# Projects;
в области Templates выберите ASP.NET Web Application;
в строке Location введите URL проекта, включающего http://, имя сервера, имя проекта (для IIS сервера версии 5.0 и выше при установленном пакете .NET Framework можно ввести http://localhost). Назовите приложение Web5.
Нажмите кнопку ОК для создания проекта и Web-формы.
Проверьте режим разметки страницы. Если страница находится не в режиме координатной сетки, то войдите в окно Properties и установите значение свойства pageLayout равным GridLayout.
Этот шаг не является обязательным, но он облегчит позиционирование элементов на форме.
Добавление элементов ввода данных
В примере раздела предполагается создание страницы для регистрации пользователей, и мы добавим элементы для ввода следующих параметров: адрес электронной почты, дата рождения, пароль (пароль вводится дважды).
Для добавления элементов управления выполните следующие действия.
ИзвкладкиWebFormsокнаToolboxперетащитенаформуэлементы,
приведенные в табл. 6.1, и задайте им соответствующие имена из столбца ID.
Таблица 6.1. Значения свойств элементов управления Web-формы
Элемент
Назначение
ID (имя-идентификатор)
TextBox
Ввод адреса электронной почты
txtName
TextBox
Ввод даты рождения
txtBirthdate
TextBox
Ввод пароля
txtPassword
TextBox
Повторения пароля
txtPasswordAgain
Button
Передача регистрационных данных
btnRegister
Присвойте свойству Text значение Регистрация
ПрисвойтесвойствуTextModeдвухполейдлявводапаролязначение
Password для того, чтобы в них при вводе данных отображались звездочки (рис. 6.1).
Рис. 6.1. Изменение свойства TextMode элемента управления TextBox
Добавьте надписи перед текстовыми полями, чтобы указать их функции, Если Web-форма находится в режиме сетки, нужно добавить элементы Label перед каждым текстовым полем и установить их свойство Text. Если страница находится в режиме потока, нужно просто напечатать текст перед каждым полем.
Измените шрифт, цвет, размер и размещение элементов на форме по вашему вкусу. В данном примере в верхней части формы добавлен элемент image, в который вставлен рисунок. Расположите элементы на форме в соответствии с рис. 6.2.
Start Psge WebForml.aspK I
Добро побаловать на сайт компании Sonlnteso
Адрес электронной почты : ;
Дата рождения
Пароль
Повторение пароля : ■ ::■в
Регистрация
Рис. 6.2. Расположение элементов управления на форме
Добавление контролен для проверки правильности данных
Теперь, когда форма создана, можно добавить элементы для проверки правильности вводимой информации. Необходимо вставить по одному элементу проверки для каждого правила, которое вы хотите реализовать. В целом к данной форме мы добавим семь контролен проверки правильности и отображения ошибок пользователей. Ниже приведены правила, которые они реализуют.
Q Заполнение полей. Необходимо проверить, что пользователи ввели значения во все четыре поля, соответственно понадобятся 4 контроля.
QФормат электронного адреса (name@domain.xxx).
Q Формат даты. Мы проверим, что введенная дата рождения допустима.
Q Соответствие паролей. Мы проверим идентичность паролей, введенных в два поля.
Проверка заполнения обязательных полей
Необходимо проверить, что пользователь ввел значения во все четыре текстовых поля.
Для проверки заполнения всех полей выполните следующие действия.
ИзвкладкиWebFormsокна Toolboxперетащитенаформуэлемент
RequiredFieldValidator, поместите его рядом с текстовым полем txtName.
Выделите только что созданный элемент управления, перейдите в окно свойств Properties и установите значения для свойства, указанных в табл. 6.2,
Таблица 6.2. Значения свойств элементов управления Web-формы
Свойство
Значение
Описание
ControlToValidate
TxtName
Свойство указывает, что данный контроль будет проверять содержание поля с име- немtxtName
Text
*
Текст, который будет отображен на месте расположения контроля, если в проверяемом элементе будет найдена ошибка
ErrorMessage
Введите адрес электронной
Текст сообщения, выводимого контролем в случае ошибки пользователя
почты
Если есть необходимость, установите шрифт, цвет и другие свойства форматирования — эти свойства затрагивают вид сообщения об ошибки.
Повторитешаги1-3длядругихтрехтекстовыхполей, создавещетри
контроля RequiredFieldValidation; их свойства сведены в табл. 6.3.
Таблица 6.3. Значения параметров элементов управления Web- формы
Элемент управления
Значения параметров элементов управления
RequiredFieldValidator2
ControlToValidate: txtBirthdate
Text: *
ErrorMessage: Введите дату рождения
Таблица 6.3. (окончание)
Элемент управления
Значения параметров элементов управления
RequiredFieldValidator3
ControlToValidate: txtPassword
Text: *
ErrorMessage: Введите пароль
RequiredFieldValidator4
ControlToValidate:txtPasswordAgain
Text: *
ErrorMessage: Повторите пароль
Проверка формата текста
В разбираемом примере мы в качестве имени пользователя будем использовать адрес его электронной почты (в формате name@domain.xxx).
Для проверки корректности ввода имени будет использован элемент RegularExpressionValidator, в котором будет содержаться правильный формат электронного адреса в виде регулярного выражения. В свойствах этого элемента можно сделать выбор из списка заранее определенных регулярных выражений для адреса электронной почты, номера телефона, почтового индекса и пр.
Когда новый элемент проверки правильности вводимого текста будет добавлен, одно поле будет иметь два контроля, и его содержание будет подвергаться двум проверкам. Если имеется множественная проверка для одного поля и необходимо отобразить один и тот же текст ошибки (свойство Text), независимо от того, какая проверка дала ошибку, то нужно задать значение Dynamic для свойства Display элемента контроля правильности ввода.
Для проверки формата электронного адреса, введенного пользователем, выполните следующие действия.
Из вкладки Web Forms окна Toolbox перетащите на форму элемент управленияRegularExpressionValidator и расположите его рядом с
текстовым полем txtName.
Выделите элемент управления проверки правильности данных, перейдите в окно свойств Properties и установите значения свойства согласно данным табл. 6.4.
Таблица 6.4. Свойства элементов управления Web-формы
Свойство
Значение
ControlToValidate
TxtName
*
Text
Таблица 6,4. (окончание)
Свойство
Значение
ErrorMessage
Имя должно быть в формате name@domain.xxx
ValidationExpression
В списке выберите Internet E-mail Address
Проверка формата даты
Теперь настал черед убедиться, что пользователь ввел допустимую дату в поле Дата рождения. Значение этого поля будет проверяться на соответствие типа данных и на превышение минимально допустимой даты. Для задания проверки поля с датой выполните описанные ниже действия.
1. Из вкладки Web CompareValidator txtBirthdate.
Forms окна Toolbox перетащите на форму элемент и расположите его рядом с текстовым полем
2. Выделите данный
элемент управления, перейдите в окно свойств
Properties и установите значения его свойств согласно табл. 6.5.
Таблица 6.5. Значения свойств элементов управления Web-формы
Свойство
Значение
ControlToValidate
txtBirthdate
Text
*
ErrorMessage
Введенные данные не являются допустимой датой
ValueToCompare
01/01/1900
(или любая другая минимальная дата)
Operator
Greater Than
Type
Date
Display
Dynamic
Проверка соответствия паролей
Как правило, на формах регистрации пароль вводится дважды, чтобы убедится, что пользователь при вводе не сделал ошибки.
Из вкладкиWebFormsокнаToolboxперетащитенаформуэлемент
CompareValidator и расположите его рядом с текстовым полем txtPasswordAgain.
Выделите данный элемент управления проверки правильности данных, перейдите в окно Properties и установите значения свойств, согласно табл. 6.6.
Таблица 6.6. Значения свойств элементов управления Web-формы
Свойство
Значение
ControlToValidate
txtPasswordAgain
Text
*
ErrorMessage
Пароли не идентичны
ControlToCompare
txtPassword
Operator
Equal
Display
Dynamic
Отображение ошибок при проверке правильности данных
Итак, мы сконфигурировали элементы проверки правильности данных так, чтобы они отображали красную звездочку рядом с текстовым полем, содержащим ошибку. Однако для пользователя этой информации может быть не достаточно, он может не понять суть ошибки и как ее устранить.
Чтобы отобразить более подробную информацию об ошибках ввода данных, можно использовать элемент управления ValidationSummary. Этот элемент отображает значение свойство ErrorMessage любого элемента управления проверки правильности данных, который обнаружил ошибку. Если найдено несколько ошибок, то ValidationSummary сможет отобразить их список.
Для отображения ошибок при проверке правильности данных выполните следующие действия.
Из вкладки Web Forms окна Toolbox перетащите на форму элемент ValidationSummary. Расположите его там, где на форме есть место для отображения нескольких строк текста.
Установите формат отображения ошибок, выбрав одну из пунктов свойства DisplayMode.
Установите желаемые свойства Font и ForeColor для текста отображения ошибок.
Итак, контроль возможных ошибок пользователя определен. Полученная форма должна иметь вид, изображенный на рис. 6.3.
Рис. 6.3. Внешний вид Web-формы в окне дизайнера проекта
Теперь можно проверить, как работают элементы проверки данных.
Тестирование приложения
Для проверки Web-формы запустим приложение и будем сознательно вводить в текстовые поля информацию с ошибками, чтобы видеть эффект работы элементов проверки правильности данных.
В Solution Explorer щелкните правой кнопкой мыши на имени формы и выберите в контекстном меню пункт Build и Browse.
Когда страница будет отображена на экране, вводите различные значения в текстовые поля (допустимые и недопустимые).
Каждый раз при вводе неверных данных будет появляться звездочка рядом с полем, содержащим ошибку.
Нажмите кнопку Регистрация.
Если есть ошибочные данные, то будут отображены соответствующие сообщения об ошибках на месте расположения элемента управления ValidationSummary (рис. 6.4).
Рис, 6.4. Результаты проверки ошибок пользователя на этапе работы приложения
В примере данного раздела были рассмотрены основные понятия проверки правильности данных на Web-формах. Можно делать и более детальную проверку данных непосредственно в программном коде.
а В частности можно проверить, что пользователь ввел дату рождения более позднюю, чем текущая. Для этого нужно для поля Дата рождения добавить второй элемент контроля CompareValidator, установив его свойству Operator значение LessThan, и сравнить введенную дату с сегодняшней.
Присваивать свойствам значения можно и в программном коде страницы. Синтаксис кода мог бы выглядеть следующим образом:
<asp:CompareValidator id=c1
ValueToCompare='<%# DateTme.Today.ToShortDateString() %>'
ControlToVaiidate="txtBirthDate" Operator="LessThan" Typs="Date+" Text="*" runat="server" />
Примечание
। Вы должны вызвать метод DataBind элемента контроля данных для формирования значения поверочного выражения.
• Можно проверить количество символов в пароле, чтобы убедиться, что в нем содержится минимально допустимое число знаков. Это МОЖНО сделать С ПОМОЩЬЮ Элемента RegularExpressionValidator. Для определения минимально допустимого числа символов (в данном случае — пяти) можно использовать следующее выражение: ^[\w] {5, }
« Каждый элемент проверки правильности данных имеет признак (флаг) наличия ошибки, который можно использовать в программном коде. Анализ состояния этого признака позволяет управлять дальнейшим ходом работы приложения (завершить работу модуля, продолжить работу модуля, автоматически исправить некоторые ошибки и т. п.).
Использование серверного элемента управления DataGrid для просмотра и редактирования данных
Как было отмечено в предыдущем разделе, в Web-формах обеспечивается одностороннее связывание элементов управления с источником данных. Такая архитектура позволяет достаточно просто реализовать отображения информации на стороне клиента, однако при этом не поддерживается автоматическое обновление информации на сервере. В предыдущих разделах для обновления информации на сервере использовался объект DataCommand, который выполняет обновление информации непосредственно на сервере. В данном примере мы реализуем другой способ обновления источника данных. Здесь будет использоваться набор данных, а все изменения, сделанные пользователем, будут переданы источнику данных через соответствующий метод адаптера данных. Кроме того, мы задействуем более мощный и гибкий элемент управления DataGrid. Мы посмотрим, как можно использовать DataGrid для отображения данных, для редактирования информации и для передачи измененных записей назад источнику данных.
Для реализации этого примера необходимо:
Q иметь доступ к тестовой базе Northwind, поставляемой с SQL-сервером;
а иметь права на создание и размещение ASP.NET-приложений на используемом Web-сервере.
Пример выполняется в несколько этапов:
Q создание проекта и Web-формы;
Q добавление необходимых компонентов доступа к данным;
Q добавление элемента управления DataGrid для отображения данных;
Q добавление программного кода для получения записей из базы данных и связывание их с элементом DataGrid;
Q конфигурирование DataGrid для реализации возможности редактирования данных;
Q добавление программного кода для передачи обновлений источнику данных.
Создание проекта и формы
На первом этапе мы создадим Web-приложение и Web-форму. Для создания Web-формы выполните обычные действия.
В меню File выберите элемент New и пункт Project.
В открывшемся диалоговом окне New Project выполните следующее:
в области Project Types выберите тип проекта Visual Basic Projects или Visual C# Projects;
в области Templates выберите тип приложения ASP.NET Web Application;
в поле Location введите полный URL для вашего приложения. Он должен включать http://, имя сервера и имя проекта. У вас должен быть установлен Web-сервер (1IS) версии 5.0 и выше, а также .NET Framework. Если Web-сервер (IIS) установлен на вашем компьютере, то в качестве имени сервера можно задать http://localhost. Задайте проекту имя Web6.
Когда вы нажмете кнопку ОК, го новый Web-проект будет создан и размещен в корневом каталоге Web-сервера, который был задан в поле Location. Кроме того, будет создана страница Web-формы с именем WebForm1.aspx, которая будет отображена в окне Web Forms Designer.
Созданиеиконфигурированиенабораданных
В Web-формах имеется несколько способов доступа к данным. Первый способ — использовать набор данных, который является своеобразной копией фрагмента базы данных в оперативной памяти. Второй — работать непосредственно с таблицами базы данных, используя команды данных. Если в
приложении требуется модифицировать данные, то в этом случае предпочтительней задействовать набор данных.
Для создания набора данных нужно выполнить описанные ниже шаги.
Создать адаптер данных, используя соответствующего мастера. Адаптер содержит SQL-запросы, которые позволяют как выбрать информацию из базы данных, так и вернуть в нее изменения. Мастер позволяет сформировать все необходимые SQL-запросы, а также создать соединение с базой данных.
Сгенерировать схему набора данных. В этом процессе Visual Studio создает новый класс набора данных, основанный на структуре таблиц, к которым делается обращение в базе данных; кроме того, экземпляр класса добавляется к форме.
Создание и конфигурирование объектов
DataConnection и DataAdapter
Итак, приступим к процессу создания адаптера данных и объекта, обеспечивающего соединение с базой данных. Для этого необходимо выполнить следующие действия.
Из вкладки Data окна Toolbox перетащите на форму объект SqlDataAdapter.
Примечание
Если вы будете работать не с SQL-сервером, то используете адаптер данных OleDbDataAdapter, который обеспечивает доступ к любому OLE DB-совместимому источнику данных.
Появится окно мастера Data Adapter Configuration Wizard.
В данном мастере сделайте следующее:
на второй странице создайте или выберите соединение с базой данных Northwind SQL-сервера;
Примечание
Вы должны иметь соответствующие права доступа к SQL-серверу. Рекомендуется использовать средства Windows для идентификации пользователя при создании подключения к базе данных. В качестве альтернативы можно определить имя пользователя и пароль непосредственно в объекте Connection, однако это ставит под угрозу защиту информации на SQL-сервере.
на третьей странице укажите, что вы будете использовать SQL-запрос для обращения к базе данных;
на четвертой странице создайте следующий SQL-запрос:
SELECT CategoryID, CategoryName, Description FROM Categories
Для упрощения процесса формирования SQL-запроса, нажмите кнопку Query Builder, чтобы загрузить диалоговое окно построителя запросов (рис. 6.5).
Рис. 6.5. Создание запроса в окне Query Builder
Нажмите кнопку Finish.
Мастер создаст соединение с базой данных (SglConnection1 или sqlConnection1). Также будет создан адаптер данных (SqlDataAdapter1 или sqlDataAdapter1), который содержит тексты запросов, обеспечивающих доступ к информации в базе данных.
После того, как мастер завершит свою работу, необходимо сгенерировать набор данных.
Создание набора данных DataSet
В Visual Studio набор данных создается автоматически, на основе того запроса, который был определен при формировании адаптера данных. Набор данных — экземпляр класса DataSet, основанного на соответствующей схеме данных (xsd файл). Схема данных описывает элементы этого класса (таблица, столбцы и ограничения).
Для создания объекта DataSet выполните следующие действия.
В меню Data выберите пункт Generate DataSet.
Примечание j
Если пункт Generate DataSet не доступен, щелкните мышью в любом месте Web-формы (она должна иметь фокус).
Откроется диалоговое окно Generate Dataset.
Выберите элемент New и задайте имя набору данных dsCategories (рис. 6.6).
Убедитесь, что в списке под надписью Choose which table(s) to add to the dataset выбрана таблица categories.
Удостоверьтесь, что установлен флажок Add this dataset to the designer и затем нажмите кнопку ОК (рис. 6.6).
Рис. 6.6. Окно создания набора данных Generate Dataset
В результате будет сгенерирован типизированный класс набора данных dsCategories и схема, которая описывает структуру этого набора данных. Вы можете увидеть файл с описанием схемы dsCategories.xsd в окне Solution Explorer.
Примечание
В Solution Explorer нажмите на верхней панели кнопку Show All Files, чтобы увидеть сопутствующий файл схемы (vb или cs-файл), содержащий код, определяющий ваш новый класс набора данных.
Наконец, Visual Studio добавит экземпляр нового класса набора данных dsCategories1 К Web-форме.
На этом этапе мы сделали все, что необходимо для получения информации из базы данных.
Добавление элемента управления DataGrid для отображения данных
В данном разделе мы добавим один элемент управления DataGrid, который позволяет и отображать записи набора данных, и выполнять редактирование информации. При этом элемент DataGrid должен быть связан с набором данных.
Для добавления элемента DataGrid и связывания его с набором данных выполните следующие действия.
Если вы находитесь не в окне дизайнера Web-формы, то переключитесь в него (выбрав соответствующую закладку в верхней части окна).
ИзвкладкиWebFormsокнаToolboxперетащитенаформуэлемент
управления DataGrid.
Выделите мышью DataGrid, нажмите клавишу <F4> для перехода в окно Properties и в его нижней части нажмите Property Builder.
Появится диалоговое окно DataGrid1 Properties (рис. 6.7).
На вкладке General сделайте следующие установки (табл. 6.7).
Таблица 6.7. Значения свойств элементов управления Web-формы
Свойство
Значение
Описание
DataSource
DsCategories1
Связывает DataGrid с набором данных
DataMember
Categories
Указывает имя таблицы набора данных, которая должна быть отображена в DataGrid
Data key field
CategoryID
Определяет первичным ключ для записей элемента управления DataGrid. Это позволяет идентифицировать запись для возможности внесения в нее изменений
Нажмите кнопку ОК для закрытия диалогового окна DataGrid1 Properties.
Если есть желание, то можете изменить внешний вид сетки данных, изменив свойства Font, BackColor И Т, П.
Рис. 6.7. Диалоговое окно DataGrid1 Properties
Примечание
Самый простой путь изменения внешнего вида сетки данных состоит в том, чтобы нажать кнопку Auto Format в нижней части окна Properties и выбрать один из заданных стилей внешнего вида.
Выберем для данного примера стиль Professional 6,
Заполнение набора данных и отображение информации в DataGrid
Элемент DataGrid связан с набором данных, но сам набор данных не заполняется автоматически, эту процедуру нужно активизировать принудительно, вызывая метод Fill адаптера данных. И даже после того, как набор данных будет заполнен, элемент управление DataGrid останется пустым, он
не отображает поступившие данные автоматически, нужно заставить его сделать это в программном коде.
Для заполнения набора данных и отображения информации в DataGrid выполните следующие действия.
Дважды щелкните на Web-форме, чтобы перейти в редактор кода.
В обработчике события Page_Load вызовите метод Fin адаптера данных, передав ему в качестве параметра набор данных, который необходимо заполнить (листинг 6.1).
Листинг 6.1
' Visual Basic
SqlDataAdapter1.Fill(DsCategories1)
//C#
sqlDataAdapter1.Fill(dsCategories1) ;
Вызовите метод DataBind элемента управления DataGrid для явного связывания этого элемента управления с набором данных — DataGrid1.DataBind. Эту процедуру не нужно делать каждый раз, когда страница отправляется на сервер и возвращается обратно (в противном случае будут утеряны все изменения данных, сделанные пользователем). Но явное связывание необходимо делать обязательно в следующих случаях:
при первой загрузки Web-формы;
когда изменился набор данных.
При первой загрузке Web-формы нужно сделать проверку ее свойства IsPostBack. Эта проверка делается в обработчике события Page_Load. Программный код обработчика события загрузки выглядит следующим образом (листинг 6.2).
Листинг 6.2
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, ByVal a AsSys
tem. EventArgs) Handles MyBase.Load
'Добавленный код
SqlDataAdapter1.Fill(DsCategories1)
If Not IsPostBack Then
DataGrid1.DataBind()
End If
End Sub
// C#
private void Page_Load(object sender, System.EventArgs e}
{
// Добавленный код
SqlDataAdapter1.Fill(dsCategories1);
if (!IsPostBack)
{
DataGrid1.DataBind();
}
}
Можно скомпилировать приложение и выполнить его. Данные будут отображены в элементе управления DataGrid, однако их пока невозможно редактировать. Давайте реализуем эту возможность.
Добавление возможности редактирования данных
Итак, мы сделали все для того, чтобы отобразить содержимое таблицы базы данных в элементе управления DataGrid. Однако любая попытка отредактировать данные закончится неудачей. Чтобы обеспечить возможность редактирования данных нужно добавить кнопку Edit к каждой строке сетки данных. Когда пользователь нажмет эту кнопку, DataGrid перейдет в режим редактирования строки. При этом в редактируемой строке появятся текстовые поля для редактирования колонок. Когда строка перейдет в режим редактирования, то кнопка Edit будет заменена двумя другими кнопками (Update и Cancel).
Для того чтобы отобразить эти кнопки, необходимо добавить их к элементу управления DataGrid. Для придания функциональности кнопкам Edit, Cancel и Update необходимо добавить обработчики событий, в которых реализовать следующие функции:
Q кнопка Edit — переводит строку в режим редактирования;
Q кнопка cancel — возвращает строку к режиму визуального отображения информации, не внося изменений ни в сетку, ни в базу данных;
Q кнопка update — выполняет обновление базы данных (на основе информации текущей строки).
Для добавления возможности редактирования данных в DataGrid выполните следующие действия.
Выделите элемент управление DataGrid, нажмите клавишу <F4>, чтобы отобразить окно свойств Properties. Затем нажмите Properties Builder в нижней части этого окна.
Появится диалоговое окно DataGrid1 Properties. Перейдите на вкладку Columns (рис. 6.8).
Рис. 6.8. Вкладка формирования свойств колонок элемента DataGridРис. 6.8. Вкладка формирования свойств колонок элемента DataGrid
Рис. 6.8. Вкладка формирования свойств колонок элемента DataGrid
Рис. 6.8. Вкладка формирования свойств колонок элемента DataGrid
Selected cokmns:Selected cokmns:7 Edit, Update, Cancel7 Edit, Update, Cancel♦♦
Selected cokmns:
Selected cokmns:
7 Edit, Update, Cancel
7 Edit, Update, Cancel
♦
♦
Пролистайте вниз список Column list до появления строки Available columns и откройте узел Button Column.
Выберите строку Edit, Update, Cancel и нажмите кнопку >, чтобы добавить эти кнопки в список Selected columns (рис. 6.9).
Column kt
AvadaWe columns
• 7 Button Column
7 Select
7 Eck, Update, Cane
71 Delete
Рис. 6.9. Добавление колонок Edit, Cancel, Update элемента управления DataGrid
Смените установленные по умолчанию надписи на кнопках Edit, Cancel, Update на Редактировать, Отменить, Обновить (рис. 6.10).
Edit Text:
Cancel text:
'Редактировать
{Отменить
Update text:
Button type:
{Обновить
|lx*8utton*|
Рис. 6.10. Смена наименований колонок Edit, Cancel, Update
Нажмите кнопку ОК.
В элементе управления DataGrid появится колонка с кнопками (в виде ссылок). Первоначально видна только кнопка Редактировать (кнопки Обновить и Отменить будут отсутствовать, см. рис. 6.11).
j-' •" i. Webf-ormLaspH* | • _-.' ■ : , ■■
1
Category!!)
CategoryName
Desciiplion
' Редактировать
0
abc
abc
Редактировать
1
abc
abc
Редактировать
2
abc
abc
Редактировать
3
abc
abc
Редактировать
4
abc
abc
Рис. 6.11. Внешний вид Web-формы после добавления колонки с кнопками
Теперь, когда имеется кнопка Edit, необходимо написать обработчики события ее нажатия, чтобы перевести строку в режим редактирования. Для этого нужно свойству EditItemIndex элемента управления DataGrid присвоить индекс той строки, которую нужно редактировать (нумерация строк начинается с нуля). Например, чтобы перевести в режим редактирования третью строку, нужно этому свойству присвоить значение 2, а чтобы вернуть строку в режим отображения данных- -1. После смены режима редактирования, необходимо повторно связать элемент управления DataGrid с источником данных.
В режим редактирования нужно перевести ту строку, в которой пользователь нажал кнопку Edit (текущая строка). Вы можете получить номер текущей строки из объекта обработчика события нажатия кнопки. В обработчике события имеется свойство Item, которое представляет всю строку DataGrid для модификации. Объект Item, в свою очередь, поддерживает набор различных свойств, включая и свойство Item.Itemindex, которое содержит индекс той строки, с которой в данный момент работает пользователь.
Для перевода строки в режим редактирования выполните следующие действия.
В Visual Basic:
щелкните правой кнопкой мыши в любом месте Web-формы и в контекстном меню выберите View Code, чтобы открыть редактор кода;
в левом раскрывающемся списке верхней части редактора кода выберите DataGrid1;
в правом раскрывающемся списке верхней части редактора кода выберите EditCommand.
В Visual C#:
в режиме дизайнера формы выделите DataGrid затем нажмите клавишу <F4>, чтобы открыть окно Properties;
нажмите кнопку Events в верхней части окна Properties;
дважды щелкните в строке EditCommand (или наберите текст DataGrid1_EditCoiranand).
Будет создан обработчик события DataGrid1_EditCommand.
Повторите Шаг 1 ДЛЯ события CancelCommand.
Будет создан Обработчик события DataGrid1_CancelCommand.
В обработчик события EditCommand добавьте следующий код (листинг 6.3).
' ■—^
Листинг 6.3
' Visual Basic
DataGrid1.EditItemIndex=e.Item.ItemIndex
DataGrid1.DataBind()
// C#
DataGrid1.EditItemIndex=e.Item.ItemIndex;
DataGrid1.DataBind();
В обработчик события CancelCommand добавьте следующий код (листинг 6.4).
«wm'/w.ituimHii •••»~~~~*^—“•,♦•••••••?•• •••••••••••••••.•'■•••••••^’•••♦^*''••■•••••• ••••••••••••••••••••••••••••■•••••••nTmwnwrw*»wv*vHwww,*«iwHiiwwi«o.u<«uw*ww<^~*WHiM«i*ww»«if„*
Листинг 6.4
' Visual Basic
DataGrid1.EditItemIndex=-l
DataGrid1.DataBind()
// с#
DataGrid1.EditltemIndex=-l;
DataGrid1.DataBind();
Предварительная проверка работы созданных элементов
Теперь мы имеем элемент управления DataGrid, который способен не только отображать записи из связанного набора данных, но и редактировать отдельные строки путем нажатия кнопки Edit в любой строке. Наш пример еще не закончен, но уже можно проверить, что возможность редактирования данных действительно существует.
Для тестирования возможности редактирования данных выполните следующие действия.
В Solution Explorer щелкните правой кнопкой мыши на Web-форме и выберите в контекстном меню пункт Build and Browse.
Проект будет откомпилирован и Web-форма появится в окне браузера. Если все шаги были сделаны правильно, то сетка будет заполнена данными, а в первом столбце будет расположена ссылка Редактировать (рис. 6.12).
I Cate gory ID CategoryName Description.
Редактировать
,Soft drinks, coffees, teas, beers,
1Beverages. ,
and ales
Редактировать
Sweet and savory sauces, 2Condimentsrelishes, spreads, and
Редактировать
seasonings
_~ _ .Desserts, candies, and sweet
3Confections,,
breads
Редактировать
4Dairy Products Cheeses
Рис. 6.12. Внешний вид Web-формы на этапе работы приложения.
Нажмите на ссылке Редактировать в любой строке.
После этого строка изменится следующим образом:
ссылка Редактировать будет заменена на две: Обновить и Отменить;
данные в строке будут отображены в элементах TextBox, их можно редактировать (рис. 6.13).
Il1
CategorylD | Category Name
(Description
Обновить Отменить
1
(Beverages
(Soft drinks, coffees, teas, Sweet and savory
Редактировать
2
Condiments
sauces, relishes, spreads, and seasonings
Редактировать
3
Confections
Desserts, candies, and sweet breads
Рис. 6.13. Строка элемента управления DataGrid, переведенная в режим редактирования
Нажмите кнопку Отменить.
Строка примет первоначальной вид.
Однако на данном этапе результаты редактирования не передаются источнику данных. В следующем разделе будет показано, как реализовать передачу обновленной записи в базу данных.
Редактирование DataSet и обновление базы данных
Для того чтобы из элемента управления DataGrid отправить к источнику данных все изменения, сделанные пользователем, необходимо написать дополнительный программный код — обработку события нажатия кнопки Update. Обновление данных осуществляется в два этапа. На первом этапе изменения из элемента DataGrid переносятся в набор данных. На втором этапе изменения из набора данных передаются в базу данных.
Когда строка DataGrid переходит в режим редактирования, в левом столбце появляется кнопка update. Когда пользователи нажимают эту кнопку, то генерируется событие UpdateCommand. В обработчик этого события и необходимо написать нужный программный код. Для создания обработчика события UpdateCommand выполните следующие действия.
В Visual Basic:
щелкните правой кнопкой мыши в любом месте Web-формы и в контекстном меню выберите View Code, чтобы открыть редактор кода;
в левом раскрывающемся списке верхней части редактора кода выберите DataGrid1;
в правом раскрывающемся списке верхней части редактора кода выберите UpdateCommand.
В Visual C#:
в режиме дизайнера фермы выделите DataGrid затем нажмите клавишу <F4>, чтобы открыть окно Properties;
нажмите кнопку Events в верхней части окна Properties;
дважды щелкните в строке UpdateCommand или наберите текст DataGrid1_UpdateCommand.
Будет создан обработчик события DataGrid1_UpdateCommand.
Последовательность шагов обновления данных из DataGrid
Для обновления информации в источнике данных нужно последовательно сделать следующие шаги.
Определить номер (индекс) той строки элемента управления DataGrid, в которую пользователь внес изменения. Получить первичный ключ (datakey) этой строки, чтобы однозначно идентифицировать измененную строку.
Получить измененные значения из идентифицированной строки DataGrid.
Используя значение первичного ключа (datakey), найти соответствующую строку в таблице набора данных и перенести в нее измененные значения из DataGrid. На этом шаге модифицируется набор данных, но эти изменения еще не переданы в базу данных.
Передать все изменения из набора данных в базу данных. Это выполняется с помощью SQL-запроса или хранимой процедуры, которые копируют изменения из набора данных в базу данных.
Обновите содержимое элемента управления DataGrid.
Для обновления базы данных из элемента управления DataGrid выполните следующие действия.
Идентифицируйте редактируемую строку DataGrid. Для этого нужно сначала получить номер измененной строки, для чего используется свойство ItemIndex объекта Item, сгенерированного событием Edit (е.Item.ItemIndex). Зная номер измененной строки, можно получить соответствующее значение первичного ключа строки (из коллекции DataKeys элемента управления DataGrid). В программном коде это реализуется следующим образом (листинг 6.5).
: -■- ”""■"•■—:,:1
I Листинг 6.5
' Visual Basic
Dim key As String=DataGrid1.DataKeys(e,Item.ItemIndex).ToString()
// с#
string key=DataGrid1.DataKeys[e.Item.ItemIndex] .ToString() ;
Получите измененные значений из редактируемой строки DataGrid. Для этого нужно:
в строке, которая была модифицирована (она передана в обработчик соответствующего события) перебрать все ячейки (их нумерация начинается с нуля). Доступ к ячейке можно получить, задав ее индекс в коллекции Cells. Например, к крайней левой ячейке в строке можно обратиться Cells(0);
для каждой ячейки получите доступ к ее коллекции controls;
для каждой ячейки получите значение из первого элемента коллекции controls (в нашем случае этим элементом будет текстовое поле TextBox, в котором содержится отредактированное пользователем значение). Присвойте значение из элемента TextBox ячейки строки DataGrid любой переменной с типом TextBox (предварительно объявите эту переменную в операторе Dim, например, Dim tab AS TextBox);
Запомните полученные значения в переменных текстового типа.
Листинг 6.6 показывает реализацию описанных выше шагов.
Листинг 6.6
' Visual Basic
Dim categoryName, categoryDescription As String
Dim tb As TextBox
tb=Type(e.Item.Cells(2).Controls(0), TextBox)
categoryName=tb.Text
tb=CType(e.Itera.Cells(3).Controls(0), TextBox) categoryDescription=tb.Text
// C#
string categoryname;
string categoryDescription;
TextBox tb;
tb=(TextBox) e.Item.Cells[2].Controls[0];
categoryName=tb.Text;
tb=(TextBox) e.Item.Cells[3].Controls[0];
categoryDescription=tb.Text
Найдите соответствующую строку в таблице набора данных. Типизированный набор данных dsCategories имеет специальный метод FindBy. В нашем примере метод будет иметь имя FindByCategoryID, он определит местонахождение измененной пользователем строки в таблице набора данных по значению первичного ключа и вернет ссылку на эту строку. Создайте переменную для типизированной строки данных и присвойте ей ссылку на измененную строку, полученную с помощью метода FindByCategoryID (ЛИСТИНГ 6.7).
Листинг 6.7
' Visual Basic
Dim r As dsCategories.CategoriesRow
r=DsCategories1.Categories.FindByCategoryID(key)
// C#
dsCategories.CategoriesRow r;
r=DsCategories1.Categories.FindByCategoryID(key);
Обновите строку в наборе данных, изменяя значения столбцов в строке на полученные на шаге 2 (листинг 6.8).
Листинг 6.8 .. ..^j
' Visual Basic
r.CategoryName=categoryName
r.Description=categoryDescription
// C#
r.CategoryName=categoryName;
r.Description=categoryDescription;
Передайте изменения из набора данных в базу данных, вызвав метод Update адаптера данных (листинг 6.9).
Листинг 6.9
' Visual Basic
SqlDataAdapter1.Update(DsCategories1)
// C#
SqlDataAdapter1.Update(DsCategories1);
Переключите редактируемую строку в DataGrid в обычный режим отображения информации (листинг 6.10).
Листинг 6.10
' Visual Basic
DataGrid1.EditItemIndex-1
// C#
DataGrid1.EditItemIndex=-l;
Обновите связь DataGrid с набором данных (листинг 6.11).
Листинг 6.11
' Visual Basic
DataGrid1.DataBind()
// C#
DataGrid1.DataBind();
Листинг 6.12Листинг 6.12Следующий программный код показывает все приведенные выше фрагменты обработчика события UpdateCommand (ЛИСТИНГ 6.12).
Листинг 6.12
Листинг 6.12
' Visual Basic
Private Sub DataGrid1_UpdateCommand(ByVal source As Object, ByVal e As^ System.Web.UI.WebControls.DataGridCommandEventArgs) Handles^ Data- Grid1.UpdateCommand
Dim CategoryName, categoryDescription As String
' Получение значения ключевого поля редактируемой строки
Dim key As String=DataGrid1.DataKeys(e.Item.ItemIndex).ToString
' Получение значений из элементов TextBox
' из колонок редактируемой строки
Dim tb As TextBox
tb=CType(e.Item.Cells(2).Controls(0), TextBox)
categoryName=tb.Text
tb=CType(e.Item.Cells(3).Controls(0), TextBox)
categoryDescription=tb.Text
' Поиск соответствующей строки в наборе данных
Dim r As dsCategories.CategoriesRow
r=DsCategories1.Categories.FindByCategoryID(key)
' Обновление строки в таблице DataSet
r.CategoryName=categoryName
r.Description=categoryDescription
' Обновление строки в базе данных SqlDataAdapter1.Update(DsCategories1)
' Перевод DataGrid в режим отображения информации
DataGrid1.EditItemIndex=-l
' Обновление DataGrid
DataGrid1.DataBind()
End Sub
// C#
private void DataGrid1_UpdateCommand(object source, ъ Sys
tem. Web.01.WebControls.DataGridCommandEveritArgs e)
{ string CategoryName, categoryDescription;
// Получение значения ключевого поля редактируемой строки
string key=DataGrid1.DataKeys[e.Item.IteinIndex].ToString();
// Получение значений из элементов TextBox (из колонок редактируемой^ строки)
TextBox tb;
tb=(TextBox)(e.Item.Cells[2].Controls[0]);
categoryName=tb.Text;
categoryDescription=tb.Text;
// Поиск соответствующей строки в наборе данных
dsCategories.CategoriesRow r;
r=dsCategories1.Categories,FindByCategoryID(int.Parse(key));
// Обновление строки в таблице DataSet
г.CategoryName=categoryName;
r.Description=categoryDescription;
// Обновление строки в базе данных
SqlDataAdapter1.Update(dsCategories1);
// Перевод DataGrid в режим отображения информации
DataGrid1.EditItemIndex=-l;
// Обновление DataGrid
DataGrid1,DataBind();
}
Тестирование приложения
Мы закончили работу над примером — теперь посмотрим, как работает наше приложение.
Для тестирования приложения выполните следующие шаги.
В Solution Explorer щелкните правой кнопкой мыши на Web-форме и выберите в контекстном меню Build and Browse.
Проект будет откомпилирован и Web-форма отобразится в окне браузера.
Нажмите ссылку Редактировать в любой строке и отредактируйте данные.
Нажмите ссылку Обновить.
В результате элемент управления DataGrid примет обычный вид, но в нем будут отражены все сделанные изменения. Если теперь заглянуть в таблицу базы данных (с помощью SQL-менеджера или анализатора запросов), то можно увидеть, что эти изменения присутствуют и там, то есть поставленная нами цель достигнута.
Усовершенствованиепримера
В реализованном примере мы использовали элемент управления DataGrid на Web-форме не только для просмотра, но и для редактирования данных. Для простоты изложения материала в примере были пропущены некоторые детали, которые обязательно должны присутствовать в реальных приложениях. Вкратце упомянем некоторые из них:
Q конфигурирование отдельных столбцов DataGrid;
Q разбиение DataGrid на страницы. В этом примере было отображено небольшое количество записей. Однако в реальных приложениях в наборе данных может присутствовать сотни и тысячи записей, которые удобнее разбить и отображать постранично.
Q Возможность удаления строк (добавление кнопки Delete и формирование программного кода удаление записей).
Попробуем усовершенствовать наше приложение, добавив к нему вышеприведенные функции.
Конфигурирование отдельных столбцов
Во всех примерах, приведенных ранее, мы не изменяли наименования столбцов. По умолчанию им присваивались имена соответствующих полей базы данных. Это не всегда удобно, так как конечным пользователям нужно показать более полную и понятную расшифровку содержимого колонок. Попробуем изменить наименования столбцов в элементе DataGrid.
Для переименования столбцов выполните следующие действия.
Перейдите в окно Properties элемента DataGrid.
Нажмите на ссылку Property Builder в нижней части окна Properties. После этого появится диалоговое окно DataGrid Properties.
Перейдите на вкладку Columns (рис. 6.14.).
Сбросьте флажок Create columns automatically at run time. Если этого не сделать, то при запуске приложения колонки будут продублированы. В левой части окна выделите нужные колонки и перенесите их в правую часть окна, нажав кнопку >. В правой части окна (Selected columns) поочередно выделяйте колонки и в текстовом поле Header text вводите тот текст, который вы желаете видеть в качестве названия колонки сетки данных. Нажмите кнопку ОК.
Запустите приложение. Вы увидите, что имена колонок изменились (рис. 6.15).
Рис. 6.14. Изменение наименований столбцов элемента управления DataGridРис. 6.14. Изменение наименований столбцов элемента управления DataGrid
Рис. 6.14. Изменение наименований столбцов элемента управления DataGrid
Рис. 6.14. Изменение наименований столбцов элемента управления DataGrid
v-.?M .-if ■; d-,p 4et wml jip- Browse - WebForm 1
КатегорияКатегория11мя'категории11мя'категорииОписание категорииОписание категории
Категория
Категория
11мя
'категории
11мя
'категории
Описание категории
Описание категории
and alesand alesSweet and savory sauces.relishes, spreads, and seasoningsSweet and savory sauces.relishes, spreads, and seasoningsРедактировать 1Beverages
and ales
and ales
Sweet and savory sauces.
relishes, spreads, and seasonings
Sweet and savory sauces.
relishes, spreads, and seasonings
Редактировать 2Condiments
Рис. 6.15. Измененные наименования колонок на этапе работы приложения
Разбиение DataGrid на страницы
Данные, полученные с сервера, не всегда помещаются на экране. В этом случае с правой стороны браузера появляется полоса прокрутки, и пользователь может просмотреть записи, не поместившиеся на экран. Однако так поступать не всегда удобно, поскольку в верхней части экрана могут располагаться различные элементы управления (текстовые поля, кнопки, пере-
ключатели и пр.), которые будут исчезать из поля зрения пользователя. В этом случае желательно разбить DataGrid на страницы и выдавать информацию порциями — постранично. Элемент управления DataGrid имеет встроенный механизм разбиения на страницы. Воспользуемся им.
Для разбиения элемента управления DataGrid на страницы выполните следующие действия.
Перейдите в окно Properties элемента DataGrid.
Нажмите на ссылку Property Builder в нижней части окна Properties. После этого появится диалоговое окно DataGrid Properties.
Перейдите на вкладку Paging (рис. 6.16).
Рис. 6.16. Вкладка разбиения элемента DataGrid на страницы
Установите флажок Allow paging. В свойстве Page size укажите то количество строк, которое будет отображено на экране (в нашем примере задано 5 строк). Задайте названия навигационных кнопок перемещения по страницам (например, Следующая и Предыдущая). Нажмите кнопку ОК.
Теперь нужно создать обработчик события нажатия навигационных кнопок. Для этого дополните приложение программным кодом, приведенным в листинге 6.13.
? Листинг 6.13
Private Sub DataGrid1_PageIndexChanged(ByVal source As Object, ъ
ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) ъ
Handles DataGrid1.PageIndexChanged
DataGrid1.CurrentPageIndex=e.NewPageIndex
DataGrid1.DataBind()
End Sub
private void DataGrid1_PageIndexChanged (objectAъ
source,System.Web.UI.WebControls. A DataGridPageChangedEventArgs e) {
DataGrid1.CurrentPageIndex= e.NewPageIndex;
DataGrid1.DataBind();
}
Запустите приложение. Нажимая мышью на навигационные кнопки, вы будете перемещаться по страницам элемента DataGrid (рис. 6.17).
1 —.
I Категория
। Имя категории
| Описание категории
Редактировать
6
Meat/Poultry
Prepared meats
Редактировать
7
Produce
Dried fruit and bean curd
Редактировать
8
Seafood
Seaweed and fish
<Предыдущая Следующая >
Рис. 6.17. Внешний вид разбитой на страницы Web-формы на этапе работы приложения
Это самый простой способ постраничного отображения данных, но он далеко не оптимален. Когда пользователь щелкает на навигационные кнопки, то весь набор данных создается заново. В результате, если обрабатываются большие массивы информации, то это приводит к увеличению времени перезагрузки страницы. Есть более оптимальные способы постраничной разбивки DataGrid, которые будут рассмотрены в разделе 6.3.
Кэширование набора данных
В приведенном выше примере, набор данных заполняется из базы данных каждый раз, когда страница отправляется на сервер и возвращается назад к пользователю. Такой режим работы с данными приводит к увеличению трафика и к загрузке SQL-сервера ненужной работой.
В качестве альтернативы можно сохранять набор данных после заполнения. Тогда вместо повторного считывания информация из базы данных можно делать обновление набора данных из этого "временного хранилища". Есть несколько способов сохранения набора данных: используя переменную сессии пользователя (на стороне сервера) или используя представление (на стороне клиента).
Например, если вы хотите сохранить набор данных с использованием переменной сессии пользователя, то в обработчик события Page_Load необходимо включить следующий код (листинг 6,14).
Листинг 6.14
' Visual Basic
If Not Page.IsPostBack Then
If Session("mydatset") Is Nothing Then
SqlDataAdapter!.Fill(dsCategories1)
Session("mydataset")=dsCategories1
Else
DsCategories1=CType(Session("mydatset"), dsCategories)
End If
DataGrid1.DataBind()
End If
// C#
if (! Page.IsPostBack)
{
if (Session["mydatset"]==null)
{
sqlDataAdapter1.Fill(dsCategories1);
Session["mydataset"]=dsCategories1;
}
else
{
dsCategories1=(dsCategories)Session["mydatset"];
}
DataGrid1.DataBind();
}
ПримечаниеПримечание
Примечание
Примечание
Если вы сохранили набор данных в сессии или в приложении, то при считывании его из временного хранилища необходимо привести его к тому типу набора данных, в который вы его считываете.
Не забывайте сохранять набор данных в сессии каждый раз, когда он был изменен (например, как это сделано в коде листинга 6.15).
Листинг 6.15
' Visual Basic
SqlDataAdapter1.Update(DsCategories1)
Session("mydataset")=DsCategories1
// C#
SqlDataAdapter1.Update(dsCategories1);
Session["mydataset"]=dsCateqories1;
В данном примере мы послали обновления базе данных, не проверив того, что другой пользователь тоже мог изменить эти же данные. Однако в реальных приложениях такую проверку нужно делать обязательно.
6.3. Создание постраничного доступа
к данным с использованием DataGrid
Обычно в Web-форму с сервера возвращается не одна, а несколько записей. Количество возвращенных записей может быть достаточно большим, и они не поместятся в области экрана. В этом случае желательно записи разбить на страницы и дать пользователю возможность листать эти страницы назад и вперед. Пример данного раздела иллюстрирует возможность разбивки информации, содержащейся в DataGrid на страницы.
Есть несколько способов создания постраничного вывода.
Q Использование встроенных возможностей элемента управления DataGrid. Однако, этот способ не очень эффективен, так как сервер возвращает из базы данных всю таблицу каждый раз, когда пользователь перемещается с одной страницы на другую страницу.
Q Кэширование набора данных. Вы можете создать набор данных и затем сохранить его (например, в переменной сеанса). Это избавляет от постоянного считывания таблицы из базы данных, но остается необходимость считывания таблицы из памяти сервера. Для небольших таблиц этот способ может быть достаточно эффективным.
QВыборкана страницуизбазыданныхтолькотех записей,которыев
данный момент необходимы пользователю. Данный способ устраняет недостатки двух предыдущих: по каналу связи передается только минимальное количество необходимых данных, не требуется сохранение данных в памяти сервера. Однако данный подход самый сложный в реализации.
Пример, который мы сейчас разберем, иллюстрирует последний метод.
Для реализации этого примера необходимо:
Q иметь доступ к тестовой базе Northwind, поставляемой с SQL-сервером;
Q иметь права на создание и размещение ASP.NET-приложений на Web- сервере.
Работа над примером разбита на несколько этапов:
Q создание Web-приложения и Web-формы;
Q добавление компонента доступа к данным;
I Q добавление элемента управления DataGrid;
Q добавление программного кода, обеспечивающего выборку необходимых записей, когда пользователи перемещаются с одной страницы на другую.
Создание проекта и формы
На первом этапе вы создадите Web-приложение и Web-форму, для чего выполните описанные ниже действия.
В меню File выберите пункт New и элемент Project.
В открывшемся диалоговом окне New Project выполните следующее:
в дереве Project Types выберите тип проекта Visual Basic Projects или Visual C# Projects;
в области Templates выберите тип приложения ASP.NET Web Application;
в поле Location введите полный адрес для вашего приложения. Он должен включать http://, имя сервера и имя проекта. У вас должен быть установлен Web-сервер (IIS) версии 5.0 и выше, а также .NET Framework. Если Web-сервер (IIS) установлен на вашем компьютере, то в качестве имени сервера можно задать http://localhost. Назовите проект Web7.
Когда вы нажмете кнопку ОК, то будет создан новый Web-проект, и он будет размещен в корневом каталоге Web-сервера, который был задан выше. Кроме того, будет создана страница Web-формы с именем WebForm1.aspx, которая будет отображена в окне Web Forms Designer.
Добавление компонентовдоступа кданным
Для реализации примера этого раздела нам будут необходимы два похожих SQL-запроса для получения страницы с данными. Оба запроса возвращают 10 записей, используя одно ключевое значение, но несколько отличаются предложением WHERE:
Q запрос для получения следующей страницы получает 10 строк из таблицы базы данных, начиная со строки, следующей за последней строкой на текущей странице;
Q запрос для получения предыдущей страницы получает 10 записей, начинающихся с первой на предыдущей странице.
Примечание
В качестве альтернативы можно создать один запрос и динамически изменять в нем предложение WHERE. Однако в данном примере, для упрощения логики программного кода будет задействовано два запроса.
В этом примере мы будем использовать таблицу Customers тестовой базы данных Northwind SQL-сервера. Вы можете использовать любую другую таблицу из любой базы данных, однако она должна удовлетворять следующим условиям:
О таблица должна иметь уникальное ключевое поле (идентификатор);
Q таблица должна быть отсортирована по ключевому полю;
Q диалект языка SQL, который вы используете, должен поддерживать ключевое слово ТОР (определяющее количество возвращаемых строк).
Создание и конфигурирование объекта Connection
Для создания соединения с базой данных выполните следующие действия.
Из вкладки Data окна Toolbox перетащите на форму объект SqlConnection.
Примечание
В данном примере мы используем объект SqlConnection, который оптимизирован для работы с SQL-сервером версии 7.0 и выше. Если в своих приложениях вы будете обращаться к другим источникам данных, то используете OleDbConnection, который обеспечивает соединение с более широким спектром источников данных.
Выделите созданное соединение и в окне Properties нажмите кнопку в строке свойства ConnectionString.
Появится список существующих объектов соединения и пункт New Connection.
Если вы ранее не создавали соединение с базой данных Northwind SQL- сервера, то щелкните на New Connection. Если соединение с этой базой данных уже существует, то просто выберите его и перейдите к шагу 5.
Появится диалоговое окно Data Link Properties.
В этом диалоговом окне задайте имя используемого SQL-сервера, выберите базу данных Northwind и нажмите кнопку ОК.
Примечание
Вы должны иметь соответствующие права доступа к SQL-серверу, с которым будете работать. Рекомендуется использовать средства Windows для идента-- фикации пользователя при создании подключения к базе данных. В качестве альтернативы можно определить имя пользователя и пароль непосредственно в объекте Connection, однако это ставит под угрозу защиту информации на SQL-сервере.
Информация с параметрами подключения к базе данных будет сохранена в свойстве ConnectionString объекта Connection
Теперь пришла пора добавить команды. Вам необходимо будет создать две команды, по одной для каждого SQL-запроса (получение записей следующей и предыдущей страницы).
Для создания команды получения идентификаторов категории выполните следующие действия:
Из вкладки Data окна Toolbox перетащите на форму объект SqlCommand.
Присвойте команде имя cmdNext.
Выделите созданную команду и в окне свойств Properties нажмите кнопку в свойстве Connection. Выберите соединение, которое вы создали ранее, открыв узел Existing.
В строке свойства CommandText щелкните мышью кнопку для открытия диалогового окна построителя запросов Query Builder.
С помощью Query Builder сформируйте следующий SQL-запрос (рис. 6.18):
SELECT TOP 10 CustomerID, CompanyName, City
FROM Customers
WHERE (CustomerID > @customerid)
ORDER BY CustomerID
Рис. 6.18. Построение запроса с параметрами а окне Query Builder
Закройте диалоговое окно Query Builder.
Текст созданного SQL-запроса будет помещен в строку свойства CommandText.
Повторите шаги с 3 по 5 для создания объекта команды данных cmdPrevious, создав следующий запрос:
SELECT TOP 10 CustomerID, CompanyName, City
FROM Customers
WHERE (CustomerID >= @customerid)
ORDER BY CustomerID
Итак, мы закончили формирование объектов доступа к данным.
Добавление элемента управления DataGrid
Для иллюстрации возможности постраничного отображения данных будем использовать элемент управлении DataGrid. Для передвижения по страницам создадите кнопки Предыдущая и Следующая.
Для добавления и конфигурирования элемента управления DataGrid выполните следующие действия.
ИзвкладкиWebFormsокнаToolboxперетащитенаформуэлемент
управления DataGrid.
В нижней части окна Properties нажмите ссылку AutoFormat и задайте стиль Prosessional 6.
В окне Properties нажмите ссылку Property Builder.
Появится диалоговое окно DataGrid1 Properties (рис. 6.19).
Рис. 6.19. Разбивка элемента управления DataGrid на страницы в диалоговом окне DataGrid1 Properties
Переключитесь на вкладку Paging и установите свойства, описанные в табл. 6.8.
Таблица 6.8. Значения свойств элементов управления Web-формы
Свойство
Значение
AllowPaging
Checked
Allow custom paging
Checked
Page size
10
Show navigation buttons
Unchecked
5. Нажмите кнопку OK для закрытия диалогового окна.
Примечание
Привязку элемента управления DataGrid к источнику данных DataSource мы будем выполним в программном коде.
Для добавления навигационных кнопок выполните следующие действия.
ИзвкладкиWebFormsокнаToolboxперетащитенаформудваэлемента
LinkButton.
Назовите ИХ btnPrevious И btnNext.
Задайте текст, который будет отображен в этих кнопках, например, предыдущая И Следующая (рис. 6.20).
Рис. 6.20. Добавление навигационных кнопок перемещения по страницам объекта DataGrid
Добавление программного кода для выборки и отображения данных
Теперь добавим программный код для постраничного отображения данных. Основная логика работы приложения состоит в том, что при смене страницы выполняется один из SQL-запросов (одна из команд данных). В результате этого из базы данных выбирается 10 строк, которые помещаются в объект SqlDataReader. Данный объект динамически связывается с элементом управления DataGrid, и строки автоматически отображаются на экране. Осталось определить логику процесса отбора нужных 10 строк.
Для получения 10 строк следующей страницы, нужно начать выборку из базы данных со строки, которая следует за последней строкой в DataGrid. Необходимо получить идентификатор последней строки в сетке данных и использовать его как параметр для команды cmdNext.
Логика получения 10 строк предыдущей страницы является более сложной. Мы должны получить 10 строк, идущих перед первой строкой, которая находится на странице, отображаемой в текущий момент. Для реализации сказанного нужно запомнить номера первых строк всех просмотренных страниц и использовать их в качестве параметра для команды cmdPrevious.
Поскольку мы работаем с Web-формой, которая по своей сути является динамической Web-страницей, мы не имеем возможности сохранять информацию о номерах первых строк страниц в переменных. Мы должны хранить эти значения в каком-то буфере, пока страница будет отправлена к серверу и возвращена назад. В этом примере мы будем записывать информацию в элементе ViewState, который разместим непосредственно на странице (в скрытом поле). Данная структура будет содержать следующее:
Q номер текущий страницы, которая отображена на экране; данное значение также будет использоваться для определения того, в какую сторону пользователь листает страницы (вперед или назад);
Q идентификатор первой строки для каждой пройденной страницы, именем элемента будет номер страницы, а значением — идентификатор строки.
Мы будем создавать новый элемент ViewState для каждой страницы. Например, если мы находимся на третьей странице сетки данных, то будем иметь четыре элемента, описывающее текущее состояние:
CurrentPage=3
0=ALFKI
1=BSBEV
2=FAMIA
Итак, здесь номер текущей страницы — 3, идентификаторы первых записей: на первой странице — ALFKI, на второй странице — BSBEV, на третьей странице — FAMIA (номера страниц начинаются с 0).
В следующем разделе показан код, реализующий постраничный просмотр данных.
Отображение данных в DataGrid
Процедура заполнения DataGrid не зависит от того, какая кнопка навигации по записям была нажата. Поэтому нужно создать универсальную процедуру, к которой можно обратиться при выполнении любой команды cmdNext или cmdPrevious.
Для отображения данных в DataGrid выполните следующие действия.
Создайте переменную типа private с именем CurrentPage для хранения номера текущей страницы. Мы присвоим значение этой переменной позже (листинг 6.16).
[
••••—* **,* “» -
Листинг 6.16
' Visual Basic
Public Class WebForm1
Inherits Systern.Web.UI.Page
Private CurrentPage As Integer
//C#
public class WebForm6 : System.Web.UI.Page
{
private int CurrentPage;
}
Создайте процедуру с именем FillGrid, которой в качестве параметра передается команда данных SqlCommand.
Создайте экземпляр объекта считывания данных DataReader.
Откройте соединение и вызовите метод команды данных ExecuteReader — из базы данных будет выбрано 10 строк.
Установите в качестве свойства DataSource элемента управления DataGrid объект считывания данных DataReader и вызовите метод DataBind элемента управления DataGrid.
Закройте объекты DataReader И Connection.
Сохраните два значения в ViewState:
Значение переменной CurrentPage (номер текущей страницы);
Значение идентификатора первой строки в DataGrid.
Сохраните эти значения в элементе ViewState, именем которого будет номер текущей страницы. Строка этого программного кода будет иметь вид (листинг 6.17).
FTr """ ~
Листинг 6.17
' Visual Basic
ViewState(CurrentPage.ToString)=DataGrid1.Items(0).Cells(0).Text
// C#
ViewState[CurrentPage.ToString()]=DataGrid1.Items[0].Cells[0].Text;
Наконец, нужно определить, не находится ли пользователь в конце таблицы. Для простоты, в примере мы просто проверим, возвратил ли запрос меньшее количество строк, чем размер страницы (10). Если достигнут конец таблицы, то нужно сделать недоступной кнопку Следующая.
Листинг 6.18 показывает код процедуры FillGrid.
y„v»m..V..p.IV.^^.-„.^...............„.^...„„„........-^^^„^~«.и****^**^*-*»,***--».„„„....„,.....
Листинг 6.18
' Visual Basic
Private Sub FillGrid(ByVal currentSqlCommand as SqlClient.SqlCommand)
Dim dr As SqlClient.SqlDataReader
SqlConnection1.Open()
dr=currentSqlCommand.ExecuteReader()
DataGrid1.DataSource=dr
DataGrid1.DataBind()
dr.Close()
SqlConnection1.Close()
ViewState("CurrentPage")=CurrentPage
ViewState(CurrentPage.ToString)=DataGrid1.Items(0).Cells(0).Text
If DataGrid1.Items.Count<DataGrid1.PageSize Then
btnNext.Enabled=False
End If
End Sub
//C#
private void FillGrid(System.Data.SqlClient.SqlCommand currentSqlCommand)
{
System.Data.SqlClient.SqlDataReader dr;
SqlConnection1.Open();
dr=currentSqlCommand.ExecuteReader();
DataGrid1.DataSource=dr;
DataGrid1.DataBind();
dr.Close();
SqlConnection1.Close();
ViewState["CurrentPage"]=CurrentPage;
ViewState[CurrentPage.ToString()]=DataGrid1.Items[0].Cells[0].Text;
if (DataGrid1.Items.Count<DataGrid1.PageSize)
{
btnNext,Enabled=false;
}
}
Инициализация страницы
При первой загрузке Web-формы в элементе DataGrid необходимо отобразить первую страницу данных. Теперь, когда нами реализован модуль заполнения DataGrid, все, что нам нужно сделать, это установить передаваемые параметры и вызывать эту процедуру. Нам нужно выполнить команду cmdNext. Установите значение пустой строки для параметра @customerid. Данная запись означает, что запрос вернет записи, значение ключевого поля которых больше чем пустая строка (" ") — первые 10 записей таблицы. Номеру текущей страницы CurrentPage нужно присвоить значение о — признак того, что мы находимся на первой странице.
Программный код будет иметь следующий вид (листинг 6.19).
^мтумм ........... ..........„,..Wf.W~WW~M~W....W....*WWW«W.«~*..W~..W...M ~~~^*~~. .......,.,.. ........WUMM.,^
Листинг 6.19
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, ByVal e AsJv System. EventArgs) Handles MyBase.Load
' Добавленный код
If Not Page.IsPostBack Then
cmdNext.Parameters("@customerid").Value=""
CurrentPage=0
FillGrid(cmdNext)
End If
End Sub
//C#
private void Page_Load(object sender, System.EventArgs e)
{
// Добавленный код
if {!Page.IsPostBack)
{
cmdNext.Parameters["@customerid"].Value="";
CurrentPage=0;
FillGrid(cmdNext);
}
}
Переход на следующую страницу
Когда пользователь перемещается к следующей странице, необходимо снова выполнить команду cmdNext, используя нашу универсальную процедуру
FillGrid. Для этой команды нужно определить значение параметра — значение идентификатора последней строки в DataGrid.
Также нужно увеличить номер текущей страницы на единицу, чтобы в процедуре FillGrid можно было использовать этот номер для создания нового элемента ViewState для хранения идентификатора первой строки следующей страницы. Для увеличения номера страницы, нужно сначала вывести номер предыдущей страницы из элемента ViewState. Значение предыдущего номера нужно привести к целому числу, так как все элементы в ViewState сохраняются как объекты.
Программный код выглядит следующим образом (листинг 6.20).
Листинг 6.20
' Visual Basic
Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As % System. EventArgs) Handles btnNext.Click
' Получение номера следующей страницу
CurrentPage=CType(ViewState("CurrentPage"), Integer)
CurrentPage += 1
' Получение идентификатора последней строки текущей страницы
Dim lastid As String=DataGrid1.Items(9).Cells(0).Text
cmdNext.Parameters("@customerid").Value=lastid
FillGrid(cmdNext)
End Sub
//C#
private void btnNext_Click(object sender, System.EventArgs e)
{
// Получение номера следующей страницы
CurrentPage=(int)(ViewState["CurrentPage"]);
CurrentPage++;
// Получение идентификатора последней строки текущей страницы
string lastid=DataGrid1.Items[9].Cells[0].Text;
cmdNext.Parameters["@customerid"].Value=lastid;
FillGrid(cmdNext);
}
Переход к предыдущей странице
Наконец, мы должны написать программный код, который позволит листать страницы назад. Сначала получим номер текущей страницы и умень-
шим его на единицу. Затем обратимся к элементу ViewState, используя номер страницы как имя, для получения идентификатора первой строки на этой странице. Полученный идентификатор первой строки будет являться параметром для команды cmdPrevious, которая в свою очередь передается в универсальную процедуру FillGrid.
Чтобы предотвратить выход за начало таблицы, нужно проверить, не стал ли номер страницы меньше нуля. Кроме того, мы должны открыть доступ к кнопке Следующая, которая могла быть заблокирована в предыдущем движении вперед (листинг 6.21).
■’."'■“*""-“?•-"• ~}f;; v-x-rpt
Листинг 6.21
' Visual Basic
Private Sub btnPrevious_Click(ByVal sender As System.Object, ByVal e As^ System.EventArgs) Handles btnPrevious.Click
btnNext.Enabled=True
CurrentPage=CType(ViewState("CurrentPage"), Integer)
CurrentPage -= 1
If CurrentPage >= 0 Then
Dim firstid As String
firstid=CType(ViewState(CurrentPage.ToString), String)
cmdPrevious.Parameters("@customerid").Value=firstid
FillGrid(cmdPrevious)
End If
End Sub
//C#
private void btnPrevious_Click(object sender, System.EventArgs e)
{
btnNext.Enabled=true;
CurrentPage=(int)(ViewState["CurrentPage"]);
CurrentPage—-;
if (CurrentPage >= 0)
{
string firstid;
firstid=(string)(ViewState[CurrentPage.ToString()]);
cmdPrevious.Parameters["@customerid"].Value=firstid;
FillGrid(cmdPrevious);
}
}
Тестирование приложения
После добавления программного кода, проверим работу нашего приложения.
Для тестирования Web-формы выполните следующие действия.
Сохраните Web-форму.
В Solution Explorer щелкните правой кнопкой мыши на Web-форме и выберите в контекстном меню Build and Browse.
Убедитесь, что в DataGrid отображено 10 записей.
Нажимайте кнопки Следующая и Предыдущая пока не достигните конца и не вернетесь назад к началу(рис. 6.21).
Рис. 6.21. Внешний вид сетки данных с оптимизированной разбивкой на страницы
Добавление, удаление и обновление записей в Web-формах
В заключение главы мы рассмотрим взаимосвязанные процедуры добавления, удаления и редактирования записей. Это наиболее частые действия, которые выполняют пользователи при работе с базами данных. В качестве
элемента отображения данных будет использоваться элемент управления DataGrid. Данный пример иллюстрирует Web-форму, которая отображает в сетке содержимое таблицы базы данных. С помощью кнопок пользователь будет иметь возможность редактировать, добавлять или удалять записи из таблицы базы данных.
Для того чтобы реализовать пример этого раздела, нужно иметь доступ к базе данных Northwind, которая автоматически устанавливается при инсталляции MS SQL Server. Вам предстоит пройти следующие этапы работы:
Q создать Web-проект и, соответственно, Web-фому;
Q создать соединение с базой данных connection;
Q создать объект доступа к базе данных DataAdapter;
Q создать и сконфигурировать набор данных DataSet;
Q добавить на форму элемент управления DataGrid и связать его с набором данных DataSet;
Q добавить на форму элемент управления Button;
Q добавить программный код для заполнения набора данных DataSet;
Q добавить программный код, обеспечивающий функциональность кнопок активизации процедур модификации записей базы данных.
Создание проекта и формы
Для создания проекта и формы выполните следующие шаги.
В меню File укажите New и затем выберите элемент Project.
В частиProjectTypesоткрывшегосяокнавыберитеVisualBasicProjects
или Visual C# Projects, а затем в правой части выберите ASP.NET Web Application.
В поле Location введите полный URL вашего приложения. Он должен включать приставку http://, имя сервера и имя проекта. У вас должен быть установлен Web-сервер (IIS) версии 5.0 и выше, а также .NET Framework. Если Web-сервер (IIS) установлен на вашем компьютере, то в качестве имени сервера можно задать http://localhost
Если у вас уже открыто какое-либо приложение, выберите пункт Close Solution, чтобы закрыть текущее приложение.
Назовите проект уникальным именем, которое будет ассоциироваться у вас с выполняемыми действиями. Например, данный проект можно на- зватьWebAddDel.
Когда вы назначили имя проекта, щелкните кнопку ОК.
Visual Studio создаст новый проект и отобразит Web-форму в окне дизайнера.
Создание и конфигурирование элементов доступа к данным
Чтобы получить данные на компьютер пользователя необходимо создать соединение с базой данных и элемент DataAdapter, который содержит SQL-запросы, и используется для заполнения данными элемента DataSet,
На панели дизайнера появится объект DataSetll. На этом этапе мы создали все объекты, необходимые для связи приложения с базой данных.
Далее мы добавим на форму традиционный элемент управления — DataGrid, который используется для отображения всех записей, содержащихся в наборе данных. Для добавления сетки данных на форму выполните следующие действия.
Щелкните левой кнопкой мыши в любом свободном месте формы WebForm1, чтобы форма стала активной и получила фокус.
Из вкладки Web Forms окна Toolbox, перетащите элемент DataGrid на форму.
Нажмите клавишу <F4> для перехода в окно Properties.
Свойству DataSource выберите DataSet11 в качестве источника данных.
Свойству DataMember установите значение Categories.
Значением свойства DataKeyField назначьте CategoryID.
Установив пару последних свойств, вы фактически связали DataGrid с таблицей categories из набора данных DataSetll. После этих действий в сетке данных DataGrid появились столбцы с заголовками полей выводимых данных.
Из вкладки Windows Forms окна Toolbox перетащите на форму элемент Button и его свойству Text присвойте значение Добавить.
Перерисуйте элемент управления DataGrid так, чтобы в сетке данных было видно несколько колонок и строк, в окне Properties щелкните на ссылку Auto Format и в открывшемся окне выберите один из стилей форматирования (например, Professional 2). Расположите элементы на форме в соответствии с рис. 6.22.
Добавьте к элементу DataGrid две колонки с кнопками (для обеспечения возможности редактирования и удаления записи). Для этого выделите мышью элемент DataGrid, в окне его свойств Property нажмите на ссылку Property Builder, после чего откроется диалоговое окно DataGrid1 Properties.
Start Peg» WebForrnl.aspx* |
'?в
Добавить
1 Category ID
CategoryName
Description
Рис. 6.22. Расположение элементов управления на форме
В диалоговом окне перейдите на вкладку Columns и в левом списке Available columns раскройте узел Button Column.
Выделите пункт с названием Delete и нажмите кнопку > для переноса колонки в правый список Selected Columns.
В поле Text введите наименование действия Удалить, в поле Button Туре выберите значение PushButton (рис. 6.23).
Рис. 6.23. Окно редактирования свойств элемента управления DataGrid
Выделите в левом списке колонку с наименованием Edit, Update, Cancel и нажмите кнопку > для переноса этой колонки в часть Selected Columns.
В поле Edit Text введите слово Редактировать, в Cancel Text — Отменить, в Update Text — обновить, в выпадающем списке Button Type выберите PushButton и нажмите кнопку ОК.
После этого к элементу управления DataGrid добавится столбец с кнопкой Удалить и столбец с кнопками Редактировать, которая после нажатия будет меняться на Отменить и Обновить (рис. 6.24).
Рис. 6.24. Колонки с кнопками в элементе управления DataGrid
На следующем шаге к элементам страницы необходимо добавить соответствующую функциональность.
Формирование программного кода
Теперь перейдем к формированию программного кода. Начнем с написания обработчика загрузки формы, в котором необходимо заполнить информацией набор данных DataSet (листинг 6.22).
Листинг 6.22
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As^ System. EventArgs) Handles MyBase.Load
SqlDataAdapter1.Fill(DataSet11)
If Not IsPostBack Then
DataGrid1.DataBind()
End If
End Sub
//C#
private void Form1_Load(object sender, System,EventArgs e)
{
SqlDataAdapter1.Fill(dataSet11);
Набор данных заполняется путем вызова метода Fill адаптера данных. Вторым оператором активизируется связывание заполненного набора данных с объектом DataGrid.
На следующих шагах последовательно сформируем программный код для обработки событий нажатия кнопок.
INSERT INTO Categories (CategoryName, Description)VALUES (©CategoryName, ©Description);INSERT INTO Categories (CategoryName, Description)VALUES (©CategoryName, ©Description);Для обеспечения возможности добавления записи будет использована команда SqlInsertCommand1 адаптера данных. Для получения доступа к тексту этой команды выделите мышью объект SqlDataAdapter1, войдите в окно его свойств и найдите строку InsertCommand. Раскройте данный узел, щелкнув на указателе +, нажмите кнопку в строке свойства CommandText. Откроется окно построителя запросов Query Builder с текстом соответствующего SQL-запроса (рис. 6.25).
INSERT INTO Categories (CategoryName, Description)
VALUES (©CategoryName, ©Description);
INSERT INTO Categories (CategoryName, Description)
VALUES (©CategoryName, ©Description);
SELECT CategorylD, CategoryName, Description
FROM Categories
WHERE (Categor yID - ©©IDENTITY)
Рис. 6,25. Текст команды InsertCommand в окне построителя запросов
Из текста запроса видно — для того чтобы добавить запись в таблицу Categories, необходимо присвоить значения двум параметрам этого SQL- запроса @CategoryName и @Description. Данное обстоятельство нужно учесть при формировании программного кода. Программный код обработки события нажатия кнопки Добавить приведен в листинге 6.23.
Листинг 6.23
' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As^ System. EventArgs) Handles Button1.Click
' Добавление записи
SqlDataAdapter1,InsertCommand.Parameters("@CategoryName").Value=""
SqlDataAdapter1.InsertCommand.Parameters("@Description").Value=""
SqlConnection1.Open()
SqlDataAdapter1.InsertCommand.ExecuteNonQuery()
SqlConnection1.Close()
SqlDataAdapter1.Fill(DataSet11)
DataGrid1.DataBind()
End Sub
//C#
private void button1_Click(object sender, System.EventArgs e)
{
// Добавление записи
sqlDataAdapter1.InsertCommand.Parameters["@CategoryName"].Value="";
sqlDataAdapter1.InsertCommand.Parameters["@Description"].Value="";
SqlConnection1.Open();
sqlDataAdapter1.InsertCommand.ExecuteNonQuery();
SqlConnection1.Close();
sqlDataAdapter1.Fill(dataSet11);
DataGrid1.DataBind();
}
В первых двух строках программного кода параметры @CategoryName и @Description команды InsertCommand адаптера данных SqlDataAdapter1 получают значения (в данном случае пустую строку). Затем открывается соединение с базой данных, исполняется команда InsertCommand (запись добавляется в базу данных) и соединение с базой данных закрывается. В следующих строках объект DataSetll заполняется обновленной информацией из базы данных, путем вызова метода Fill адаптера данных. После этого активизируется связывание заполненного набора данных с объектом DataGrid.
Для обеспечения возможности удаления записи будет использована команда sqlDeleteCommand1 адаптера данных. Для получения доступа к тексту команды выделите мышью объект SqlDataAdapter1, войдите в окно его свойств и отыщите строку DeleteCommand. Раскройте этот узел, щелкнув на значке +, найдите свойство CommandText и нажмите кнопку в строке с ним. Откроется окно построителя запросов Query Builder с текстом соответствующего SQL-запроса. Измените текст запроса, приведя к виду на рис. 6.26:
DELETE FROM Categories WHERE (CategoryID=@Original_CategoryID)
Рис. 6.26. Текст команды DeleteCommand в окне построителя запросовРис. 6.26. Текст команды DeleteCommand в окне построителя запросов
Рис. 6.26. Текст команды DeleteCommand в окне построителя запросов
Рис. 6.26. Текст команды DeleteCommand в окне построителя запросов
Из текста запроса видно, что, для того, чтобы удалить запись из таблицы Categories, необходимо задать значения параметра @Original_CategoryID SQL-запроса. Значение CategoryID можно получить из текущей ячейки элемента отображения данных DataGrid (при этом будет удалена та запись, в строке которой пользователь нажал кнопку Удалить). Данное обстоятельство нужно учесть при формировании программного кода.
Для формирования обработчика события нажатия кнопки Удалить на VB войдите в редактор программного кода и из выпадающего списка в левой верхней части окна выберите элемент управления DataGrid, а из выпадающего списка в правой верхней части окна элемент DeleteCommand. После ЭТОГО будет создан Обработчик События DataGrid1_DeleteCoinmand.
Для формирования обработчика события нажатия кнопки Удалить на С# выделите на форме элемент управления DataGrid и войдите в окно его свойств Properties, в верхней части которого нажмите на кнопку Events . Дважды щелкните левой кнопкой мыши в строке DeleteCommand или наберите в ней DataGrid1_DeleteCommand. Будет создан обработчик события DataGrid1_DeleteCommand, в него нужно внести следующий код (листинг 6.24).
Листинг 6.24Листинг 6.24' Visual BasicPrivate Sub DataGrid1_DeleteCommand(ByVal source As Object, ByVal eAs АзЪSystern.Web.UI.WebControls.DataGridCommandEventArgs) Handles Data-Grid1.DeleteCommand' Visual BasicPrivate Sub DataGrid1_DeleteCommand(ByVal source As Object, ByVal eAs АзЪSystern.Web.UI.WebControls.DataGridCommandEventArgs) Handles Data-Grid1.DeleteCommand
Листинг 6.24
Листинг 6.24
' Visual Basic
Private Sub DataGrid1_DeleteCommand(ByVal source As Object, ByVal eAs АзЪ
Systern.Web.UI.WebControls.DataGridCommandEventArgs) Handles Data-
Grid1.DeleteCommand
' Visual Basic
Private Sub DataGrid1_DeleteCommand(ByVal source As Object, ByVal eAs АзЪ
Systern.Web.UI.WebControls.DataGridCommandEventArgs) Handles Data-
Grid1.DeleteCommand
' Удаление записи
Dim CategoryID As Int16
Dim index As Integer
index=e.Item.ItemIndex
CategoryID=CType(DataGrid1.Items(index).Cells(2).Text, Int32)
SqlDataAdapter1.DeleteCommand.Parameters("@Original_CategoryID")ъ
.Value=CategoryID
SqlConnection1.Open()
SqlDataAdapter1.DeleteCommand.ExecuteNonQuery()
SqlConnection1.Close()
DataSet11.Clear(}
SqlDataAdapter1.Fill(DataSet11)
DataGrid1.DataBind()
End Sub
//C#
private void DataGrid1_DeleteCommand(object source, ^ Sys- tem.Web.Ul.WebControls.DataGridCommandEventArgs e)
{
int index ;
int CategoryID;
index=e.Item.ItemIndex;
CategoryID=dataSet11.Categories[index].CategoryID;
SqlDataAdapter1.DeleteCommand.Parameters["@Original_CategoryID"]
.Value=CategoryID;
SqlConnection1.Open();
SqlDataAdapter1.DeleteCommand.ExecuteNonQuery();
SqlConnection1.Close();
dataSet11.Clear();
SqlDataAdapter1.Fill(dataSet11);
DataGrid1.DataBind();
}
В первых двух строках программного кода выполняется объявление переменных: index — номер текущей строки элемента управления DataGrid, CategoryID — идентификатор удаляемой записи (категория товара). Затем переменная index получает значение текущей строки элемента DataGrid, переменная CategoryID получает значения идентификатора удаляемой записи. Параметр @Original_CategoryID команды DeleteCommand адаптера данных SqlDataAdapter1 получает значение из переменной CategoryID. Затем
открывается соединение с базой данных, исполняется команда DeleteCommand (запись удаляется из базы данных) и соединение с базой данных закрывается. В следующих двух строках объект DataSetll заполняется обновленной информацией из базы данных, путем вызова метода Fill адаптера данных и активизируется связывание заполненного набора данных с объектом DataGrid. После этого удаленная запись исчезает из элемента отображения информации DataGrid.
Наконец, для обеспечения возможности редактировать информацию в элементе управления DataGrid, необходима добавить код обработки нажатия кнопок Редактировать, Отменить и Обновить.
В режим редактирования нужно перевести ту строку, в которой пользователь нажал кнопку Редактировать (текущая строка). Вы можете получить номер текущей строки из объекта обработчика события нажатия кнопки. В обработчике события имеется свойство Item, которое представляет всю строку DataGrid для модификации. Объект Item в свою очередь, поддерживает набор различных свойств, включая и свойство Item. ItemIndex, которое содержит индекс той строки, с которой в текущий момент работает пользователь.
Для перевода строки в режим редактирования выполните следующие действия.
Создайте обработчик события DataGrid1_EditCommand, для чего на Visual Basic:
щелкните правой кнопкой мыши в любом месте Web-формы и в контекстном меню выберите View Code, чтобы открыть редактор кода;
в левом раскрывающемся списке верхней части редактора кода выберите DataGrid1;
в правом раскрывающемся списке верхней части редактора кода выберите EditCommand.
На Visual С#:
в режиме дизайнера формы выделите DataGrid затем нажмите клавишу <F4>, чтобы открыть окно Properties;
нажмите кнопку Events в верхней части окна Properties;
дважды щелкните в строке EditCommand в сетке данных.
Будет создан обработчик события DataGrid1_EditCommand.
Повторитешаг1длясобытияCancelCommand(будетсозданобработчик
события DataGrid1_CancelCommand).
Повторитешаг1длясобытияUpdateCommand(будетсозданобработчик
события DataGrid1_ UpdateCommand).
В обработчик события EditCommand добавьте следующий код (листинг 6.25).
Листинг 6.25
' Visual Basic
Private Sub DataGrid1_EditCommand(ByVal source As Object, ByVal e As%>
System.Web.UI.WebControls.DataGridCommandEventArgs) Handles Data-
Grid1.EditCommand
DataGrid1.Editltemlndex=a.Item.ItemIndex
DataGrid1.DataBind()
End Sub
// C#
private void DataGrid1_EditCommand(object source, ъ Sys- tem.Web.UI.WebControls.DataGridCommandEventArgs e)
{
DataGrid1.EditItemIndex=e.Itern.ItemIndex;
DataGrid1.DataBind();
}
В обработчик события CancelCommand добавьте следующий код (листинг 6.26).
' Visual Basic
Private Sub DataGrid1_CancelCommand(ByVal source As Object, ByVal e Asч> System.Web.UI.WebControls.DataGridCommandEventArgs) Handles Data- Grid1.CancelCommand
DataGrid1.Editltemlndex=-1
DataGrid1.DataBind()
End Sub
// C#
private void DataGrid1_CancelCommand(object source, ъ Sys- tem.Web.UI.WebControls.DataGridCommandEventArgs e)
{
DataGrid1.Editltemlndex=-1;
DataGrid1.DataBind();
}
Следующий программный код показывает обработчик события UpdateCommand (листинг 6.27). Комментарии к выполняемым действиям приведены непосредственно в листинге.
Листинг 6.27
' Visual Basic
Private Sub DataGrid1_UpdateCommand (ByVal source As Object, ByVal e Asч> System.Web.UI.WebControls.DataGridCommandEventArgs) Handles Data-
Grid1,UpdateCommand
Dim categoryName, categoryDescription As String
' Получение значения ключевого поля редактируемой строки
Dim key As String=DataGrid1.DataKeys(e.Item.ItemIndex).ToString
' Получение значений из элементов TextBox (из колонок редак. строки) Dim tb As TextBox
tb=CType(e.Itein.Cells(3).Controls(0), TextBox) categoryName=tb.Text
tb=CType(e.Item.Cells(4).Controls(0), TextBox) categoryDescription=tb.Text
' Поиск соответствующей строки в наборе данных
Dim r As DataSet1.CategoriesRow
r=DataSet11.Categories.FindByCategoryID(key)
' Обновление строки в таблице DataSet r.CategoryName=categoryName
r.Description=categoryDescription ' Обновление строки в базе данных SqlDataAdapter1.Update(DataSet11)
' Перевод DataGrid в режим отображения информации DataGrid1.Editltemlndex=-1
' Обновление DataGrid
DataGrid1.DataBind()
End Sub
// C#
private void DataGrid1_UpdateCommand (object source, ^ System. Web.UI.WebControls.DataGridCommandEventArgs e) {
string categoryName, categoryDescription;
// Получение значения ключевого поля редактируемой строки
string key=DataGrid1.DataKeys[e.Item.ItemIndex].ToString();
// Получение значений из элементов TextBox колонок
// редактируемой строки) TextBox tb;
tb=(TextBox)(e.Item.Cells[3].Controls[0]);
categoryName=tb.Text;
tb=(TextBox)(e.Item.Cells[4].Controls[0]);
categoryDescription=tb.Text;
// Поиск соответствующей строки в наборе данных
DataSet1.CategoriesRow r;
r=dataSet11.Categories.FindByCategoryID(int.Parse(key));
// Обновление строки в таблице DataSet
r.CategoryName=categoryName;
r.Description=categoryDescription;
// Обновление отроки в базе данных
SqlDataAdapter1.Update(dataSet11);
// Перевод DataGrid в режим отображения информации
DataGrid1.EditItemIndex=-1;
// Обновление DataGrid
DataGrid1.DataBind();
}
Запустите приложение и протестируйте все запрограммированные действия (добавить запись, отредактировать и обновить любую запись, удалить запись). На рис. 6.27 приведен фрагмент окна запущенного приложения, находящегося в режиме редактирования данных.
Start' :;- I WeuFa>r.il »:»• Wetftuni: е»> " Browse - WebForml |
Добавить
Category!!) CategoryName
Beverages jCondimenlsI ConfectionsBeverages jCondimenlsI ConfectionsУдалить IРедактировать |1
Beverages jCondimenlsI Confections
Beverages jCondimenlsI Confections
Удалить | Обновить [ Отменить j; 2
Удалить IРедактироватьI3
Рис. 6.27. Редактирование данных в элементе управления DataGridна этапе работы приложения
До настоящего момента мы рассматривали в той или иной степени знакомые типы приложений, построенные на основе Widows и Web-форм. Однако технология .NET предоставляет возможность разработки принципиально нового класса программных продуктов — Web-сервисов. Знакомству с приложениями этого типа и посвящена следующая глава.
ГЛАВА 7
Основные понятия о Web-сервисах
На сегодняшний день Web-сервисы — принципиально новый класс программных продуктов. Используя XML, HTML и другие стандартные технологии Web-сервисы могут взаимодействовать с другими приложениями, независимо от места их расположения и платформы, на которой они работают. В данной главе будут представлены материалы, связанные с созданием Web-сервисов с помощью Visual Studio .NET и организации доступа к ним из приложений-клиентов. В частности, мы познакомимся со структурой Web-сервисов и узнаем:
Q как создать простейший Web-сервис;
Q как обратиться к методу Web-сервиса из клиентского приложения.
Структура и назначение Web-сервисов
Технология Microsoft .NET сама по себе является новым шагом в упрощении создания распределенных приложений, а Web-сервисы являются "изюминкой" этой технологии. По сути дела Web-сервис это приложение, которое функционирует на сервере (в локальной сети или в Интернете) и представляет свои функции (методы) другим приложениям-клиентам. Коммуникация между приложениями-клиентами и Web-сервисом осуществляется при помощи языка XML и протокола HTTP. Поскольку язык XML и протокол HTTP являются платформонезависимыми, то с Web-сервисом может взаимодействовать любое приложение. В отличие от статических HTTP-документов Web-сервисы имеют более высокую функциональность, что позволяет на их основе создавать распределенные приложения. Причем клиенту передается не само приложение, а доступ к нему. Приложение- клиент передает Web-сервису набор входных параметров, а назад получает готовый результат. Учитывая, что через Web-сервисы можно взаимодейство-
вать с данными, расположенными на удаленных компьютерах, сфера их применения достаточно широка.
В данной главе мы создадим простейший Web-сервис и приложение- клиент, которое будет с ним взаимодействовать. А также создадим свое приложение, которое будет использовать функциональные возможности реального Web-сервиса через сеть Интернет.
Создание простейшего Web-сервиса
Следующий пример описывает процесс создания Web-сервиса. Для того чтобы сконцентрировать внимание на последовательности шагов при создании Web-сервиса, реализуем в нем достаточно простую функцию — преобразование одной валюты в другую. Для этого сервису будем передавать курс валюты и сумму, которую необходимо преобразовать.
При выполнении примера мы выполним следующие действия:
Q создадим Web-сервис на основе проекта-шаблона ASP.NET Web Service;
Q реализуем функциональность XML-сервиса;
Q запустим Web-сервис в режиме отладки;
Q развернем Web-сервис на Web-сервере.
Создание проекта XML Web Service
Для создания проекта XML Web Service выполните следующие действия.
В меню File выберите подменю New и пункт Project.
В дереве New Project выберите пункт Visual Basic Projects или the Visual C# Projects.
Щелкните мышью на значке ASP.NET Web Service.
Введите адрес Web-сервера, на котором вы собираетесь развернуть XML Web-сервис и определите имя директории его размещения. Например, http://MyServer/TempConvert1. По умолчанию, проект в качестве Web- сервера будет использовать локальный компьютер с именем http://localhost (рис. 7.1).
Примечание
Вы можете разрабатывать и отлаживать Web-сервис на промежуточном Web- сервере (на сервере разработки). По умолчанию сервером разработки является ваш локальный компьютер. Затем этот Web-сервис необходимо переместить на
реальный сервер в сети Интернет (сервер развертывания). Однако разработка может вестись и непосредственно на сервере развертывания.
Project Types:Project Types:Ten l acesTen l acesASP.NET Web ASP.NET WebASP.NET Web ASP.NET WebWindowsControl LibraryWindowsControl Library♦ ' M Visual Basic ProjectsI Visual СЖ Projects Cj Setup and Deployment Projects* _J Other Projects О Visual Studio Solutions♦ ' M Visual Basic ProjectsI Visual СЖ Projects Cj Setup and Deployment Projects* _J Other Projects О Visual Studio SolutionsWndows Class Library ApplicationWndows Class Library ApplicationApplicationApplicationServiceServiceWeb Control LibraryWeb Control Library
Project Types:
Project Types:
Ten l aces
Ten l aces
ASP.NET Web ASP.NET Web
ASP.NET Web ASP.NET Web
Windows
Control Library
Windows
Control Library
♦ ' M Visual Basic Projects
I Visual СЖ Projects Cj Setup and Deployment Projects
* _J Other Projects О Visual Studio Solutions
♦ ' M Visual Basic Projects
I Visual СЖ Projects Cj Setup and Deployment Projects
* _J Other Projects О Visual Studio Solutions
Wndows Class Library Application
Wndows Class Library Application
Application
Application
Service
Service
Web Control Library
Web Control Library
A project for creatng XML web services to use from other applications
Location:Location:J ’егт. .".хгув*1| http://locahost/TempConvertlJ ’егт. .".хгув*1| http://locahost/TempConvertlBrowse...Browse...
Location:
Location:
J ’егт. .".хгув*1
| http://locahost/TempConvertl
J ’егт. .".хгув*1
| http://locahost/TempConvertl
Browse...
Browse...
Project wi be created at http://locahost/TempCixwertl.
¥Mort¥Mort| OK | Cancel| OK | Cancel
¥Mort
¥Mort
| OK | Cancel
| OK | Cancel
Рис. 7.1. Окно создания проекта Web-сервиса
Щелкните кнопку ОК для создания проекта.
Visual Studio автоматически создаст необходимые файлы и ссылки для поддержки Web-сервиса, и вы увидите основной файл созданного Web- сервиса — Service1.asmx (рис. 7.2).
Рис. 7.2. Основной файл Web-сервиса в окне Solution ExplorerРис. 7.2. Основной файл Web-сервиса в окне Solution Explorer
Рис. 7.2. Основной файл Web-сервиса в окне Solution Explorer
Рис. 7.2. Основной файл Web-сервиса в окне Solution Explorer
Формирование программного кода Web-сервиса
На следующем шаге необходимо написать программный код, который реализует функциональные возможности нашего Web-сервиса. Для Web-
сервиса, созданного в Visual Studio, программный код, реализующий его функциональные возможности, содержится в asmx-файле.
Для написания программного кода выполните следующие действия.
Дважды щелкните мышью в любом месте окна Component Designer, чтобы открыть файл с программным кодом.
Примечание j
В окне Solution Explorer файл с программным кодом может быть невидим (по умолчанию он скрыт). Нажмите Show All Files на инструментальной панели Solution Explorer, чтобы отобразить скрытые файлы или в меню Project выберите Show All Files.
После этого откроется редактор программного кода, в котором будет находиться в закомментированном виде заготовка формируемого Web- метода (рис. 7.3).
Start Page | Serve»:.asm: vbtDeslon] Servkel.a6mx.vb |
1^Service 1v] |K\ (Declarations)
Imports System.Web.Services
Ы <VebService(Namespace :- "http://temourl,ora/"1> _
Public Class Service1
Inherits System.Web.Services.VebService
E3| Veh Ser vic
E 1 WEB SERVICE EXAMPLE
The HelloUorld() example service returns the string Hello World.
To build, uncomment the following lines then save and build the project.
To test this web service, ensure that the . asn.x file is the start page
and press F5.
• <UebMethod()> Public Function HelloUorld() As String
* HelloUorld ■ "Hello World"
L * End Function
End Class
Рис. 7.3. Закомментированный шаблон Web-метода в редакторе программного кода
Снимите комментарии с шаблона Web-метода и наберите следующий программный код метода convert (листинг 7.1).
Листинг7.1 8нм<1и.н1ги.••.»••*»..........«..«„f,,,.••••••••• .......~...——-»«
Visual Basic
<WebMethod(Description:="Преобразование валюты")>
Public Function Convert(ByVal Summa As Double,Ъ
ByVal Kurs As Double) As String
Convert=Summa * Kurs
End Function
// C#
[WebMethod(Description="Преобразование валюты")] public double Convert(double Summa, double Kurs) {
return Summa * Kurs;
}
В теге WebMethod создается Public-функция с именем convert. Эта функция является частью Web-сервиса, результаты работы этой функции будут переданы программе-клиенту, которая к ней обратится. Метод convert будет включен в состав сервисной страницы справки методов Web-сервиса. Параметр Description является не обязательным, он, по сути дела, является описанием назначения данного метода на его справочной странице.
Если вы создаете проект на VB, то выберите Service1.asmx в Solution Explorer. В меню Project выберите пункт Web Project и затем нажмите Set as Start Page.
Если вы создаете проект на С#, щелкните правой кнопкой мыши на Service1.asmx в Solution Explorer и затем выберите в контекстном меню Set as Start Page.
Сохраните приложение.
Тестирование Web-сервиса
Проверим работоспособность созданного нами Web-сервиса. Для этого щелкните правой кнопкой мыши на файле Service1.asmx в окне Solution Explorer и в появившемся контекстном меню выберите пункт Build and Browse. Откроется справочная страница (рис. 7.4). Эта страница автоматически генерируется на Web-сервере на основе информации из файла Service1.asmx и тегаWebMethod().
На данной странице имеется ссылка на метод нашего сервиса Convert. Нажав на эту ссылку, мы запустим тестовую страницу, на которой можно проверить работу нашего Web-сервиса (рис. 7.5).
В нашем примере для проверки работы сервиса необходимо передать ему два параметра: преобразуемую сумму (Summa) и курс валют (Kurs). Введите в эти два поля любые значение и нажмите кнопку Invoke (рис. 7.6).
Рис. 7.4. Справочная страница Web-сервиса со ссылкой на Web-метод
'•'i ij- । 1 i иBrowse - Set vice 1 Web Service | I
Servicel
Click hvrr for a complete list of operations.
Convert Преобразование валюты Test
To test the operation using the HTTP GET protocol, click the ‘Invoke’ button.
Parameter Value Summa: |
Kurs: Invoke |•
Рис. 7.5. Тестовая страница проверки функциональности Web-метода Convert
Parameter Value
Summa: [1000•
Kurs:130*
Invoke |
Рис. 7.6. Тестирование Web-метода Convert на тестовой странице
После этого откроется новое окно, в котором вы увидите результат, представленный в виде XML-документа (рис. 7.7).
Slnrl Faye Sarvicel asmx.vb [Pesqn] | Service I .emrx.vt) | Frowse ■ x-rvicel Web Service
<?xml version=" 1.0" encoding="utf-8" ?>
<stnng xmlns=‘http://tempuri.org/">30000</string>
Рис, 7.7. Результат работы Web-метода Convert в виде XML-документа
Результат работы Web-сервиса представлен в не совсем удобном для восприятия виде. Однако нужно не забывать, что к сервису будет обращаться приложение-клиент, и результат будет возвращен ему по сети Интернет. А как он будет отображен и использован в удаленном приложении с точки зрения Web-сервиса не важно. Главное, чтобы метод Web-сервиса работал без ошибок и его результаты были переданы клиенту в требуемом формате, в данном случае — XML.
Отладка Web-сервиса
В Visual Studio можно использовать отладчик для проверки логики работы приложения и поиска ошибок,
Для запуска Web-сервиса с отладкой и использования контрольных точек выполните следующие действия.
Налевомполередакторакодавставьтеточкуостановав любомместе
программного кода (рис. 7.8).
<VebMethod(Description:="Преобразование валюты") >
Public Function Convert(ByVai Summa As Double, _
_ByVai Kurs As Double) As String
Convert = Summa * Kurs
End Function
' End Class
Рис. 7.8. Точка останова в листинге Web-метода
В меню Debug нажмите Start.
Эта команда запускает Web-службу в режиме отладчика. При этом Visual Studio компилирует проект и развертывает приложение на Web-сервере разработчика, а заданный по умолчанию браузер отображает asmx-файл. В точках останова будет показан фрагмент программного кода и текущие значения переменных (рис. 7.9).
Таким образом, при разработке Web-сервиса программист работает в обычной среде и использует знакомые и привычные средства отладки приложений.
start Page Service! asm> vb [Design] Servicel.asmx.vb |
P* Service 15 |-♦Convert
Imports System.Web.Services
L<WebService(Namespace :- "http://tempuri.ora/")> _ Public Class Service1
Inherits System.Web.Services.WebService
[]| Web Services Designer Generate! Code |
. <VebMethod(Description:w"npeo6pa3OBaHMe валюты")> Public Function Convert(ByVai Summa As Double, _ r •ByVai Kurs As Double) As String
QConvert * Summa * Kurs
End Function
End Class
Рис. 7.9. Остановка работы программы в режиме отладки приложения
Для завершения работы Web-сервиса и возвращения в редактор кода, закройте браузер или в меню Debug выберите Stop Debugging.
Примечание
Запустить Web-сервис можно нажатием клавиши <F5>, а завершить его работу — <SHIFT>+<F5>.
РазвертываниеWeb-сервиса
Для того чтобы предоставить ваш Web-сервис другим приложениям, необходимо развернуть его на Web-сервере, который является доступным для клиентов в рамках локальной сети или через Интернет. Развернуть Web- сервис на общедоступном сервере можно двумя способами: добавлением к вашему проекту специального проекта установки (Web Setup project) или специальным копированием требуемых файлов на общедоступный сервер.
Для развертывания Web-сервиса с использованием Web Setup project выполните следующие действия.
В меню File выберите подменю Add Project и в нем пункт New Project.
ВыберитепапкуSetupandDeploymentProjectsи нажмитеWebSetupPro
ject.
В поле Name наберите имя проекта установки TempConvert1WebSetup и нажмите кнопку ОК (рис. 7.10).
Рис. 7.10. Окно создания приложения развертывания Web-сервиса
Примечание
По умолчанию инсталлятор использует имя вашего проекта установки для создания виртуального каталога на сервере развертывания.
В открывшемсяокнеFileSystemEditorвыберитепапкуWebApplication
Folder.
В окнеSolutionExplorerщелкнитеправойкнопкоймышинатетрсоп-
vert1WebSetup, выберите пункт Add и затем нажмите Project Output (рис. 7.11).
В диалоговом окне Add Project Output Group выберите Content Files, Primary output и Debug Symbols:
группа Content Files состоит из следующих файлов Web-сервиса: TempConvert1.asmx, Global.asax, и Web.config. По умолчанию, группа Content Files не включает vsdisco-файл;
группа Primary output состоит из файла TempConvert1.dll и зависимых файлов;
группа Debug Symbols состоит из файла TempConvert1.pdb.
Нажмите кнопку ОК.
В Solution Explorer щелкните правой кнопкой мыши на проекте TempConvert1WebSetup и затем в контекстном меню выберите Build.
При этом будет создан обычный файл установки в каталоге с проектами на вашем локальном компьютере (рис. 7.12).
Рис. 7.11. Диалоговое окно формирования состава распространяемого приложения
Рис. 7.12. Установочные файлы для инсталляции Web-сервиса
Скопируйте установочные файлы на общедоступный Web-сервер и запустите там процедуру Setup для установки вашего Web-сервиса.
Для развертывания Web-сервиса путем копирования проекта выполните следующие действия.
В окне Solution Explorer выделите проект TempConvert1 (рис. 7.13).
Рис. 7.13. Проект Web-сервиса в окне Solution Explorer
В меню Project нажмите Copy Project.
В полеDestinationprojectfolder введитепуть,кудавыхотитескопиро
вать проект.
Установите переключатель в положение FrontPage или File share, чтобы выбрать метод доступа (Web access method).
НажмитеOnlyfiles neededtorunthis application.Поумолчаниюне будет
включен vsdisco-файл.
Нажмите кнопку OK (рис. 7.14).
Рис. 7.14. Окно формирования параметров копирования Wab-сервиса
Доступ к Web-сервису
из клиентского приложения
Следующий пример описывает процесс обращения к Web-сервисам из приложений клиентов.
В ходе этого примера мы выполним следующие действия:
О создадим приложение-клиент, которое будет использовать функциональные возможности Web-сервиса;
Q добавим Web-ссылку на Web-сервис;
Q напишем программный код для обращения к Web-сервису;
О запустим наше приложение.
Q развернем приложение Web.
СозданиеприложенияклиентаWeb-сервиса
В примере мы создадим простое Web-приложение, которое обратится к Web-службеTempConvert1.
Примечание
Чтобы обратиться к другим Web-службам, нужно заменить имя TempConvert1, используемое в этом примере, на имя другой Web-службы.
Для создания приложения клиента (Web-приложения) выполните следующие действия.
В меню File выберите подменю New и в нем пункт Project для открытия диалогового окна New Project.
Выберите язык программирования для реализации проекта Visual Basic Projects или Visual C# Projects.
Укажите тип проекта ASP.NET Web Application.
Введите адрес Web-сервера, на котором вы разработаете Web- приложение и введите в качестве имени проекта TempConvertClient1 — и путь http://MyServer/TempConvertClient1. По умолчанию имя Web- сервера задано как http://localhost.
Нажмите кнопку ОК для создания проекта (рис. 7.15).
ИзвкладкиWebForms окнаToolboxперетащитенаформуэлементы
управления TextBox, Label и Button. Расположите их на форме, как показано на рис. 7.16., и задайте этим элементам свойства Text в соответствии с табл. 7.1.
Рис. 7.15. Окно создания приложения клиента Web-сервиса
Рис. 7.16. Расположение элементов управления на Web-форме
Таблица 7.1. Свойства Text элементов управления
Элемент
Значение
Label1
Сумма (руб.)
Label2
Курс $
Label3
Сумма $
Label4
(Пусто)
TextBox1
(Пусто)
TextBox2
(Пусто)
Button1
Преобразовать
В текстовые поля мы будем вводить значения конвертируемой суммы (TextBox1) и курса валюты (TextBox2), а метке Label4 будем присваивать значения, возвращаемые из Web-сервиса. В обработчике события нажатия кнопки Button1 напишем код обращения к Web-сервису.
Добавление ссылки на Web-сервис
В Web-сервисе поддерживается процесс его открытия, при этом приложение-клиент определяет местонахождение Web-сервиса и получает его описание. В описании содержится информация о том, какие услуги доступны в Web-сервисе и как взаимодействовать с этими услугами. Без сервисного описания программа-клиент не сможет взаимодействовать с Web-службой. Добавление ссылки на Web-сервис к проекту приложения клиента обеспечивает возможность их полноценного взаимодействия.
Для добавления Web-ссылки на Web-сервис выполните следующие действия.
В меню Project нажмите Add Web Reference.
В поле Address диалогового окна Add Web Reference введите адрес, чтобы получить описание Web-службы, к которой необходимо обратиться, например, http: // <servername>/TempConvert1/Service1.asmx.
Если вы создавали Web-службу на вашем локальном компьютере, то необходимо набрать http://localhost/TempConvert1/Service1.asmx и нажать клавишу <ENTER> (рис. 7.17).
4= иг пч Address: | http;//localhost/TempCo<wertl/Sefvicel.a$mx4= иг пч Address: | http;//localhost/TempCo<wertl/Sefvicel.a$mx
4= иг пч Address: | http;//localhost/TempCo<wertl/Sefvicel.a$mx
4= иг пч Address: | http;//localhost/TempCo<wertl/Sefvicel.a$mx
Avaiable references:Web Services*1 http://localhost/TempConView ContractView DocumentationAvaiable references:Web Services*1 http://localhost/TempConView ContractView DocumentationServicel
Avaiable references:
Web Services
*1 http://localhost/TempCon
View Contract
View Documentation
Avaiable references:
Web Services
*1 http://localhost/TempCon
View Contract
View Documentation
The following operations are supported. For a formal definition, please review the • ervu •■ Qey notion.
• Convert Преобразование вапюты
Рис. 7.17. Добавление Web-ссылки на Web-сервис в приложении-клиенте
Нажмите кнопку Add Reference, чтобы добавить Web-ссылку на выбранную Web-службу.
После этого Visual Studio загрузит описание сервиса и сгенерирует полномочный класс, который обеспечит взаимодействие между вашим приложением и Web-сервисом.
Дважды щелкните кнопку Преобразовать на форме WebForm1, чтобы создать обработчик события нажатия кнопки.
Доступ к Web-сервису из приложения клиента
После того, как в проекте добавлена ссылка на Web-сервис, появляется возможность создать экземпляр класса Web-службы (proxy class). Это даст возможность обращаться к методам Web-службы тем же способом, каким осуществляется обращение к методам любого объекта.
Сначала мы создадим экземпляр Web-службы, Затем, взяв значение из текстовых полей TextBox1 и TextBox2, вызовем метод Convert Web-службы. Результаты расчетов, выполненных в Web-службе, поместим в элемент управления Label4.
Для обращения к Web-службе в обработчике события нажатия кнопки напишите следующий код (листинг 7.2).
Листинг 7.2
' Visual Basic
Private Sub Button1_Click(ByVal sender As Object,^ ByVal e as EventArgs) Handles Button1.Click
Dim ws As New TempConvertClient1.localhost.Service1() Dim Sum As Double Dim Kur As Double
Sum=Convert.ToDouble(TextBox1.Text)
Kur=Convert.ToDouble(TextBox2.Text)
Labe14.Text=ws.Convert(Sum, Kur) End Sub // C# protected void Button1_Click (System.Object sender, System.EventArgs e) { TempConvertClient1.localhost,Service1 ws=newъ
TempConvertClient1.localhost.Service1 ();
double Sum=Convert.ToDouble(TextBox1.Text);
double Kur=Convert.ToDouble(TextBox2.Text); Label4.Text=ws.Convert(Sum, Kur);
}
Примечание
Имя класса Web-службы, сгенерированного при добавлении Web-ссылки, может отличаться от приведенного выше имени Service1.
Итак, мы закончили работу над приложением-клиентом, которое обращается к Web-сервису. Теперь можно проверить работу этого приложения. Для тестирования приложения выполните следующие действия.
Выберите форму webForm1 в Solution Explorer.
В меню Project выберите Web Project и нажмите Set as Start Page. Или щелкните правой кнопкой мыши на WebForm1.aspx в Solution Explorer, и затем выберите в контекстном меню Set as Start Page.
Сохраните проект.
Запустите приложение, нажав кнопку Start, и проверьте его работу (рис. 7.18).
Рис. 7.18. Результаты работы Web-сервиса, возвращенные приложению-клиенту
Использование общедоступных Web-сервисов через сеть Интернет
Теперь попробуем воспользоваться функциональными возможностями Web-сервисов, имеющихся в сети Интернет. В качестве примера используем достаточно простой с точки зрения функциональности Web-сервис компании PROMT. Данный сервис обеспечивает возможность перевода текста. При этом совершенно неважно, какой язык программирования вы исполь-
зуете для создания приложения-клиента, и какая операционная система установлена на вашем компьютере.
Мы не будем создавать новое приложение, а несколько модернизируем приложение, созданное в предыдущем разделе, для чего выполните следующие действия.
Примечание j
Ваш компьютер должен быть подключен к сети Интернет. Если вы не имеете выхода в Интернет, то выполнение следующих шагов не имеет смысла.
Добавьте на форму две метки, два текстовых поля и одну кнопку. Расположите их на форме в соответствии с рис. 7.19, и измените их свойства Text в соответствии с табл. 7,2.
Рис. 7.19. Расположение элементов управления на форме
Таблица 7.2, Свойства Text элементов управления
Элемент
Значение свойства
Label5
Английский
Label6
Русский
Label7
(Пусто)
TextBox3
(Пусто)
Button2
Перевести
В меню Project выберите Add Web Reference.
В поле Address диалогового окна Add Web Reference введите URL, чтобы получить описание Web-службы, к которой необходимо обратиться: http://www.gotdotnet.ru/webservices/promt/translate/simplesvc.asmx.
Добавьте программный код в обработчик события нажатия кнопки Button2. В частности, объявите новую объектную переменную translator. Далее используйте эту переменную для вызова метода Web-
сервиса TranslateText, У этого метода есть 3 параметра. Первый параметр — текстовая строка (переводимый текст), второй параметр — направление перевода (о — с русского на английский, 1 — с английского на русский). Третьему параметру присвойте значение 0. Результаты перевода присвойте текстовой строке TextBox3. Текст программного кода приведен в листинге 7.3.
j Листинг 7.3
' Visual Basic
Private Sub Button2_Click(ByVal sender As Object,S>
ByVal e аз EventArgs) Handles Button1.Click
Dim translator As New
ru.gotdotnet.www.SimpleTranslateServise()
Label7.Text=translator.TranslateText(TextBox3.Text, 0, 0)
End Sub
// C#
protected void Button2_Click (System.Object sender, System.EventArgs e)
{
ru.gotdotnet.www.SimpleTranslateServise translator=newъ
ru.gotdotnet.www.SimpleTranslateServise();
Label7.Text=translator.TranslateText(TextBox3.Text, 0, 0);
}
Запустите приложение. В текстовом поле TextBox3 напечатайте любое английское слово и нажмите кнопку Перевести. Через несколько секунд (это зависит от скоростных характеристик используемого канала связи) вы получите русский перевод введенного слова.
Итак, мы в своем приложении использовали функциональные возможности другой программы, написанной другой командой программистов, на другом языке, находящейся на другом компьютере сети Интернет. При этом написали всего две строчки программного кода.
В данной главе мы создали простейшие Web-сервисы, выполняющие элементарные операции. При создании распределенных приложений требуется реализация более сложных функций и работа с удаленными базами данных. Этому вопросу будет посвящена следующая глава.
ГЛАВА 8
Доступ к базам данных через Web-сервисы
В распределенных приложениях на уровне Web-серверов можно реализовать все процедуры, обеспечивающие взаимодействие пользователей с базами данных, что в значительной степени облегчает разработку и отладку клиентской части приложений- Кроме того, появляется возможность создания своеобразных универсальных программных модулей, функциональность которых может быть использована в других приложениях. Это в частности могут быть элементы различных информационно-справочных систем (торговых и транспортных компаний, гостиничных и туристических фирм, библиотек и т. п.). В данной главе мы познакомимся с технологией реализации многоуровневых распределенных приложений, ядром которых являются Web-сервисы. Из материалов данной главы вы узнаете:
Q структуру распределенных приложений и этапы их создания;
Q как реализовать бизнес-логику распределенного приложения на базе Web-сервиса;
Q как реализовать доступ к Web-сервисам из Windows-приложений;
Q как можно работать с удаленными базами данных через Web-сервисы из Web-приложений.
Распределенные приложения
В первом разделе мы рассмотрим последовательность создания многоуровневых распределенных систем, которые работают с базами данных из традиционных Windows-приложений и через Интернет-браузер (на уровне "тонкого" клиента).
В данном примере мы создадим многоуровневое распределенное приложение. Оно будет состоять из трех логических уровней: данные, бизнес- логика, интерфейс пользователя. Уровень данных — база данных (в нашем примере SQL-сервер), включающая таблицы, представления, хранимые процедуры, триггеры и т. п. Бизнес-логика обеспечивает доступ к данным, это своеобразный посредник между базой данных и приложением- клиентом. Бизнес-логика будет реализована в виде Web-сервиса. Интерфейс пользователя позволяет отобразить информацию, полученную из базы данных, а также дает возможность пользователю манипулировать полученными данными (добавление, удаление и модификация записей). На рис. 8.1. представлена архитектура трехуровневого распределенного приложения.
DataGridDataGrid
DataGrid
DataGrid
КлиентWeb-приложение
Web-форма
DataSet (Authors 1)
Рис. 8.1. Архитектура трехуровневого распределенного приложения
Приложение, которое мы будем создавать — это обычное приложение для работы с данными (поиск и редактирование информации). Сначала мы разработаем Web-сервис, который обеспечит подключение к базе данных, выполнение процедур выборки и обновления данных. Затем последовательно построим приложения-клиенты, которые не будут напрямую обращаться к базе данных, а взаимодействовать с ней путем вызова соответствующих методов Web-сервиса. Клиентами будут выступать Windows-приложение и Web-приложение. Для упрощения примера мы будем работать только с од-
ной таблицей authors база данных Pubs, которая поставляется вместе с SQL-сервером. Для Web-приложения мы будем использовать Web-форму, которая является совместимой со стандартом HTML версии 3.2 и выше. Для Windows-приложения мы будем использовать обычную Windows-форму. В обоих случаях приложение-клиент будет обращаться к одному и тому же Web-сервису, который вернет приложению содержимое таблицы authors из базы данных Pubs. После того, как пользователь выполнит модификацию полученной информации, тот же Web-сервис обновит содержимое базы данных. Коммуникация Web-сервиса с приложениями-клиентами будет осуществляться с использованием протоколов HTTP и формата XML.
Чтобы реализовать данный пример вам необходимо:
Q Иметь установленную базу данных Pubs на SQL-сервере или на локальном компьютере;
Q Иметь основные понятия модели доступа к данным в Visual Studio .NET.
•
Этапы создания
распределенныхприложений
При разработке многоуровневого распределенного приложения необходимо последовательно создавать элементы каждого уровня. Начинать нужно с уровня данных, затем реализовывать бизнес-логику (средний уровень) и, наконец, разрабатывать интерфейс пользователя. Для этого примера вся работа на первом уровне уже выполнена (мы будем работать с готовой базой данных). Поэтому свою работу начнем с создания бизнес-логики (XML Web-сервиса), а затем сформируем два интерфейса пользователя (Web- форму и Windows-форму).
На примерах главы мы последовательно познакомимся со следующими шагами создания распределенных приложений.
Создание объектов бизнес-логики (среднего уровня):
создание проекта ASP.NET Web Service;
создание и конфигурирование соединения с базой данных и схемы набора данных;
заполнение набора данных и передача его приложению-клиенту из объекта среднего уровня.
Создание интерфейса пользователя:
Создание интерфейса пользователя для Windows-приложения;
Создание интерфейса пользователя Web-приложения.
Развертывание созданных программ.
Реализация бизнес-логики распределенных приложений на основе Web-сервиса
Бизнес-логика, созданная в данном примере, будет работать на Web-сервере. Кроме того, мы реализуем ее в виде XML Web-сервиса, а значит, клиенты смогут использовать стандартные Интернет-протоколы, чтобы связаться с нашим бизнес-объектом из любой платформы. Разработанный Web-сервис будет обеспечивать подключение к базе данных и формирование набора данных, который будет передаваться приложению-клиенту, где эти данные могут быть представлены как для просмотра, так и для редактирования.
В нашем Web-сервисе будет реализовано два метода. Первый, GetAuthors, сформирует набор данных и возвратит его приложению-клиенту. Второй, UpdateAuthors, вернет в базу данных те изменения, которые сделает пользователь в приложении-клиенте. Чтобы обеспечить работу этих методов будет создано несколько объектов для работы с базой данных. В частности набор данных — DataSet, адаптер данных — DataAdapter, соединение с базой данных — Connection - И несколько команд данных — DataCommand — для выборки информации и модификации базы данных. На рис. 8.2 приведены основные компоненты Web-сервиса.
Рис. 8.2. Основные компоненты Web-сервиса и его место в трехуровневом приложении
Создание проекта Web-сервиса
Итак, приступим к реализации Web-сервиса, который будет являться своеобразным посредником между базой данных и приложением-клиентом. Для создания проекта Web-сервиса выполните следующие действия.
В менюFileвыберитеподменюNewи щелкнитемышьюнапункте
Project для вывода диалогового окна New Project.
В зависимости от языка, который вы собираетесь использовать, выберите Visual Basic Projects или Visual C# Projects в дереве Project Types, затем выберите ASP.NET Web Service в области Templates.
В текстовом поле Location введите имя Web-сервера и имя проекта http://ServerName/AuthorsWebService и затем нажмите кнопку ОК (рис. 8.3).
Рис. 8.З. Окно создания проекта Web-сервиса
Примечание
Если Web-сервер находится на вашем локальном компьютере, то в качестве имя сервера введите localhost. Если Visual Studio не смог создать ASP.NET- проект для вашего Web-сервиса, то необходимо посмотреть протокол ошибок в диалоговом окне Web Access Failed и принять меры по их устранению (обычно это связано с настройками IIS сервера или браузера).
Будет создан проект с именем AuthorsWebService и файл с именем Service1.asmx, куда вы будете вносить нужный программный код.
В Solution Explorer дважды щелкните левой кнопкой мыши на файле Service1.asrnx, чтобы выделить его.
В окнеPropertiesнайдитесвойствоNameи сменитеимясервисас
Service1 на AuthorsService (рис. 8.4).
Рис. 8.5, Изменение имени базового файла Web-сервисаРис. 8.5, Изменение имени базового файла Web-сервисаВ Solution Explorer щелкните правой кнопкой мыши на файле Service1.asmx, в контекстном меню выберите Rename и смените имя файла на AuthorsService.asmx (рис. 8.5).
Рис. 8.5, Изменение имени базового файла Web-сервиса
Рис. 8.5, Изменение имени базового файла Web-сервиса
I Рис. 8.4. Изменение имени Web-сервиса в окне Properties
На следующем шаге мы добавим к Web-сервису два объекта: SqlDataAdapter И SqlConnection. Объект SqlConnection обеспечивает соединение с базой данных, адаптер данных SqiDataAdapter делает выборку записей из базы данных и помещает их в объект DataSet. Адаптер данных также обеспечивает обновление базы данных теми изменениями, которые пользователь сделает в наборе данных. .
Создание соединения с базой данных и адаптера данных
Для создания соединения с базой данных и адаптера данных выполните следующие действия.
Выделите мышью окно Server Explorer.
Примечание
По умолчанию окно Server Explorer расположено в левой части экрана дизайнера в виде вкладки. Если эта вкладка не видна, то в меню View выберите опцию Server Explorer.
Если вы уже ранее создавали соединение с базой данных Pubs, то шаги 2-6 можно пропустить.
В окне Server Explorer щелкните правой кнопкой мыши на узле Data Connections и выберите в контекстном меню пункт Add Connection. После этого откроется окно формирования параметров соединения с базой данных - Data Link Properties (рис. 8.6).
Рис. 8.6. Окно формирования параметров соединения с базой данных
На вкладке Подключение (Connection) диалогового окна Свойства связи с данными (Data Link Properties), введите имя вашего SQL-сервера, где установлена база данных Pubs. Если SQL-сервер установлен непосредственно на вашем компьютере, то введите local.
Выберите Учетные сведения Windows NT (Use Windows NT Integrated se
curity).
Примечание
Если на вашем компьютере отсутствует интегрированная защита Windows NT Integrated security, то обратитесь к сетевому администратору.
Выберите из списка базу данных Pubs.
Нажмите кнопку Test Connection для проверки правильности введенной информации и затем нажмите кнопку ОК для создания объекта Connection.
В окне Server Explorer появится новый элемент в узле Data Connections, обеспечивающий доступ к базе данных Pubs (рис. 8.7).
Примечание
Если возникнут проблемы с подключением к базе данных, обратитесь к вашему администратору базы данных.
В окне Server Explorer разверните узел для созданного элемента connection и затем разверните узел с таблицами базы данных Tables.Найдите таблицу authors и разверните ее, чтобы показать имеющиеся в ней поля.Используя сочетание клавиш <CTRL>+<Click>, выделите поля au_id, au_lname, au_fname и city (рис. 8.8).В окне Server Explorer разверните узел для созданного элемента connection и затем разверните узел с таблицами базы данных Tables.Найдите таблицу authors и разверните ее, чтобы показать имеющиеся в ней поля.Используя сочетание клавиш <CTRL>+<Click>, выделите поля au_id, au_lname, au_fname и city (рис. 8.8).Рис. 8.7. Доступные соединения с базами данныхв окне Server ExplorerРис. 8.7. Доступные соединения с базами данныхв окне Server ExplorerРис. 8.8. Доступ к полям таблицы базы данныхв окне Server ExplorerРис. 8.8. Доступ к полям таблицы базы данныхв окне Server Explorer
В окне Server Explorer разверните узел для созданного элемента connection и затем разверните узел с таблицами базы данных Tables.
Найдите таблицу authors и разверните ее, чтобы показать имеющиеся в ней поля.
Используя сочетание клавиш <CTRL>+<Click>, выделите поля au_id, au_lname, au_fname и city (рис. 8.8).
В окне Server Explorer разверните узел для созданного элемента connection и затем разверните узел с таблицами базы данных Tables.
Найдите таблицу authors и разверните ее, чтобы показать имеющиеся в ней поля.
Используя сочетание клавиш <CTRL>+<Click>, выделите поля au_id, au_lname, au_fname и city (рис. 8.8).
Рис. 8.7. Доступные соединения с базами данных
в окне Server Explorer
Рис. 8.7. Доступные соединения с базами данных
в окне Server Explorer
Рис. 8.8. Доступ к полям таблицы базы данных
в окне Server Explorer
Рис. 8.8. Доступ к полям таблицы базы данных
в окне Server Explorer
Перетащите выделенные поля из Server Explorer на окно дизайнера проекта. На панели дизайнера появятся два объекта SqlConnection1 и SqlDataAdapter1 (рис. 8.9).
St»г Page AuthorsService...*.vb [Design]* |
^l SqfConnection 1^ SqlDataAdapter 1
Рис. 8.9. Объекты SqIConnection1 и SqlDataAdapter1в окне дизайнера Web-сервиса
Эти компоненты сконфигурированы для того, чтобы обеспечить передачу информации между набором данных, который будет создан чуть позже, и таблицей authors базы данных Pubs.
Для работы в сетях вы должны сконфигурировать параметры защиты вашего проекта — организовать интегрированную защиту (Integrated Security). Для этого необходимо отключить анонимный доступ (anonymous access) и включить персональный доступ (impersonation). Эта процедура описана в следующем разделе. Если вы работаете на домашнем компьютере или вне сети, то следующий раздел можно пропустить.
Конфигурирование интегрированной идентификации
Чтобы сконфигурировать интегрированную идентификацию, необходимо изменить некоторые файлы и параметры проекта, используя Internet Information Services.
Запустите Internet Information Services. Этот сервис можно запустить из Администрирование (Administrative Tools) панели управления Windows (для более подробной информации о запуске данного инструмента см. документацию по операционной системе Windows).
Разверните узел вашего Web-сервера.
Разверните узел Веб узел по умолчанию (Default Web Site) (рис. 8.10).
Рис. 8.10. Окно управления компьютером
Щелкните правой кнопкой мыши на узле AuthorsWebService и в контекстном меню выберите пункт Properties.
В открывшемся окне переключитесь на вкладку Безопасность каталога - (Directory Security).
Нажмите кнопку Изменить (Edit) в разделе Анонимный доступ и проверка подлинности (Anonymous access and authentication control), который изображен на рис. 8.11.
Рис. 8.11. Конфигурирование анонимного доступаРис. 8.11. Конфигурирование анонимного доступа
Рис. 8.11. Конфигурирование анонимного доступа
Рис. 8.11. Конфигурирование анонимного доступа
Снимите флажок Анонимный доступ (Anonymous Access).Установите флажок Встроенная проверка подлинности (Integrated Windows authentication), который виден на рис. 8.12.Снимите флажок Анонимный доступ (Anonymous Access).Установите флажок Встроенная проверка подлинности (Integrated Windows authentication), который виден на рис. 8.12.WindowsWindows
Снимите флажок Анонимный доступ (Anonymous Access).
Установите флажок Встроенная проверка подлинности (Integrated Windows authentication), который виден на рис. 8.12.
Снимите флажок Анонимный доступ (Anonymous Access).
Установите флажок Встроенная проверка подлинности (Integrated Windows authentication), который виден на рис. 8.12.
Windows
Windows
Рис. 8.12. Окно конфигурирования проверки подлинности доступа к ресурсамРис. 8.12. Окно конфигурирования проверки подлинности доступа к ресурсам
Рис. 8.12. Окно конфигурирования проверки подлинности доступа к ресурсам
Рис. 8.12. Окно конфигурирования проверки подлинности доступа к ресурсам
Вернитесь к вашему проекту в Visual Studio, дважды щелкните на файле
Web.config в окне Solution Explorer.
Добавьте следующий тег после строки <system.web>, которая говорит, что сконфигурирована интегрированная защита для вашего Web- сервиса.
<identity impersonate="true"/>
Создание определения класса набора данных DataSet
В нашем Web-сервисе необходимо создать набор данных DataSet, который будет являться своеобразным промежуточным хранилищем информации между базой данных и приложением-клиентом. Для добавления объекта DataSet выполните следующие действия.
В Solution Explorer дважды щелкните на файле AuthorsService.asmx, чтобы перейти на связанную с ним вкладку окна дизайнера.
В меню Data выберите пункт Generate DataSet. В открывшемся диалоговом окне Generate Dataset выберите строку New и введите имя набора данных authors1. He устанавливайте флажок Add this dataset to the designer, он должен быть опущен (рис. 8.13).
Рис. 8.13. Окно создания объекта DataSet
Примечание
К проекту будет добавлен файл со схемой набора данных authors1.xsd. Этот файл содержит определение класса authors1, он является наследником класса DataSet и содержит описание набора данных для таблицы authors.
Сохраните проект, выбрав в меню File пункт Save All.
Итак, мы включили в приложение набор компонентов, необходимых для взаимодействия с базой данных. Теперь необходимо реализовать функциональность Web-сервиса, т.е. сформировать его методы. Эти методы должны обеспечить взаимодействие приложений клиентов с созданным нами набором данных.
Представление набора данных другим приложениям
На следующем этапе реализации примера мы должны сделать доступным наш набор данных для других приложений, причем это могут быть как Windows-приложения, работающие в рамках локальной сети, так и Web- приложения. Мы сформируем два метода: один для выборки информации из базы данных и передачи ее приложению клиенту— GetAuthors, второй для возврата в базу данных тех изменений, которые сделает пользователь в Полученных данных — UpdateAuthors.
Для формирования методов Web-сервиса выполните следующие действия.
В Solution Explorer дважды щелкните на объекте AuthorsService, если он еще не выделен в окне дизайнера.
В меню View нажмите Code для активизации окна редактора программного кода.
Добавьте метод с именем GetAuthors, который передаст набор данных программе клиенту.
Данный метод создает объектную переменную authors (набор данных на основе базового класса authors1) и заполняет его записями из таблицы authors через объект SqiDataAdapter. Далее набор данных возвращается приложению-клиенту. Программный код метода приведен в листинге 8.1.
Листинг 8.1
' Visual Basic
<WebMethod> Public Function GetAuthors() As authors1
Dim authors As New authors1()
SqlDataAdapter1.Fill(authors)
Return authors
End Function
// C#
[WebMethod]
public authors1 GetAuthors()
{
authors1 authors=new authors1();
SqlDataAdapter1.Fill(authors) ;
return authors;
}
Добавьте метод с именем UpdateAuthors, который будет передавать изменения, сделанные пользователем в приложении-клиенте, назад к базе данных.
Данный метод имеет один параметр — набор данных author Changes, созданный на основе набора данных authors1. authorChanges содержит только измененные записи набора данных authors1 , и метод SqlDataAdapter.Update Использует набор данных Для модификации базы данных. Кроме того, набор данных authorChanges возвращается клиенту. Приложение-клиент будет использовать этот возвращаемый набор данных, чтобы модифицировать собственный экземпляр набора данных authors1. Программный код метода приведен в листинге 8.2.
Листинг 8.2
' Visual Basic
<WebMethod> Public Function UpdateAuthors(ByVal authorChanges
As authors1) As authors1
If Not (authorChanges Is Nothing) Then
SqlDataAdapter1.Update(authorChanges)
Return authorChanges
Else
Return Nothing
End If
End Function
// C#
[WebMethod]
public authors1 UpdateAuthors(authors1 authorChanges)
{
if (authorChanges != null)
{
SqlDataAdapter1.Update(authorChanges);
return authorChanges;
}
else
{ return null;
}
}
Примечание
В реальных приложениях в программный код этих методов необходимо добавить обработчик возможных ошибок.
В меню File выберите Save All.
В меню Build выберите Build Solution.
Итак, мы создали бизнес-логику среднего уровня трехуровневого распределенного приложения. Наш бизнес-объект содержит набор данных, соединение с базой данных SQL-сервера, два метода GetAuthors и UpdateAuthors, к которым можно обратиться из любых приложений-клиентов.
Вы можете проверить корректность работы метода GetAuthors, для чего щелкните правой кнопкой мыши на файле AuthorsService.asmx и в контекстном меню выберите пункт Build and Browse. В результате будет сгенерирована страница с описанием методов этого Web-сервиса (рис. 8.14).
Нажмите ссылку на метод GetAuthors. В результате будет выведено окно тестирования данного метода (рис. 8.15).
Рис. 8.15. Тестовая страница проверки метода GetAuthors
Нажмите на кнопку Invoke — Web-сервис сформирует набор данных в виде XML-документа (его фрагмент приведен на рис. 8.16).
ervice.asmx.vb , ’&«» - AuthorsService Web Service http://localhost.../GetAuthor$? | < b X
.Miiiru^ ттир-.у; nmmeiupui i.ui g/ uucriurj-x;стч ^
«authors diffgr:id=*authorsl" msdata:rowOrder="O,l>
<au_id> 172-32-1176</aujd>
<au_lname>White«/au_lname> <au_fname>Johnson«/au_fhame> <city>Menlo Park«/city>
</authors>
<authors diffgr:id=’outhors2" msdata:rowOrder=*V>
<au_id>213-46-8915</au_id>
<au_lname>Green</au_lname> <au_fname>Marjorie</au_fname> <city>Oakland</city>
</authors>
«authors diffgr:id=“authors3" msdata:rowOrder=*2*>
<au_id>238-95-7766</au_id>
<auJname>Carsonc/auJname>
<au_fname>Cheryl</au_fname>
<city>Berkeley</city>
</authors>
<>
Этот XML-документ будет передан приложению-клиенту, где данные будут преобразованы из XML-формата к виду, удобному для их отображения, просмотра и редактирования. Теперь перейдем к созданию приложения- клиента.
Виды приложений — клиентов Web-сервисов
Существует два варианта создания интерфейса пользователя: с использованием традиционных Windows-форм для работы в локальных сетях и с использованием Web-форм для работе в Интернете. Причем с Web-формами можно работать как в локальных, так и в глобальных сетях. Далее будут рассмотрены оба эти варианта как отдельные проекты.
Доступ к Web-сервисам из Windows-приложений
Приложения с Windows-интерфейсом позволяют использовать мощности и возможности клиентского компьютера для решения некоторой части логики прикладной задачи. Вообще, Windows-интерфейс обеспечивает более богатые функциональные и визуальные возможности, чем Web-интерфейс. Обеспечивается меньшая загрузка сервера, чем при работе с Web- приложениями, потому что сервер может быть освобожден от выполнения некоторых частей прикладной задачи. Кроме того, Windows-приложение может активно использовать ресурсы локального компьютера, доступные через операционную систему (например, запросы к файловой системе и системному реестру). Основные компоненты Windows-формы и ее место в трехуровневом приложении приведены на рис 8.17.
В нашем примере Windows-приложение будет состоять из одной Windows- формы и содержать ссылку на Web-сервис AuthorsWebService. Информация из базы данных будет отображена в элементе управлении DataGrid. Для загрузки данных создадим кнопку Загрузить. При нажатии этой кнопки будет производиться вызов метода GetAuthors созданного нами Web-сервиса. Элемент управления DataGrid позволит нам отобразить полученную информацию и выполнять прямое редактирование данных, с передачей этих изменений к связанному с ним набору данных. На форме создадим еще одну кнопку Сохранить. При нажатии данной кнопки будет вызван метод UpdateAuthors нашего Web-сервиса, который вернет эти изменения назад в базу данных.
ТаблицыТаблицыБДБДПредставления
Таблицы
Таблицы
БД
БД
Хранимые процедуры
Рис. 8.17. Основные компоненты Windows-формы и ее место в трехуровневом приложенииРис. 8.17. Основные компоненты Windows-формы и ее место в трехуровневом приложенииТриггеры
Рис. 8.17. Основные компоненты Windows-формы и ее место в трехуровневом приложении
Рис. 8.17. Основные компоненты Windows-формы и ее место в трехуровневом приложении
Создание Windows-приложения
При создании приложения-клиента разработчику нет необходимости знать, где и в каком виде хранятся данные, не нужно создавать ни объектов подключения, ни взаимодействия с таблицами базы данных. Все эти функции уже реализованы на уровне Web-сервиса. Разработчик должен знать только перечень методов Web-сервиса и набор параметров каждого метода.
Для создания Windows-приложения, использующего функциональные возможности Web-сервиса, выполните следующие действия.
В меню File выберите Add Project и нажмите New Project для открытия диалогового окна Add New Project.
В зависимости от того, какой язык программирования вы хотите использовать, выберите в дереве Project Types пункт Visual C# Projects или Visual Basic Projects, затем в области Templates выберите Windows Application.
Назовите проект AuthorsWinClient, выберите местоположение проекта и нажмите кнопку ОК (рис. 8.18).
Рис. 8.18, Окно создания Windows-приложения
В результате этих действий будет сгенерирован проект AuthorsWinClient, к нему автоматически добавиться Windows-форма с именем Form1, которая будет отображена в окне дизайнера форм.
Добавьте ссылку к Web-сервису, который мы создали ранее:
в Solution Explorer щелкните правой кнопкой мыши на проекте AuthorsWinClient и затем выберите в контекстном меню Add Web Reference;
введите местоположение базового файла вашего Web-сервиса в поле Address в верхней части диалогового окна Add Web Reference: http://ServerName/AuthorsWebService/AuthorsService.asmx.
Если Web-сервер находится па вашем локальном компьютере, то эта строкадолжнавыглядетьследующимобразом:
http://localhost/AuthorsWebService/AuthorsService.asmx.
Затем нажмите клавишу <ENTER> (рис. 8.19).
Нажмите кнопку Add Reference.
После добавления ссылки на Web-сервис мы сможем создать экземпляр набора данных authors1 в нашем клиентском приложении.
Теперь необходимо добавить на форму компоненты, которые позволять конечному пользователю работать с данными, полученными от Web- сервиса.
Рис. 8.19. Окно формирования Web-ссылки на Web-сервис
Добавление к форме элементов управления
Для взаимодействия с данными нам понадобятся следующие элементы:
Q две кнопки — для получения информации из базы данных и для возврата изменений, сделанных пользователем;
Q элемент управления DataGrid для отображения и редактирования данных;
Q набор данных DataSet для хранения информации в памяти компьютера клиента.
Для добавления и конфигурирования этих элементов выполните следующие действия.
ИзвкладкиWindowsFormsокнаToolboxперетащитенаформуэлемент
управления DataGrid.
Из вкладки Windows Forms окна Toolbox перетащите на форму элемент управления Button. Присвойте свойству кнопки Name значение LoadData И СВОЙСТВУ Text Значение Загрузить.
Из вкладки Windows Forms окна Toolbox перетащите на форму элемент управления Button. Присвойте свойству кнопки Name значение SaveData И СВОЙСТВУ Text значение Сохранить.
Из вкладки Data окна Toolbox перетащите на форму объект DataSet. В появившемся диалоговом окне Add DataSet установите тип набора данных Typed dataset и выберите из выпадающего списка Name значение AuthorsWinClient.ServerName.authors1.Таким образом мы создали объект
DataSet, который базируется на классе набора данных authors1 (рис. 8.20).
Choose a typed or untyped dataset to add to the designer.
<• Typed dataset
Name:[AuthorsWinflient .localhostauthorsl-r]
Creates an instance of a typed dataset class already in your project. Choose this option to work with a dataset that has a built-in schema. See Help fa details on generating typed datasets.
Г Untyped dataset
Creates an Instance of an untyped dataset class of type System.Data.DataSet.
Choose this option when you want a dataset with no schema.
OKCancelHelp
Рис. 8.20. Окно создания объекта DataSet в приложении-клиенте Web-сервиса
Выделите объект Dataset и смените ему имя — свойству Name присвойте значение AuthorData (рис. 8.21).
Рис. 8.21. Изменение имени объекта DataSet
Выделите элемент управления DataGrid. Для свойства DataSource задайте имя источника данных — выберите из выпадающего списка значение AuthorData. Для свойства DataMember задайте имя таблицы базы данных, выбрав значение authors из выпадающего списка (рис. 8.22).
Заголовкам столбцов элемента управления DataGrid будут присвоены значения имен полей таблицы authors. Расположите элементы управления на форме в соответствии с рис. 8.23.
Рис. 8.22. Связывание элемента управления DataGrid с источником данных
Рис. 8.23. Расположение элементов управления на форме приложения
На этом этапе у нас готовы все компоненты, необходимые для приема и работы с данными. Теперь необходимо сформировать программный код, который будет обеспечивать загрузку и обновление данных.
Программный код загрузки и обновления данных
Программный код загрузки данным поместим в обработчик события нажатия кнопки Загрузить. Для этого необходимо выполнить следующие действия.
В меню View выберите пункт Designer. Дважды щелкните на кнопке LoadData, чтобы создать модуль обработчика события click. В обработчике события сначала необходимо создать экземпляр класса Web- сервиса, а затем нужно вызывать его метод. Для кнопки, которую мы сейчас конфигурируем, нужно вызвать метод GetAuthors. Полученные из Web-сервиса записи поместим в набор данных AuthorData, связан-
ный с объектом отображения данных DataGrid. Свойство Credentials Web-сервиса используется, чтобы передать ваш идентификатор к Web- сервису, который в свою очередь передает этот параметр на сервер базы данных. Добавьте программный код, показанный в листинге 8.2, в обработчик события нажатия кнопки.
Примечание
Если Web-сервер работает не на вашем локальном компьютере, то необходимо заменить имя localhost в примере кода на имя используемого Web- сервера.
Листинг 8.2
' Visual Basic
Private Sub LoadData__Click (ByVal sender As System.Object,Ъ
ByVal e As System.EventArgs) Handles LoadData.Click
Dim ws As New AuthorsWinClient.localhost.AuthorsService()
ws.Credentials=System.Net.CredentialCache.DefaultCreclentials
AuthorData.Merge(ws.GetAuthors())
End Sub
// C#
private void LoadData_Click(object sender, System.EventArgs e)
I
AuthorsWinClient.localhost.AuthorsService ws =ъ
new AuthorsWinClient.localhost.AuthorsService();
ws.Credentials=System.Net.CredentialCache.DefaultCredentials;
AuthorData.Merge(ws.GetAuthors());
}
В меню View нажмите Designer. Дважды щелкните на кнопке SaveData, чтобы создать обработчик события Click.
Если пользователь внес какие-либо изменения в полученный набор данных, то их нужно вернуть источнику (базе) данных. Для этой цели мы сформируем новый объект DataSet с именем diffAuthors (на основе набора данных authors1), и заполним его только измененными записями. Этот набор данных передадим методу UpdateAuthors Web-сервиса, который внесет эти изменения в базу данных. Кроме того, сделанные изменения передадим и в набор данных AuthorData, чтобы и в нем отразить изменения пользователя.
Примечание j
В реальных приложениях необходимо рассматривать и вопросы параллельной обработки одних и тех же записей несколькими пользователями.
Добавьте следующий программный код в обработчик события нажатия кнопки обновления данных (листинг 8.3).
Листинг 8,3 i...- i
' Visual Basic
Private Sub SaveData_Click(ByVal sender As System.Object, Ъ
ByVal eAs System.EventArgs) Handles SaveData.Click
If AuthorData.HasChanges() Then
Dim ws As New AuthorsWinClient.localhost;AuthorsService()
ws.Credentials=System.Net.CredentialCache.DefaultCredentials
Dim diffAuthors As New AuthorsWinClient.localhost.authors1()
diffAuthors.Merge(AuthorData.GetChanges())
diffAuthors=ws.UpdateAuthors(diffAuthors)
AuthorData.Merge{diffAuthors)
End If
End Sub
// C#
private void SaveData_Click(object sender, System.EventArgs e)
{
if (AuthorData.HasChanges())
{
AuthorsWinClient.localhost.AuthorsService ws =ъ
new AuthorsWinClient.localhost.AuthorsService();
ws.Credentials=System.Net.CredentialCache.DefaultCredentials;
AuthorsWinClient.localhost.authors1 diffAuthors%>
=new AuthorsWinClient.localhost.authors1();
diffAuthors.Merge(AuthorData.GetChanges());
diffAuthors=ws.UpdateAuthors(diffAuthors);
AuthorData.Merge(diffAuthors);
}
}
Тестирование приложения
Для тестирования данного приложения выполните следующие действия.
В меню File выберите Save All.
В Solution Explorer выделите AuthorsWinClient, щелкните на нем правой кнопкой мыши и выберите Set as Startup Project.
Нажмите <CTRL<+<F5> для запуска приложения.
Будет отображено окно с пустым объектом DataGrid.
Нажмите кнопку Загрузить, чтобы заполнить таблицу данными, сделайте некоторые изменения в колонках таблицы и затем нажмите кнопку Сохранить (рис. 8.24).
Рис. 8.24. Внешний вид формы на этапе исполнения
Если все было сделано правильно, все ваши изменения окажутся внесенными в таблицу базы данных.
В следующем разделе мы реализуем приложение с теми же функциями, но
на основе Web-интерфейса.
Доступ к Web-сервисам из Web-приложений
Реализация приложения на основе Web-интерфейса обеспечивает его работу на любых клиентских компьютерах и браузерах. Вся обработка информации выполняется на Web-сервере, а не на компьютере клиента. В данном разделе с использованием Web-формы мы создадим Web-приложение, которое будет обращаться к тому же самому бизнес-объекту среднего уровня, что и Windows-приложение, созданное в предыдущем разделе. На рис. 8.25 пред-
ставлены основные компоненты Web-формы и ее место в трехуровневом приложении.
Рис. 8.25. Основные компоненты Web-формы и ее место в трехуровневом приложении
Создание проекта и Web-формы
Для создания приложения клиента на основе Web-формы выполните следующие действия.
В меню File откройте подменю Add Project и выберите пункт New Project.
В диалоговом окне Add New Project в дереве Project Types укажите Visual С# Projects или Visual Basic Projects, в области Templates выберите тип приложения ASP.NET Web Application.
В текстовое поле Location введите путь к Web-серверу и имя проекта http://ServerName/AuthorsWebClient,после чего нажмите кнопку ОК
(рис. 8.26).
После этого будет создан новый проект и Web-форма с именем WebForm1.aspx.
Рис. 8.26. Окно создания Web-приложения
Добавьте ссылку на Web-сервис, который мы создали ранее:
В Solution Explorer щелкните правой кнопкой на имени проекта AuthorsWebClient и выберите в контекстном меню Add Web Reference.
Введите местоположение базового файла вашего Web-сервиса в поле
Address в верхней части диалогового окна Add Web Reference: http://ServerName/AuthorsWebService/AuthorsService.asmx.
Если Web-сервер находится на локальном компьютере, то эта строка должна выглядеть следующим образом: http://localhost/AuthorsWebService/ AuthorsService.asmx. Затем нажмите клавишу <ENTER>.
Щелкните на кнопке Add Reference.
После добавления ссылки на Web-сервис, мы сможем создать экземпляр набора данных authors1 в нашем клиентском приложении. Теперь добавим на форму и сконфигурируем элемент управления DataGrid для отображения и редактирования данных, а также другие необходимые элементы управления.
Добавление к форме элементов управления
Для работы с данными нам понадобятся следующие элементы управления:
Q объект DataSet для хранения информации на компьютере клиента;
Q элемент управления DataGrid для отображения и редактирования информации.
Для добавления на форму и конфигурирования свойств элементов управления выполните следующие действия.
ИзвкладкиDataокнаToolboxперетащитенаформуобъектDataset.От
кроется диалоговое окно Choose a DataSet, в котором установите флажок TypedDataSet и выберите имя AuthorsWebClient.ServerName.authors1 из списка имен Name. Этими действиями вы добавите на форму компонент DataSet.
Выделите объект DataSet, введите в поле свойства Name этого объекта новое ИМЯ AuthorData.
Из вкладки Web Forms окна Toolbox перетащите на форму элемент управления DataGrid.
Рис. 8.27. Связывание элемента управления DataGrid с источником данныхРис. 8.27. Связывание элемента управления DataGrid с источником данныхВыделите элемент управления DataGrid. Для свойства DataSource задайте имя источника данных — выберите из выпадающего списка значение AuthorData. Для свойства DataMember задайте имя таблицы базы данных, выбрав значение authors из выпадающего списка (рис. 8.27).
Рис. 8.27. Связывание элемента управления DataGrid с источником данных
Рис. 8.27. Связывание элемента управления DataGrid с источником данных
Safe Handling Instructions
This product was prepared from Inraw and passed meat and/or poultry Sorera: products may contain bacteria that tad cause illness if the product Is mls'irrW
□ Keep rofrtganded Of frozen Thaw in refrigerator or mcruwi»e
* K?,Prnwm<«il*>dpwTry*p»Wfr.
л aother foods. М.чкГ working suifan
(including cultmg boards), ute-isS, «и hands after touching raw meet or pxi->
^■V™ Cook liocoughly
Keep hot foods hot. Retrigerafek***!
immediately or discard
REMOVE LABEL BEFORE MICROWAVING
Заголовкам столбцов элемента управления DataGrid будут присвоены значения имен полей таблицы authors. Нажмите на ссылку Auto Format в нижней части окна Properties и выберите стиль форматирования Professional 3 для объекта DataGrid (рис. 8.28).
Чтобы обеспечить возможность редактирования данных непосредственно в элементе управления DataGrid, необходимо добавить столбец с кнопками Edit, Update, Cancel, который в режиме просмотра данных будет содержать единственную кнопку Edit. Когда пользователь нажмет кнопку Edit, то в текущей строке появятся текстовые поля для редактирования данных, а кнопка Edit будет заменена кнопками update и cancel. Итак, чтобы добавить этот столбец:
нажмите ссылку Property Builder в нижней части окна Properties, в появившемся диалоговом окне выберите вкладку Columns;
разверните узел Button Column на вкладке Available Columns;
выберите элемент Edit, Update, Cancel и нажмите кнопку > (рис. 8.29).
Select a scheme:Select a scheme:Preview:Preview:Remove Auto FormatColorful 1Colorful 2Colorful 3Colorful 4Colorful 5Professional 1Professional 2Remove Auto FormatColorful 1Colorful 2Colorful 3Colorful 4Colorful 5Professional 1Professional 2Column 1| Column 2Column 1| Column 2################################Professional >Professional >Simple 1Simple 2Simple 3Classic 1Simple 1Simple 2Simple 3Classic 1#### I ######## I ###########*###############*########OKOKCancelCancelHelpHelp
Select a scheme:
Select a scheme:
Preview:
Preview:
Remove Auto Format
Colorful 1
Colorful 2
Colorful 3
Colorful 4
Colorful 5
Professional 1
Professional 2
Remove Auto Format
Colorful 1
Colorful 2
Colorful 3
Colorful 4
Colorful 5
Professional 1
Professional 2
Column 1| Column 2
Column 1| Column 2
########
########
########
########
Professional >
Professional >
Simple 1
Simple 2
Simple 3
Classic 1
Simple 1
Simple 2
Simple 3
Classic 1
#### I ####
#### I ####
#######*
########
#######*
########
OK
OK
Cancel
Cancel
Help
Help
Рис. 8.28. Выбор стиля элемента управления DataGrid
Рис. 8.29. Добавление колонок редактирования данных к элементу управления DataGridРис. 8.29. Добавление колонок редактирования данных к элементу управления DataGrid
Рис. 8.29. Добавление колонок редактирования данных к элементу управления DataGrid
Рис. 8.29. Добавление колонок редактирования данных к элементу управления DataGrid
Смените тип кнопок: в списке Button type выберите PushButton. В результате этого кнопки примут объемный вид.
Нажмите кнопку ОК.
После этих действий элемент DataGrid будет иметь следующий вид (рис. 8.30).
WebFormLaspM*[
Рис. 8.30. Внешний вид элемента управления DataGrid в окне дизайнера формы
Программный код загрузки и обновления данных
Теперь в данное приложение нужно добавить программный код для загрузки данных, редактирования полученной информации и возвращения всех обновлений в базу данных. Последовательно запрограммируем все эта действия. Начнем с загрузки данных.
Щелкните правой кнопкой мыши на форме и выберите пункт View Code. Добавьте программный код к обработчику события загрузки страницы Page_Load, который обеспечит заполнение данными элемента управление DataGrid (листинг 8.4).
^«feMeMe>w«#M*»»»#f**M»«*««wwft«* *«**••»••«««•«*•••,•••••«HWtMHWewevtMfre'fwwwHWiWHOMHWfM»»#*t<iwMiilHH»tfiH«H«*itwWMN*''*wi<w1IMHl«HtMiHHHft'n**www»wf»ffHHtw1»«yws Листинг 8.4
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object,ъ
ByVal e As System.EventArgs) Handles MyBase.Load
Dim ws As New AuthorsWebClient.localhost.AuthorsService()
ws.Credentials=System.Net.CredentialCache.DefaultCredentials
AuthorData.Merge(ws.GetAuthors())
If Not Page.IsPostBack Then
Me.DataGrid1.DataBind()
End If
End Sub
// C#
private void Page_Load(object sender, System.EventArgs e)
{
AuthorsWebClient.localhost.AuthorsService ws =ъ
new AuthorsWebClient.localhost.AuthorsService();
ws.Credentials=System.Net.CredentialCache.DefaultCredentials;
AuthorData.Merge(ws.GetAuthors());
if (! Page.IsPostBack)
{
DataGrid1.DataBind();
}
}
В обработчике события Page_Load сначала создается экземпляр Web- сервиса (объектная переменная ws). Далее присваивается значение свойству Credentials. Свойство Credentials Web-сервиса используется, чтобы передать ваш идентификатор к Web-сервису, который в свою очередь передает данный параметр на сервер базы данных. Затем набор данных AuthorData заполняется информацией путем вызова метода Merge. В качестве параметра этому методу передается метод загрузки данных GetAuthors созданного нами ранее Web-сервиса. И, наконец, набор данных AuthorData связывается с элементом управления DataGrid, который предназначен для отображения информации. Каждый раз, когда страница будет передаваться на сервер и возвращаться к пользователю, элемент DataGrid будет содержать обновленную копию записей из базы данных.
Примечание
В реализуемом примере каждый раз, когда страница будет загружаться в браузер клиента, из базы данных будет выбираться и передаваться новая копия таблицы authors. Такой режим работы не всегда является оптимальным.
Обратите внимание — чтобы показать пользователю таблицу с удаленного SQL-сервера нам потребовалось написать всего шесть строк программного кода.
Теперь сформируем программный код, который обеспечит редактирование информации. Когда пользователь нажимает кнопку Edit, то генерируется событие EditCommand элемента управления DataGrid. Используем обработчик этого события, чтобы перевести текущую строку в режим редактирования путем изменения значения свойства EditItemIndex элемента управления DataGrid — СВОЙСТВУ EditItemIndex нужно Присвоит индекс той строки, которую необходимо перевести в режим редактирования. Для реализации возможности перевода текущей строки элемента DataGrid в режим редактирования выполните следующие действия.
Создайте обработчика события EditCommand.
В Visual Basic. Щелкните правой кнопкой мыши в любом месте формы и выберите из контекстного меню View Code. В левом раскрывающемся списке редактора кода выберите DataCrid1, а в правом раскрывающемся списке — пункт EditCommand (рис. 8.31.).
."'atfigo '.Vetroor. 1. згр-. WebForml.aspx.vb* | OataGndl^ ] ^"EditConunand
hPublic Class BebFomil
| Inherits System.Web.QI.Page
Рис. 8.31. Создание обработчика события EditCommand
В Visual C#. Выделите мышью элемент управления DataGrid1. В окне Properties нажмите кнопку Events, чтобы отобразить список событий элемента DataGrid. Дважды щелкните на событие EditCommand.
Добавьте следующий программный код (листинг 8.5).
Листинг 8.5 i ......-i- J
' Visual Basic
Private SubDataGrld1_EditCommand(ByValsource As Object, ^
ByVal e As System.Web.UI.WebControls.DataGridCoramandEventArgs) 4>
Handles DataGrid1.EditCommand
DataGrid1.Editltemlndex=e.Item.ItemIndex
DataGrid1.DataBind()
End Sub
// C#
private void DataGrid1_EditCommand(object source, System.Web.UI.WebControls.DataGridCommandEveny.Args e) {
DataGrid1.EditItemIndex=e.Item.ItemIndex;
DataGrid1.DataBind();
)
Теперь создайте обработчик события CancelCommand по аналогии с созданием обработчика события EditCommand (рис. 8.32).
Рис, 8.32. Создание обработчика события CancelCommandРис, 8.32. Создание обработчика события CancelCommand
Рис, 8.32. Создание обработчика события CancelCommand
Рис, 8.32. Создание обработчика события CancelCommand
Когда пользователь нажимает кнопку Cancel, то генерируется событие CancelCommand элемента управления DataGrid. Используем обработчик этого события для того, чтобы установить свойству EditItemIndex значение -1, а текущую строку переведем в режим отображения данных. Добавим в обработчик события CancelCommand следующий программный код (листинг 8.6).
Листинг 8,6j
' Visual Basic
Private Sub DataGrid1_CancelCommand(ByVal source As Object,ъ
ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)ъ
Handles DataGrid1.CancelCommand
DataGrid1.Editltemlndex=-1
DataGrid1.DataBind()
End Sub
// C#
private void DataGrid1_CancelCommand(object source,ъ System.Web.UI.WebControls.DataGridCommandEventArgs e) {
DataGrid1. EditItemIndex=-1;
DataGrid1.DataBind();
}
Когда пользователь нажимает кнопку Update, то генерируется событие UpdateCommand элемента управления DataGrid. Используем обработчик этого события для того, чтобы все изменения, которые пользователь сделал в строке DataGrid, передать в набор данных AuthorData, а также в базу данных через Web-сервис. Создайте обработчик события UpdateCommand по аналогии с созданием обработчика события EditCommand (рис, 8.33).
Рис. 8.33. Создание обработчика события UpdateCommand
Добавьте в обработчик события UpdateCommand следующий программный код (листинг 8.7).
Листинг 8.7. -•■•■- ..-..-—
' Visual Basic
Private Sub DataGrid1_UpdateCommand(ByVal source As Object,ъ
ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)^ Handles DataGrid1.UpdateCommand
' Обновление каждого поля в строке dataset
Dim i As Integer
For i=1 To AuthorData.authors.Columns.Count
Dim t As TextBox=CType(e.Item.Cells(i).Controls(0), TextBox)
Dim row As DataRow=AuthorData.authors(e.Item.DataSetIndex) row(AuthorData.authors.Columns(i-1).Caption)=t.Text
Next
' Обновление базы данных и набора данных.
If Me.AuthorData.HasChanges() Then
Dim ws As New AuthorsWebClient.localhost.AuthorsService() ws.Credentials=System.Net.CredentialCache.DefaultCredentials Dim diffAuthors As New AuthorsWebClient,localhost.authors1() diffAuthors.Merge(Me.AuthorData.GetChanges()) ws.UpdateAuthors(diffAuthors)
AuthorData.Merge(diffAuthors)
End If
' Перевод строки в режим отображения данных DataGrid1.EditItemIndex=-1
DataGrid1.DataBind()
End Sub
// C#
private void DataGrid1_UpdateCommand(object source, ъ System.Web.UI.WebControls.DataGridCommandEventArgs e) {
// Обновление каждого поля в строке dataset
for (int i=1; i<AuthorData.authors.Columns.Count; i++)
{
TextBox t=(TextBox)(e.Item.Cells[i].Controls[0]);
DataRow row=AuthorData.authors[e,Item.DataSetIndex]; row[AuthorData.authors.Columns[i-1].Caption]=t.Text;
}
// Обновление базы данных и набора данных.
if (AuthorData.HasChanges())
{
AuthorsWebClient.localhost.AuthorsService ws=ъ
new AuthorsWebClient.localhost.AuthorsService() ;
ws.Credentials=System.Net.CredentialCache.DefaultCredentials;
AuthorsWebClient.localhost.authors1 diffAuthors =^
new AuthorsWebClient.localhost.authors1();
diffAuthors.Merge(AuthorData.GetChanges());
ws.UpdateAuthors (diffAuthors);
AuthorData.Merge(diffAuthors);
}
DataGrid1.EditItemIndex=-1;
DataGrid1.DataBind();
}
В приведенном программном коде выполняются следующие действия. Сначала организуется цикл перебора всех колонок текущей строки набора данных AuthorData. В этом цикле значения из текстовых полей текущей строки переносятся в текущую запись набора данных. Таким образом мы обновляем запись в наборе данных. Затем проверяется условие: вносились ли какие-либо изменения в набор данных AuthorData. Если условие соблюдается, то создается новый экземпляр набора данных с именем diffAuthors. Этот набор данных заполняется только измененными записями из набора AuthorData. Затем вызывается метод UpdateAuthors нашего Web-сервиса, которому в качестве параметра передается набор данных diffAuthors, который содержит только измененные пользователем записи. В результате работы метода обновления пользователя передаются в исходную таблицу базы данных. Следующим оператором обновляется и текущий набор данных AuthorData. И наконец, на последнем шаге, текущая строка элемента управления DataGrid переводится в режим редактирования.
Теперь, если вы работаете не на локальном компьютере, необходимо сконфигурировать параметры настройки защиты вашего проекта (см. раздел "Конфигурирование интегрированной идентификации").
Тестирование приложения
Для тестирования приложения выполните следующие действия.
Выберите имя проекта AuthorsWebClient в Solution Explorer. Щелкните правой кнопкой мыши на имени проекта и выберите пункт Set
as StartUp Project. Таким образом вы сделаете форму стартовой страницей.
Нажмите <CTRL>+<F5> для запуска приложения.
В разделе мы добились поставленной цели — обеспечили возможность пользователю редактировать информацию в базе данных из окна Интернет- браузера (рис. 8.34).
Рис. 8.34. Редактирование данных в элементе управления DataGridРис. 8.34. Редактирование данных в элементе управления DataGridна этапе работы приложенияна этапе работы приложения
Рис. 8.34. Редактирование данных в элементе управления DataGrid
Рис. 8.34. Редактирование данных в элементе управления DataGrid
на этапе работы приложения
на этапе работы приложения
В последнем разделе этой главы мы создали Web-приложение, которое обеспечивает получение информации с удаленного сервера и ее корректировку. При создании приложения мы не задумывались, где находится эта информация, в каком формате она храниться, какой тип СУБД установлен на удаленном сервере. Мы просто использовали два метода Web-сервиса. Причем где находится Web-сервис - в локальной сети вашей организации или на другом континенте — также не имеет принципиального значения. Однако если обмен данными осуществляется через сеть Интернет, то важным фактором, влияющим на скорость работы созданного приложения, является скоростная характеристика канала связи.
В предыдущих главах были рассмотрены вопросы создания тех или иных типов приложений, обеспечивающих работу с данными. Следующая глава посвящена вопросам развертывания готовых приложений на компьютерах конечных пользователей.
ГЛАВА 9
Развертывание приложений
После того, как приложение написано и отлажено, его необходимо установить на компьютер клиента (для Windows-приложения) или развернуть на Web-сервере в сети Интернет (для Web-приложений). Технология развертывания приложений в Visual Studio .NET несколько отличается от традиционных приемов. Здесь в рамках одного решения (solution) можно создать и базовое приложение, и приложение по его развертыванию. В данной главе приведены материалы, которые помогут вам:
Q научится создавать инсталляционные пакеты для Windows-приложений;
Q выполнять установку Web-приложений, как в локальной сети, так и в сети Интернет.
Инсталляция Windows-приложений
Пример данного раздела демонстрирует процесс создания установщика для Windows-приложения. Для начала создадим простейшее Windows- приложение, которое будет выполнять всего одно действие — при нажатии на кнопку Пуск в текстовое поле будет выведено сообщение "Windows- приложение". Мы создадим Windows-приложение, а затем добавим к нему установщик.
Создание и установка приложения
Для создания Windows-приложения выполните следующие действия.
В меню File раскройте подменю New и выберите пункт Project.
В диалоговомокнеNewProjectвыберитеVisualBasic ProjectsилиVisual
C# Projects в дереве Project Type и укажите тип приложения Windows Application в области Templates. В текстовое поле Name введите имя проекта, например MyWin.
Проект будет добавлен в Solution Explorer и откроется дизайнер форм.
Из вкладки Windows Forms окна Toolbox перетащите на форму элементы управления Button и TextBox.
Свойству Text элемента Button присвойте значение пуск, а свойству Text элемента TextBox пустое значение (рис. 9.1).
Рис. 9.1. Внешний вид формы Windows-приложения
Дваждыщелкнитенакнопкенаформедлясозданияобработчикасобы
тия нажатия кнопки. В обработчик события добавьте следующий код:
TextBox1.Text="Windows-приложение"
В меню Build выберите Build MyWin для компиляции и сборки созданного приложения.
Итак, наше приложение готово. Теперь создадим установочные файлы, с помощью которых приложение может быть развернуто на компьютере пользователя.
Для создания проекта развертывания созданного приложения (установщика) выполните следующие действия.
В меню File раскройте Add Project и выберите пункт New Project.
В диалоговом окне Add New Project выберите Setup and Deployment Projects в дереве Project Type и Setup Project в области Templates. В текстовое поле Name введите имя проекта MyWin installer (рис. 9.2).
Проект будет добавлен к Solution Explorer и откроется редактор файловой системы (рис. 9.3).
Выделите проект MyWin installer в окне Solution Explorer. В окне свойств Properties выберите свойство ProductName и введите имя устанавливаемого приложения MyWin (рис. 9.4).
Protect Types:Protect Types:Ж О Visual Basic ProjectsD Visual СЖ Projects~ii Setup and Deployment Projects® О Other ProjectsЖ О Visual Basic ProjectsD Visual СЖ Projects~ii Setup and Deployment Projects® О Other ProjectsSetup ProjectSetup ProjectMerge Module ProjectMerge Module ProjectWeb Setup ProjectWeb Setup ProjectTemplates:Templates:Setup WizardSetup WizardCab ProjectCab ProjectCreate a Windows Installer project to which files can be added.Create a Windows Installer project to which files can be added.Name:Name:Location:Location:| MyWln Installer| C :\Documents and 5е^д$\Аматопий\Мои документы\У15иа1 Stu ▼] Beowse...| MyWln Installer| C :\Documents and 5е^д$\Аматопий\Мои документы\У15иа1 Stu ▼] Beowse...Project will be created at C:\.. ДАнатолии\Мои документы^Visual Studio Projects\MyWin Installer.Project will be created at C:\.. ДАнатолии\Мои документы^Visual Studio Projects\MyWin Installer.OKOKCancelCancelHelpHelp
Protect Types:
Protect Types:
Ж О Visual Basic Projects
D Visual СЖ Projects
~ii Setup and Deployment Projects
® О Other Projects
Ж О Visual Basic Projects
D Visual СЖ Projects
~ii Setup and Deployment Projects
® О Other Projects
Setup Project
Setup Project
Merge Module Project
Merge Module Project
Web Setup Project
Web Setup Project
Templates:
Templates:
Setup Wizard
Setup Wizard
Cab Project
Cab Project
Create a Windows Installer project to which files can be added.
Create a Windows Installer project to which files can be added.
Name:
Name:
Location:
Location:
| MyWln Installer
| C :\Documents and 5е^д$\Аматопий\Мои документы\У15иа1 Stu ▼] Beowse...
| MyWln Installer
| C :\Documents and 5е^д$\Аматопий\Мои документы\У15иа1 Stu ▼] Beowse...
Project will be created at C:\.. ДАнатолии\Мои документы^Visual Studio Projects\MyWin Installer.
Project will be created at C:\.. ДАнатолии\Мои документы^Visual Studio Projects\MyWin Installer.
OK
OK
Cancel
Cancel
Help
Help
Рис. 9.2. Окно создания проекта — установщика приложения
tPage ' Fermi ,vb [Design] I Forml.vb FHeSystem(MyWln Insta < F x
| Solution Explorer - MyWin Installer
j^ Fie System on Target Machine kJ Application Folder kl User's Desktop kJ User's Programs Menu
Name| Type
% ^ jp ^ "a ^i ta
Sokjtion MyWin' (2 projects)
У @ MyWin
Bl S) References у Assemblylnfo.vb
Forml.vb
- §5 MyWin Installer
Г 1 Detected Dependencies
tJUser's Proyams MenuFolder
У User's DesktopFolder
£□ Application FolderFolder
Рис. 9.3. Окно редактора файловой системы
Properties9 X
I MyWin Installer Deployment Project Propt ^ ‘
:: ЩЩ нDetectNewer Instalk True*
' Keywords
LocalizationEnglish (United States)
Manufacturer111
ManufacturerUrl
ProductCode-{E1463A76-F5CE-4FB8-
ProductNameMyWin
RemovePreviousVer Fake Searchpath
Рис. 9.4. Задание имени устанавливаемого приложения
Примечание
Свойство ProductName определяет имя, которое будет присвоено папке с установленным приложением и отображено в диалоговом окне Add/Remove Programs.
Проект установщика создан. Теперь ему необходимо указать, для какого приложения нужно создать установочные файлы.
Для добавления Windows-приложения к установщику выполните следующие действия.
Выделите проект MyWin installer в окне Solution Explorer. В окне File System Editor выделите папку Application Folder (рис. 9.5).
у(Рз<,- f ir«! \L (Ое>и?н] I F«n ! Л File System (MyWin Installer) < * X
Solution Explorer • MyWin Installer Sj $ 5 * ч! П] Qi
^ File System on Target Machine
•j Application Folder
*1 User's Desktop
*1 User's Programs Menu
NameI Type
Д Solution MyWin* (2 projects)
c 5 MyWin
♦: ^J References
У Assembly Info.vb
3 Forml.vb
r 5 MyWin Instaler
LJ Detected Dependencies
Рис. 9.5. Конфигурирование папки с файлами приложения Application Folder
Щелкните правой кнопкой мыши на папке Application Folder, в появившемся контекстном меню выберите Add Project Output. Появится диалоговое окно Add Project Output Group.
В диалоговом окне Add Project Output Group из выпадающего списка Project выберите MyWin, затем выберите группу Primary Output в нижележащем списке и нажмите кнопку ОК (рис. 9.6).
В папку Application Folder будет добавлен новый элемент Primary output from MyWin (рис. 9.7).
В меню Build выберите Build MyWin Installer.
На этом этапе мы закончили формирования базового установщика для созданного нами приложения. Вы можете найти на вашем компьютере созданные установочные файлы. Найдите папку с проектом MyWin installer, в нем папку Debug. В ней будет лежать файл Setup.exe и все необходимые дополнительные файлы (рис. 9.8).
На данном этапе мы уже можем запустить процедуру установки приложения на компьютере пользователя. Для чего достаточно скопировать на него файлы, приведенные на рис. 9.8, и запустить программу Setup. На компьютере разработчика процедуры установки и демонтажа можно выполнить, не выходя из проекта. Для чего нужно щелкнуть правой кнопкой мыши на проекте MyWin installer и в появившемся контекстном меню выбрать Install или Uninstall.
Add Project Output ।
Project:| My Win-I
Primary output
Localized resources
Debug Symbols
Content Files
Source Files
1^1/4i-*
Configuration:[(Active)2
Description: Contains the DLL or EXE built by the project.
OK I Cancel I Help
Рис. 9.6. Формирование перечняустанавливаемых файлов приложения
Start Page | FormLvb[Desgn] i Formi.vb File System (MyWin Installed ► x
^ Fie System on Target Machine
<j Application Folder
a 1 User's Desktop
■ £l User's Programs Menu
|| Name| Type
|!®Primary output from MyWIn (Active) Output
Рис. 9.7. Сконфигурированная папка Application Folder с первичными файлами приложения (ехе и d!l)
Запустите приложение-установщик. Для этого выделите проект MyWin installer в Solution Explorer, затем в меню Project выберите Install. Запустится процесс установки в виде последовательных диалоговых окон. Первое окно — приглашение мастера установки приложения (рис. 9.9).
Рис. 9.9. Первое окно мастера установки приложения
На следующей странице мастера установки предлагается согласиться устанавливать приложение в каталог, заданный по умолчанию, или выбрать каталог по своему усмотрению — с помощью кнопки Browse (рис. 9.10).
На третьей странице мастера имеется два переключателя для определения доступности устанавливаемого приложения: для всех пользователей данного компьютера или только для одного пользователя. Кроме того, имеется возможность нажать кнопку Disk Cost, чтобы оценить резервы свободного места на жестких дисках того компьютера, куда осуществляется установка приложения (рис. 9.11).
В следующем окне мастера установки требуется подтвердить свое согласие на установку приложения — для этого достаточно нажать кнопку Next. После чего появится следующее окно с индикатором хода процесса установки. И наконец, заключительное окно мастера информирует пользователя о том, что процесс установки завершился успешно. В конечном итоге в результате описанных действий приложение будет установлено на компьютере пользователя.
Рис. 9.10. Страница выбора каталога размещения инсталлируемого приложения
Рис. 9.11. Окно с информацией о размерах свободного дискового пространства
Однако возможности приложения установщика еще не исчерпаны. Далее мы познакомимся с некоторыми дополнительными возможностями развертывания приложений, которые могут оказаться полезными. К таким дополнительным функциям относятся, например, формирование ярлыка устанавливаемого приложения на рабочем столе Windows, расширение возможностей диалога с пользователем.
Создание ярлыка установленного приложения на рабочем столе Windows
В этом разделе мы расширим функциональность созданного установщика — он автоматически разместит на рабочем столе компьютера пользователя ярлык приложения, для этого выполните следующие действия.
Выделите проект MyWin installer в Solution Explorer. В дереве File System Editor выберите пункт Primary output from MyWin (рис. 9.12).
StartPayu File System (MyWin Installer) | F inal ,b [l?r i у,] t - ml « ► X
^ File System on Target Machine (y| Application Folder ij,'l User's Desktop
* I User's Programs Menu
Name| Type
^Primary output from MyWin (Active) Output
Рис. 9.12. Окно редактора файловой системы проекта MyWin Installer
Щелкните правой кнопкой мыши на пункте Primary output from MyWin и в контекстном меню выберите Create Shortcut to.
В результате этого будет добавлен ярлык с именем Shortcut to Primary output from MyWin (рис. 9.13).
Start Page File System (MyWin Installer) | Form! vb [Design] | Formi 1 ► X
д[ Fie System on Target Machine kJ Application Folder kl User's Desktop kJ User's Programs Menu
Name| Type
Shortcut to Primary output From M... Shortcut Primary output from My Win (Active) Output
Рис. 9.13. Ярлык устанавливаемого приложения в окне редактора файловой системыпроекта MyWin Installer
ЗадайтеярлыкуShortcutto Primary outputfromMyWinновоеимяShort
cut to MyWin.
Выберите ярлык Shortcut to MyWin и перетащите его в папку User's Desktop на левой панели (рис. 9.14).
Star Rage File System (MyWin Installer) | Form! .vblDs >gn] I Forml OX
st) ^ System on Target Machine
Name| Type
kJ Application Folder kJ User's Desktop kJ User's Programs Menu
Lf1 Shortcut to MyWinShortcut
В результате этих манипуляций мы задали установщику выполнение следующих действий: разместить файлы инсталлируемого приложения в папку с именем этого приложения (Application Folder), а ярлык приложения положить на рабочем столе компьютера конечного пользователя.
На следующем этапе мы добавим ассоциированный файл для ярлыка MyWin. В результате при двойном щелчке на ярлыке активизируется ассоциированный файл (vbn) и будет запущено приложение MyWin. Для создания ассоциированного файла (vbn) выполните следующие действия.
Выделите проект MyWin installer в Solution Explorer. В меню View укажите Editor и выберите File Types. В результате на вкладке редактора File Types появится пункт File Types on Target Machine (рис. 9.15).
•er) File Types (MyWin Installer) | - rr 1 ► X
5 Fie Types on Target Machine
Рис. 9,15, Вкладка редактора File Types
Выделите File Types on Target Machine на вкладке File Types. В меню Action выберите Add File Type.
Будет добавлен новый узел New Document Type #l, который откроется для переименования (рис. 9.16).
ite ! File Type* (MyWin Installer) | rami.v < > X i
Fie Types on Target Machine
' Я □ ,№й^УИ«ЙДи^^
У &Open
Рис. 9.16. Ассоциированный файл в окне редактора File Types
Переименуйте New Document Type #l в Vbn_doc.
В окне свойств Properties присвойте свойству файла Extension значение vbn, установив расширение для имени файла.
В окне Properties выделите свойство Command файла Vbn_doc и нажмите кнопку в этой строке. Откроется диалоговое окно Select item in project (рис. 9.17).
В диалоговом окне Selectiteminprojectв спискеLookinнайдитепапку
Application Folder и выберите Primary output from MyWin, затем нажмите кнопку ОК (рис. 9.18).
Рис. 9.17. Диалоговое окно Select item in project
Рис. 9.18. Выбор запускаемого файла а окне Select item in project
В итоге мы задали команду запуска стартового ехе. файла установленного приложения в файлеVbn_doc.
Теперь можно протестировать работу нашего установщика. Постройте заново проект, для чего щелкните правой кнопкой мыши на имени проекта MyWin installer и в контекстном меню выберите пункт Rebuild. Затем снова щелкните правой кнопкой мыши на имени проекта MyWin installer и в контекстном меню выберите пункт Install. После инсталляции приложения откройте рабочий стол вашего компьютера, на нем появится ярлык установленного приложения (рис. 9.19).
Рис. 9.19. Ярлык установленного приложения на рабочем столе пользователя
Теперь демонтируйте приложение — ярлык исчезнет с рабочего стола.
9.1.3. Модификация диалога с пользователем
В этом разделе мы несколько расширим диалоговый интерфейс с пользователем, который отображается на экране в ходе установки приложения. В частности добавим возможность включения необязательных элементов приложения. Такими элементами могут быть, например, техническая документация и файлы с примерами.
Мы добавим к мастеру инсталляции страницу с двумя элементами Checkbox: один будет служить для задания режима установки файла с документацией, другой — файла с примерами. Для конфигурирования дополнительных элементов управления выполните следующие действия.
Выделите проект MyWin installer в окне Solution Explorer. В меню View выберите пункт Editor и задайте, что мы будем редактировать — User Interface. Потом откроется вкладка с указанным редактором (рис. 9.20).
User Interface (MyWin Ins tlx
Э Install
5 Start
3 Welcome
3 Installation Folder
3 Confirm tnstalation
3 Progress
3 Progress
31 End
3 Finished
В Administrative Install
31 Start
3 Welcome
3 Installation Folder
a Confirm tnstalation
31 Progress
3 Progress
3 End
3 Finished
Рис. 9.20. Вкладка с редактором User Interface
В редакторе интерфейса пользователя (User Interface Editor) выберите узел Start под узлом Administrative Install.
В меню Action дайте команду Add Dialog, после чего откроется соответствующее окно.
В диалоговом окне Add Dialog выберите Checkboxes (А) (рис. 9.21).
Рис. 9.21. Окно выбора типа диалога с пользователем
Дважды дайте команду Move Up из меню Action, чтобы переместить страницу с Checkboxes (А) выше страницы Installation Folder.
Выделите страницу с Checkboxes (А) и в окне Properties установите СВОЙСТВУ BannerText значение Samples and Documentation.
Установите СВОЙСТВУ BodyText Значение Install Samples and Documentation.
Установите СВОЙСТВУ CheckBox1Label значение Install samples? (Устанавливать примеры?).
Установите СВОЙСТВУ CheckBox2Label значение Install Documentation? (Устанавливать документацию?).
Присвойте свойствам Checkbox3visible и Checkbox4Visible значение false. Это позволит скрыть неиспользуемые флажки.
Таким образом мы добавили к мастеру установки еще одну страницу, которая будет появляться второй после запуска установочной программы и иметь вид, как на рис. 9.22.
Рис. 9.22. Дополнительное диалоговое окно, добавленное к мастеру инсталляции
Теперь необходимо сконфигурировать две дополнительные папки (с примерами и документацией), которые будут созданы внутри папки устанавливаемого приложения в том случае, если пользователь на странице Samples and Documentation укажет необходимость установки этих элементов. Для конфигурирования папок Samples И Documentation выполните следующие действия.
Выберите проект MyWin installer в окне Solution Explorer. В меню View выберите пункт Editor и задайте редактирование файловой системы — File System. Папка Application Folder должна быть оставлена выбранной (рис. 9.23).
.'age File System (MyWin Installer) | к Гур., rM7v,4 ► X
^ Fie System on Target Machine у Application Folder <J User's Desktop w User's Programs Menu
l^1 Primary output from MyWin
Рис. 9.23. Папка Application Folderв окне редактора файловой системы
В меню Action откройте подменю Add и затем выберите пункт Folder. Затем повторите эту операцию. К папке Aplication Folder будет добавлено две новые папки с именами New Folder #1 и New Folder #2 (рис. 9.24).
; ige File System (MyWin Installer) | Fite " ypes (MyW N ► x
^ File System on Target Machine " «J Application Folder
1 New Folder #1
fin New Folder #2
* 1 User's Desktop
* 1 User's Programs Menu
Name
: ^Primary output from MyWin (. LJ New Folder #2 О New Folder#!
Рис. 9.24. Папка Application Folder с двумя вложенными папками
Переименуйте папку New Folder #1 в Samples, New Folder #2 в Documentation (рис. 9.25).
Page File System (MyWin Installer) |r i 7 ; es (MyW < ► X
^ File System on Target Machine E ж 4 Application Folder
О Documentation Samples fl User's Desktop £1 User's Programs Menu
Name
। -^Primary output from MyWin (, i Samples
□ Documentation
Рис. 9.25. Папка Application Folderс двумя вложенными переименованными папками
Итак, папки сконфигурированы. Теперь нужно поместить в них соответствующие файлы. Поскольку наше приложение носит демонстрационный характер, то создайте два файла с технической документацией (Tex_Doc1.doc, Tex_Doc2.doc) и два файла с примерами (Sample1.doc, Sample2.doc) с помощью текстового редактора Word. Содержимое этих файлов в данном случае может быть любым.
На следующем шаге добавим файлы с документацией и с примерами к соответствующим папкам, а так же определим условия, при которых они будут установлены на компьютер пользователя вместе с приложением. Для этого выполните следующие действия.
Выберите проект MyWin installer в окне Solution Explorer. В меню View выберите Editor, укажите тип редактора — File System — и выделите папку Documentation.
В меню Action укажите команду Add и выберите File. Появится диалоговое окно Add File. В нем последовательно выберите файлы Tex_Doc1.doc и Tex_Doc2.doc. Эти файлы будут добавлены в папку Documentation (рис. 9.26).
Выделите файл Tex_Doc1.doc в окне File System Editor.
В окне свойств Properties присвойте свойству Condition значение СНЕСКВОХА2=1.
P-W' File System (My Win Installer) | Пк; Тур- •'■'. 4 ► x
^ File System on Target Machine .-■ * ) Application Folder
4 Documentation
_J Samples
*.1 User's Desktop
^J User's Proyams Menu
Name
Tex_Doc2.doc
2jTexJDocl.doc
Рис. 9.26. Файлы, добавленные к лапке Documentation
Рис. 9.27. Задания условия установки файла Tex_Doc1.doc
Когда процесс установки будет запущен, файл Tex_Doc1.doc появится на компьютере только в том случае, если пользователь поставил флажок Install Documentation? на соответствующей странице мастера.
Выделите файл Tex_Doc2.doc в окне File System Editor.
В окне свойств Properties присвойте свойству condition значение СНЕСК.ВОХА2=1. Когда процесс установки будет запущен, то файл Tex_Doc2.doc будет смонтирован только в том случае, если пользователь установил флажок Install Documentation? на соответствующей странице мастера.
В редакторе File System выделите папку Samples.
В меню Action укажите пункт Add и выберите File. Добавьте файлы Sam- ple1.doc и Sample2.doc в папку Samples.
Выделите файл Sample1.doc в окне File System Editor.
В окне свойств Properties присвойте свойству condition значение СНЕСКВОХА1=1. Когда процесс установки будет запущен, то файл Sample1.doc появится на компьютере пользователя только в том случае, если будет уставлен флажок Install samples? на соответствующей странице мастера.
И. Выделите файл Sample2.doc в окне File System Editor.
В окне свойств Properties присвойте свойству condition значение СНЕСКВОХА1=1. Когда процесс установки будет запущен, то файл
Sample2.doc появится на компьютере только в том случае, если пользователь уставит флажок Install samples? на соответствующей странице мастера.
Добавим к нашему установщику еще одно условие монтажа приложения. Мы собираемся проверить, какая версия Internet Explorer установлена на компьютере пользователя. Если выяснится, что рабочий браузер — Internet Explorer версии 5.0 и выше, то установка распространяемого приложения на его компьютер будет выполнена, в противном случае процесс инсталляции будет остановлен.
Примечание j
Проверка версии браузера демонстрирует само понятие управления процессом установки. Естественно приложение MyWin не имеет никакой зависимости от версии Internet Explorer, однако для Web-приложений это может иметь принципиальное значение.
Выберите проект MyWin installer в Solution Explorer. В меню View выберите Editor и элемент Launch Conditions.
В редакторе условий запуска Launch Conditions Editor выберите узел Requirements on Target Machine — требования к целевой машине.
В меню Action выберите команду Add File Launch Condition.
Элемент Search for File1 добавится ниже узла Search Target Machine, a элемент Condition1 будет добавлен ниже узла Launch Conditions (рис. 9.28).
ii vb Launch Conditi._yWln Installer) | < I- x
Requirements on Target Machne
3 Q Search Target Machine
lA swMsi-Eitel
6 i Launch Conditions
3 Condition!
3 MsiNetAssemblySupport
Рис. 9.28. Вкладка редактора формированияусловия запуска процесса установки
Переименуйте Search for File1 в Search for Internet Explorer.
В окне свойств Properties установите свойству FileName значение Iex- plore.exe, свойству Folder значение [ProgramFilesFolder], свойству Depth значение 2 и свойству MinVeraion значение 5.00.
Выберите элемент Condition1.
Установите СВОЙСТВУ Message значение Install Microsoft Internet Explorer Version 5.00.
Задание дополнительных свойств установщика проекта
На этом этапе мы сконфигурируем свойство, которое автоматически проверяет наличие в операционной системе файлов, необходимых для запуска программы установщика и их монтаж, если они отсутствуют на компьютере пользователя.
Выберите проект MyWin installer в окне Solution Explorer. В меню View выберите команду Property Pages. Появится диалоговое окно Installer Property Pages.
В окне свойств Installer Property Pages выберите из выпадающего списка свойства Bootstrapper строку Windows Installer Bootstrapper (рис. 9.29).
Рис. 9.29. Диалоговое окно Installer Property Pages
В меню Build выберите Build MyWin Installer.
На этом завершим модернизацию программы установщика и проверим ее работоспособность.
Установка приложения MyWin на компьютере разработчика
Процесс установки на компьютере разработчика можно выполнять непосредственно из среды Visual Studio. Для чего мышью выделите проект MyWin installer в Solution Explorer и в меню Project дайте команду Install. В результате этих действий установщик смонтирует приложение MyWin на ваш компьютер.
Для установки приложения MyWin на компьютере конечного пользователя выполните следующие действия.
В Проводнике Windows найдите каталог с вашими проектами, в нем найдите папку с созданным установщиком. По умолчанию его его путь должен быть таким: \documents and settings\yourloginname\MyWin In- staller\Debug\.
Скопируйте файл MyWin installer.msi, все другие файлы и подкаталоги в каталог другого компьютера — на компьютер конечного пользователя (рис, 9.30).
Рис. 9.30. Установочные файлы, созданные приложением-инсталлятором I в папке с проектами Visual Studio
На компьютере конечного пользователя дважды щелкните на файле Setup.exe, чтобы запустить процедуру установки приложения.
После окончания установки проверьте, что ярлык приложения установлен на рабочем столе компьютера пользователя, и что с помощью этого ярлыка запускается приложение MyWin. Демонтируйте приложение, используя элемент Add/Remove Programs на панели управления Windows.
Примечание j
Демонтировать приложение на компьютере разработчика можно путем выбора в меню Project команды Uninstall.
Инсталляция Web-приложений
В этом примере мы реализуем достаточно простое приложение на основе Web-формы, затем создадим установщик для развертывания созданного приложения на Web-сервере. Для создания Web-приложения выполните следующие действия.
В меню File выберите подменю New и затем пункт Project.
В диалоговом окне New Project выберите Visual Basic Projects или Visual C# Projects в области Project Types и затем укажите тип вашего приложения ASP.NET Web Application в разделе Templates. В текстовом поле Location введите имя вашего Web-сервера и имя проекта http://localhost/MyWeb (рис. 9.31).
Рис. 9.31. Окно создания Web-приложения
Будет сформирован новый проект и Web-форма.
Войдите на вкладку Web Forms окна Toolbox. Выберите элементы управления TextBox, Button и перетащите их на Web-форму (рис. 9.32).
Рис. 9.32. Внешний вид формы Web-приложения
Дважды щелкните на элементе управления Button, чтобы добавить обработчик события нажатия кнопки, в который вставьте следующий код:
TextBox1.Text=Web-приложение"
При нажатии на кнопку в текстовом поле появится надпись "Кнопка нажата".
В меню Build выберите Build MyWeb для компиляции приложения.
2.1. Создание проекта развертывания
Итак, мы создали простое Web-приложение, теперь создадим проект для его развертывания. Для этого выполните следующие действия.
В меню File откройте подменю Add Project и выберите пункт New Project.
В диалоговом окне Add New Project выберите Setup and Deployment Projects в дереве Project Type и затем укажите тип создаваемого приложения Web Setup Project в правой части окна — Templates. В текстовое поле Name введем имя проекта, например, WebDeploy (рис. 9.33).
Рис. 9.33. Окно создания проекта инсталлятора Web-приложений
Будет сгенерирован новый проект, который появится в окне Solution Explorer и откроется редактор файловой системы — вкладка File System (рис. 9.34).
^a'tPa^e File System (WebDeploy) | W^L-orrnt <r. ■ ' -(.Fermi.asp-л d > x -
Jgj Hie System on Target Machine
Name
1 Type
♦ jj Web Application Folder
*jWeb Applcation Folder
Folder
Рис. 9.34. Вкладка редактора файловой системы
Выделите мышью проект WebDeploy, в окне Properties проекта выберите свойство productName и введите в него имя развертываемого приложения MyWeb.
Далее необходимо в проекте развертывания приложений сконфигурировать выходные параметры, для чего выполните следующие действия.
В окне File System Editor выберите папку Web Application Folder. В меню Action откройте подменю Add и затем выберите пункт Project Output. Откроется диалоговое окно Add Project Output Group.
В диалоговомокнеAddProjectOutputGroupизвыпадающегосписка
Project выберите имя развертываемого приложения MyWeb.
Выделите мышью при нажатой клавише <Ctrl> элементы списка Primary Output и Content Files и нажмите кнопку ОК (рис. 9.35).
Рис. 9.35. Окно формирования инсталлируемых файлов Web-приложения
После этого выбранные элементы будут добавлены в папку Web Application Folder.
На следующем этапе изменим некоторые свойства установщика и выполним его компиляцию.
Выберите папку WebApplication. В окне свойств Properties свойству VirtualDirectory установите значение xyz.
В окне свойств Properties установите свойству DefaultDocument значение WebForm1.aspx.
В меню Build выберите команду Build WebDeploy.
Теперь мы имеем возможность запустить установщик и выполнить развертывание приложения MyWeb.
Развертывание приложения
на Web-сервере локального компьютера
В Solution Explorer выберите проект WebDeploy. В меню Project дайте команду Install.
Будет запущен мастер установки приложения. На первой странице мастера появится информация об устанавливаемом приложении и приглашение начать этот процесс (рис. 9.36).
Рис. 9.36. Первое окно мастера установки WEB-приложений
На следующей странице пользователю представляется возможность изменить наименование виртуальной директории и номера порта, заданных по умолчанию (рис. 9.37).
Рис. 9.37. Окно изменения виртуальной директории инсталлируемого Web-приложения
На следующих страницах мастера с помощью индикатора отображается ход процесса установки приложения и сообщается об успешности его завершения.
После завершения процесса инсталляции вы можете убедиться, что необходимый набор файлов появился на вашем локальном Web-сервере. Для этого посмотрите содержимое директории C:\Inetpub\wwwroot\xyz (рис. 9.3S).
Для обращения к Web-приложению, которое было развернуто на локальном Web-сервере, запустите Internet Explorer и наберите адрес http://localhost/xyz. Для проверки работы приложения нажмите кнопку на Web-странице. Если все шаги были сделаны правильно, то в текстовом поле появится надпись "Web-приложение" (рис. 9.39).
Таким образом, мы выполнили установку Web-приложения и запустили его не из среды разработки Visual Studio, а из операционной системы Windows через Internet Explorer.
Рис. 9.38. Набор установочных файлов, созданных приложением-установщиком в виртуальном каталоге Web-сервера
Рис. 9.39. Запуск установленного Web-приложения в среде Internet Explorer
Развертывание приложения на Web-сервере сети
Если необходимо развернуть Web-приложение на Web-сервере сети Интернет, то нужно скопировать на него установочные файлы и запустить процесс установки на том компьютере, где установлен Web-сервер. Для этого выполните следующие действия.
В Проводнике Windows перейдите в каталог с вашими проектами и найдите созданный установщик. По умолчанию он будет расположен в каталоге — \documents and settings\yourloginname\ MyDocu-
ments\Visual Studio Projects\WebDeploy\Debug\(pис. 9.40).
v Q Переходv Q Переходатопий\Мои документы\У1$иа1 Studio Projects\MyWeb\WebDeploy\Debugатопий\Мои документы\У1$иа1 Studio Projects\MyWeb\WebDeploy\DebugWebDeployПакет "Windows Instater" 2^9 KEWebDeployПакет "Windows Instater" 2^9 KESetupMicrosoft (R) Visual Stutfio Wn. лMicrosoft «ZorporatwnSetupMicrosoft (R) Visual Stutfio Wn. лMicrosoft «ZorporatwnInstMsiAInst silty for the vyindcw Irgr Mi :r i^pft Coipor atronInstMsiAInst silty for the vyindcw Irgr Mi :r i^pft Coipor atronП^>дметрс^ конфигурацииП^>дметрс^ конфигурацииInstMsW(г^лГег Ьч th*- </And^7r- In$rMxrosoft CorporationInstMsW(г^лГег Ьч th*- </And^7r- In$rMxrosoft Corporation3.70 МБ3.70 МБj Мой компьютерj Мой компьютер
v Q Переход
v Q Переход
атопий\Мои документы\У1$иа1 Studio Projects\MyWeb\WebDeploy\Debug
атопий\Мои документы\У1$иа1 Studio Projects\MyWeb\WebDeploy\Debug
WebDeploy
Пакет "Windows Instater" 2^9 KE
WebDeploy
Пакет "Windows Instater" 2^9 KE
Setup
Microsoft (R) Visual Stutfio Wn. л
Microsoft «Zorporatwn
Setup
Microsoft (R) Visual Stutfio Wn. л
Microsoft «Zorporatwn
InstMsiA
Inst silty for the vyindcw Irgr Mi :r i^pft Coipor atron
InstMsiA
Inst silty for the vyindcw Irgr Mi :r i^pft Coipor atron
П^>дметрс^ конфигурации
П^>дметрс^ конфигурации
InstMsW
(г^лГег Ьч th*- </And^7r- In$r
Mxrosoft Corporation
InstMsW
(г^лГег Ьч th*- </And^7r- In$r
Mxrosoft Corporation
3.70 МБ
3.70 МБ
j Мой компьютер
j Мой компьютер
Рис. 9.40. Установочные файлы Web-приложения в папке с проектами Visual Studio
Скопируйте файл WebDeploy.msi, а также все остальные файлы и поддиректории в каталог с Web-приложениями компьютера, где установлен ваш главный Web-сервер. Обычно папки с приложениями располагаются на Web-сервере в директории C:\Inetpub\wwwroot\.
Среди перенесенных на Web-сервер фалов найдите и запустите на исполнение файл Setup.exe, чтобы выполнить установку Web-приложения.
Примечание j
Вы должны иметь права на выполнение установок на Web- сервере с удаленного компьютера — либо процедуру установки необходимо выполнять непосредственно на самом сервере.
Для запуска Web-приложения, которое было развернуто на удаленном компьютере, запустите Internet Explorer и наберите адрес http://[ComputerName]/xyz. После появления Web-формы в окне Internet Explorer убедитесь в работоспособности приложения. Для этого нажмите кнопку на Web-форме. Если все шаги были сделаны правильно, то в текстовом поле появится надпись "Web-приложение".
Демонтаж Web-приложения
На панели управления Windowsдважды щелкните на значке
Add/Remove Programs.
В диалоговом окне Add/Remove Programs выберите MyWeb и нажмите
кнопку Remove.
Примечание
Для демонтажа Web-приложений на вашем локальном компьютере а среде Visual Studio нужно в меню Project выбрать команду Uninstall.
В данной главе были приведены материалы, позволяющие создать установочные файлы для обеспечения развертывания разработанных приложений на компьютерах конечных пользователей. В следующей главе рассматриваются вопросы этапов создания Web-сайтов, позволяющих пользователям сети Интернет работать с удаленными базами данных.
ГЛАВА 10
Удаленная работа с базами данных через Интернет-сайты
На сегодняшний день технология Microsoft .Net дает наиболее широкие возможности для реализации динамических Интернет-сайтов, предоставляющих информацию внешним пользователям из баз данных. При этом программисты работают в привычной для них среде разработки, а пользователи получают самые широкие возможности по обработке информации: выборка, сортировка, добавление, удаление и модификация записей. В данной главе рассмотрен достаточно упрощенный пример создания Интернет-сайта торговой компании. В нем реализованы все стандартные операции: регистрация и идентификация пользователей, выборка и сортировка данных, добавления информации в базу данных, модификация и удаление записей. В ходе реализации примера мы выполним практически все основные операции по созданию динамического Интернет-сайта, в том числе:
О постановка задачи;
Q разработка структуры базы данных (мы воспользуемся готовой базой данных, минимально изменив ее структуру);
Q создание бизнес-логики приложения на основе Web-сервиса;
Q разработка клиентской части приложения - интерфейса пользователя.
Постановка задачи
В заключительной главе мы попробуем построить корпоративную распределенную систему. Представьте себе предприятие, состоящее из аппарата управления и множества территориально распределенных филиалов. Это мо-
жет быть торговая компания (центральный офис, торговые точки и склады), сеть станций технического обслуживания автомобилей (с мастерскими и складами), транспортно-экспедиционное предприятие (с сетью складов для накопления грузов, транспортных предприятий, массой поставщиков груза и грузополучателей) и т. д. Данный список можно продолжать достаточно долго. Однако указанные компании и предприятия объединяет одно обстоятельство — все территориально распределенные подразделения должны работать в едином информационном пространстве, с едиными информационными массивами. Кроме того, к некоторым данным должны иметь доступ и потенциальные клиенты компании (к прайс-листам на товары, к перечню и стоимости услуг, к тарифам на перевозку грузов и т. п.). Удовлетворить этим требованиям может только распределенное приложение, возможная структура которого приведена на рис. 10.1.
Рис. 10.1. Структура распределенного приложения
В распределенном приложении все пользователи системы — служащие центрального офиса, удаленные филиалы, клиенты компании — взаимодействуют с базой данных через единый пакет прикладных программ. В таких приложениях необходимо максимально разгрузить рабочие станции и основную функциональность перенести на корпоративный сервер. В идеале рабочие станции должны быть вообще "пустыми", то есть не иметь устанавливаемых элементов прикладных программ. Ведь потенциальным клиентом компании может стать любой пользователь сети Интернет, и вне зависимости от имеющихся у них компьютеров, операционных систем все заинтересованные лица должны иметь доступ к определенным массивам информации в базе данных (естественно с определенным разграничением прав доступа).
Предложенные фирмой Microsoft .Net-технологии на основе Web-сервисов идеально подходят для реализации распределенных задач. Во-первых, эта технология позволяет упростить сам процесс создания распределенных приложений, во-вторых, упрощается процесс их развертывания и модифика-
ции. Ведь ядро приложения (база данных и прикладные программы) устанавливаются только один раз на сервер. В случае изменения и модификации прикладных программ (например, Web-сервисов) достаточно выполнить их переустановку на сервере, после чего десятки, сотни или даже тысячи пользователей начнут работать с обновленной версией продукта.
Сеть Интернет имеет невысокую пропускную способность и скорость работы, что накладывает некоторые ограничения на работу с большими массивами информации, поэтому основное применение распределенных приложений — это локальные сети организаций и предприятий. Однако в .Net- технологии заложена возможность работы конечного пользователя в отрыве от основной базы данных, а также манипулирования большими массивами информации непосредственно на уровне СУБД, без передачи данных по сети, что при разумном подходе к построению прикладных систем позволяет организовать работу с удаленной информацией и через сеть Интернет.
В данной главе мы рассмотрим пример создания подобного распределенного приложения. Чтобы не приводить длинные листинги и не отвлекаться на изучение логики работы программ, предельно упростим задачу, уделяя основное внимание структуре и этапам создания распределенной системы.
Создаваемое приложение будет решать следующие задачи. Торговая компания имеет центральный склад и продает товары через свои представительства, расположенные в разных городах. Все представительства взаимодействуют с центральным складом через корпоративный Интернет-сайт. В зависимости от спроса и наличия на складах каждое представительство компании периодически делает заказ на доставку определенных товаров. Менеджер центрального склада торговой компании просматривает заказы своих представительств и формирует партии товаров для отправки в соответствующие города. При этом существует следующее разграничение прав на доступ к таблицам базы данных. Каталог товаров доступен всем пользователям только для чтения, включая любого пользователя сети Интернет. Представительства торговой компании имеют доступ только к своим заказам — для чтения и редактирования. Менеджер центрального склада имеет доступ к заказам всех представительств, но только для чтения. Кроме того, любой пользователь сети Интернет может зарегистрироваться в системе и заказать для себя имеющийся товар. Это несколько упрощенный вариант реального приложения, но целью примера является не детальная разработка конкретного приложения, а знакомство с основными приемами создания приложений, обеспечивающих взаимодействие удаленных пользователей с базой данных через Интернет-сайт.
Далее сформируем перечень основных задач, решаемых приложением:
Q регистрация и идентификация пользователей системы;
О предоставление пользователям каталога товаров;
Q формирование заказов на товары клиентами и торговыми представительствами;
Q анализ заказов на товары менеджером центрального склада.
Модуль регистрации пользователей системы предназначен для того, чтобы торговая компания имела некоторую информацию о тех пользователях сети Интернет, которые интересуются продаваемыми ими товарами. После того, как посетитель Интернет-сайта зарегистрируется в системе, ему открывается доступ к каталогу продаваемых товаров и он может сформировать заказ на интересующие товары.
Модуль идентификации пользователей системы предназначен для того, чтобы определить, кто из "клиентов" пытается получить доступ к информационным ресурсам торговой компании. Если это зарегистрированный пользователь, то ему будет открыт доступ к каталогу товаров и к своим заказам для чтения и редактирования. Если же входит незарегистрированный пользователь или кто-то пытается войти в систему под неверным паролем, то ему будет отказано в доступе.
Модуль доступа к каталогу товаров предоставит всем пользователям информацию о продаваемых товарах и ценах. Предоставленные данные будут доступны только для чтения.
Модуль формирования заказа на товары позволит получить полный перечень заказов, сделанных конкретным торговым представительством или клиентом. С его помощью можно будет добавить новый заказ, удалить или отредактировать любой существующий заказ.
Модуль анализа заказов на товары позволит менеджеру центрального склада получить информацию о заказах за определенный интервал дат, скомпоновать партии товаров по городам, торговым представительствам и клиентам. Приложение будет состоять из трех уровней:
Q первый уровень — база данных;
Q второй уровень — бизнес-логика, реализованная в виде Web-сервиса;
Q третий уровень — интерфейс пользователя, реализованный в виде Web- форм.
Структура базы данных
Чтобы не создавать базы данных, воспользуемся готовой базой Northwind, которая поставляется вместе с SQL Server. Из базы данных Northwind задействуем следующие таблицы:
Q categories (категории товаров);
Q Products (перечень товаров);
Q Customers (заказчики);
Q orders (заказы);
Q Orders Details (детали заказов).
Все таблицы базы данных оставим без изменения за исключением таблицы Customers (заказчики), в которую добавим поле для хранения пароля — Pass. Для этого запустите SQL Server Enterprise Manager, откройте таблицу Customers в режиме конструктора и добавьте поле pass (рис. 10.2).
X^ltFavJ Ser r-?!.»r> . 'C ■ ; • .. •; •• j^r ' dbo.Cu$to
Column Name
Data Type
I length |
Alow Nulls |
V!
Customer IO
neb ar
5
CompanyName
nvarchar
40
ContactName
nvarchar
30
V
Contact Title
nvarchar
30
V
Address
nvarchar
60
V
Qty
nvarchar
15
V
Region
nvarchar
15
V
PostalCode
nvarchar
10
V
Country
nvarchar
15
V
Phone
nvarchar
24
V
Fax
nvarchar
24
V
Pass
char
10
V
Рис. 10.2. Поля таблицы Customers в режиме конструктора
Поля CustomerID и Pass будут использоваться для идентификации пользователей системы. В поле Pass первых десяти существующих записей внесите произвольные значения (в тестовом примере можно использовать простую последовательность значений 1,2,3, ... 10).
Будем считать, что на этом этапе база данных сформирована (мы будем использовать только первые 10 записей таблицы с заказчиками) и можно приступать к реализации бизнес-логики приложения.
Создание Web-сервиса
Вся бизнес-логика приложения будет реализована на уровне Web-сервиса, для чего создадим следующие методы:
Q проверка того, что пользователь уже зарегистрирован в системе (CustomerExist);
Q проверка подлинности имени и пароля клиента, который пытается войти В систему (CustomerEnter);
Q регистрация в системе нового пользователя (RegUser);
Q получение информации из таблицы с категориями продуктов (GetCategories);
Q получение информации из таблицы с продуктами (GetProducts);
Q получение информации из таблицы с заказами клиента (GetOrders);
Q добавление в базу данных нового заказа (AddOrders);
Q удаление заказа из базы данных (DelOrders);
Q получение информации из таблицы с содержимым конкретного заказа (GetDetails);
Q добавление в заказ нового продукта (AddDetails);
Q удаление продукта из заказа (DelDetails).
И начнем мы работу с формирования соответствующего проекта. Для создания проекта Web-сервиса выполните следующие действия.
В меню File откройте подменю New и выберите Project для вывода диалогового окна New Project.
В зависимости от языка, который вы собираетесь использовать, укажите Visual Basic Projects или Visual C# Projects в дереве Project Types, затем выберите ASP.NET Web Service в области Templates.
В текстовом поле Locationвведите путьк проекту,
http://ServerName/MyWebService изатем нажмитекнопку ОК
(рис. 10.3).
Рис. 10.3. Окно создания проекта Web-сервиса
Примечание
Если Web-сервер находится на вашем локальном компьютере, то в качестве имя сервера введите localhost. Если Visual Studio не смог создать ASP.NET проект для вашего Web-сервиса, то необходимо посмотреть протокол ошибок в диалоговом окне Web Access Failed и принять меры по их устранению (обычно это связано с настройками IIS сервера или браузера).
Будет создан проект с именем MyWebService и файл с именем по умолчанию Service1.asmx, куда будет вноситься программный код.
Функции регистрации
и идентификации пользователей
Первым методом, который мы реализуем на уровне Web-сервиса, будет проверка прав доступа к информационным ресурсам сервера. Если на сайт компании вошел внешний клиент, то нужно проверить, является ли он зарегистрированным пользователем системы. Если клиент ранее не регистрировался в системе, то он не будет допущен к информационным ресурсам и ему будет предложено выполнить процедуру регистрации. Если пользователь ранее регистрировался, то после проверки введенного имени пользователя и пароля он получит доступ к определенным ресурсам системы. Информация о пользователях системы храниться в таблице Customers (заказчики). Для того чтобы Web- сервис имел доступ к этой таблице необходимо создать соединение с базой данных и соответствующий адаптер данных. Для создания соединения с базой данных и адаптера данных выполните следующие действия.
Выделите левой кнопкой мыши окно Server Explorer.
Примечание
I По умолчанию окно Server Explorer расположено в левой части экрана дизайнера в виде вкладки. Если эта вкладка не видна, то в меню View выберите пункт Server Explorer.
Если вы уже ранее создавали соединение с базой данных Northwind, то в окне Server Explorer появится элемент в узле Data Connections, обеспечивающий доступ к базе данных Northwind.
В Server Explorer разверните узел с таблицами Tables базы данных Northwind.
Найдите таблицу Customers, выделите ПОЛЯ CustomerID, CompanyName, Pass и перетащите их на вкладку дизайнера Web-сервиса (рис. 10.4).
После этого на панели дизайнера появятся два объекта SqlConnectionl И SqlDataAdapter1. Выделите объект SqlDataAdapter1 и в окне Properties задайте ему новое имя CustomersSqlDataAdapter (рис. 10.5).
Рис. 10.4. Доступ к таблицам базы данных в окне Server Explorer
Start Page Ser vice l.asmx.vb [Design]* |
ti$5qlConnectionl $g Customer sSqDataAdapter
Рис. 10.5. Объекты SqlConnectionl и CustomersSqlDataAdapterв окне дизайнера Web-сервиса
Эти компоненты сконфигурированы для того, чтобы обеспечить передачу информации между набором данных (он будет создан чуть позже) и таблицей Customers базы данных Northwind.
Модернизируем объект CustomersSqlDataAdapter — в частности, изменим текст команды SelectCommand. Для этого выделите мышью объект CustomersSqlDataAdapter, перейдите в окно его свойств Properties, раскройте узел SelectCommand, найдите свойство CommandText и нажмите кнопку в строке этого свойства. Откроется окно построителя запросов Query Builder. В данном окне сформируйте текст следующего запроса (рис. 10.6):
SELECT CustomerID, CompanyName, Pass
FROM Customers
WHERE (CustomerID=@CUSTOMERID)
Рис. 10.6. Формирование запроса для поиска пользователя в базе данных в окне Query Builder
В результате выполнения данного запроса из базы данных будет возвращена всего одна запись.
Теперь перейдем к формированию программного кода функции, которая будет проверять наличие в базе данных пользователя с определенным именем и паролем (customerExist). Для этого выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите View Code.
В окне редактора кода наберите следующий код (листинг 10.1).
Листинг10.1
' Visual Basic
<WetbMethod()> Public Function CustomerExist(ByVal CUSTOMERID As^ String) As Boolean
Dim ds As New DataSet()
Dim flag As Boolean
Dim str As String
SqlSelectCommand1.Parameters("@CUSTOMERID").Value =%>
CUSTOMERID
CustomersSqlDataAdapter.Fill(ds)
Try
str=ds.Tables(0).Rows(0).Item(0) flag=True
Catch
flag=False
End Try ds.Dispose() CustomerExist=flag End Function
//C#
[WebMethod]
public bool CustomerExist (string CUSTOMERID) {
DataSet da;
ds=new DataSet("Customers"); bool flag;
string str;
sqlSelectConmand1.Parameters["@CUSTOMERID"].Value= 'Ь
CUSTOMERID;
CustomersSqlDataAdapter.Fill(ds); try
{
str=(string) ds.Tables[0].Rows[0]["CustomerID"]; flag =true;
} catch
{ flag=false;
}
ds.Dispose(); return flag; }
Разберем структуру этой функции. Ей передается один параметр — имя пользователя CUSTOMERID, который пытается получить доступ к информационным ресурсам, В следующих трех строках объявляется объектная пере-
менная ds (набор данных), затем — переменная flag (признак того, что пользователь зарегистрирован в базе данных) и строковая переменная str. В следующей строке параметру команды Select адаптера данных присваивается переданное в функцию значение имени пользователя. После этого с помощью метода Fill адаптера данных CustomersSqlDataAdapter объект ds заполняется данными. При чем, если пользователь с заданным именем есть в базе данных, то набор данных ds получит одну строку, если такого пользователя нет, то набор данных ds окажется пустым. Далее в блоке try...Catch переменной str присваивается значение из первой колонки, первой строки, первой таблицы набора данных ds. Если пользователь найден в базе данных, то эта операция выполняется успешно и переменная flag получает значение true, в противном случае оно получает значение false, В последних двух строках мы освобождаем ранее объявленный экземпляр класса DataSet при помощи метода Dispose и присваиваем функции CustomerExist возвращаемое значение.
Желательно сразу убедиться в корректности работы этой функции, для чего выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите Build and Browse. Появится страница с описанием методов Web-сервиса (рис. 10.7).
Browse - Servlcel Web Service | Start Page :e icel .asmx.vb [Design) I Serve-, j ► x
Servicel
The following operations are supported. For a formal definition, please review the Service Description.
• Custom e rhxist
This web service is using http://tempuri.org/ as its default namespace.
Рис. 10.7. Страница с описанием метода CustomerExist Web-сервиса
ЩелкнителевойкнопкоймышинассылкеCuctomerExist,послеэтого
появится страница тестирования созданного Web-метода.
Наберите существующее в базе данных имя пользователя (в данном тестовом примере ANTON) и нажмите кнопку Invoke (рис. 10.8).
Есливсебылосделаноправильно,тофункциявернетзначениеtrue
(рис. 10.9).
Browse - Service 1 Web Service | '?. -• ’jc t -! ,>r.r<vb [Desrin] «vice; . "
Servicel
Click here for a complete list of operations.
CustomerExist
Test
To test the operation using the HTTP GET protocol, click the "Invoke' button,
Parameter Value
CUSTOMER ID: [ANTON
Invoke |
Рис. 10.8. Страница тестирования Web-метода CustomerExist
http://localh...TOMERID=ANTON | Bre ;■».:■•:-! We •«•*» | Startpage
<?xml version=" 1.0" encoding="utf-8" ?>
<boolean xmlns="http://tempuri.org/’>true</boolean>
Рис. 10.9. Результат работы Web-метода CustomerExist в формате XML
Теперь введите заведомо несуществующее значение имени пользователя (например, 12345), функция должна вернуть значение false.
Теперь создадим метод, который будет регистрировать нового пользователя информационной системы, сохраняя информацию о нем в базе данных. Для этого будет задействован тот же адаптер данных CustomersSqlDataAdapter, который использовался при реализации предыдущей функции. Однако теперь мы воспользуемся другой командой адаптера данных, а именно InsertComman.
Мы можем посмотреть текст команды InsertComman объекта CustomersSqlDataAdapter. Дляэтоговыделитемышьюобъект
CustomersSqlDataAdapter, перейдите в окно его свойств Properties, раскройте узел InsertComman, найдите свойство CommandText и нажмите кнопку в строке этого свойства. Откроется окно построителя запросов Query Builder. В данном окне появится следующий текст запроса (рис. 10.10): INSERT INTO Customers
(CustomerID, CompanyName, Pass)
VALUES (@CustomerID, @CompanyName, @Pass)
Рис. 10.10. Формирование запроса для добавления в базу данных нового пользователя в окне Query Builder
Теперь перейдем к формированию программного кода функции, которая будет добавлять в базу данных нового пользователя (RegUser). Для этого выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите пункт View Code.
В окне редактора кода наберите следующий код (листинг 10.2).
;
; Листинг 10.2
' Visual Basic
<WebMethod()> Public Function RegUser(ByVal CUSTOMERID Asъ
String,ByVal PASS As String, ByVal CompanyName As String) Asъ
Boolean
Dim flag As Boolean
Dim user As Boolean
user=CustomerExist(CUSTOMERID)
If user Then
flag=False
Else
SqlInsertCommand1.Parameters("@CUSTOMERID").Value =^
CUSTOMERID
SqlInsertCommand1.Parameters("@PASS").Value=PASS
SqlInsertCommand1.Parameters("@CompanyName").Value =ъ
CompanyName
SqlConnection1.Open()
SqlInsertCommand1.ExecuteNonQuery()
SqlConnection1.Close()
flag=True
End If
RegUser=flag
End Function
//C#
[WebMethod]
public bool RegUser (string CUSTOMERID, string PASS, stringъ
CompanyName)
{
bool flag ;
bool user ;
user=CustomerExist (CUSTOMERID) ;
if (user)
{
flag=false;
}
else
{
sqlInsertCommand1,Parameters["@CUSTOMERID"].Value=ъ
CUSTOMERID;
sqlInsertCommand1.Parameters["@PASS"].Value=PASS;
sqlInsertCommand1.Parameters["@CompanyName"].Value=
CompanyName;
SqlConnection1.Open();
sqlInsertCommand1.ExecuteNonQuery();
SqlConnection1.Close();
flag=true;
}
return flag;
}
Эта функция принимает в качестве параметров три значения, которые будут занесены в таблицу customers: CUSTOMERID, PASS, CompanyName. Результат выполнения функции имеет логическое значение: true — если запись о пользователе добавлена, false — если запись не добавлена. В первых двух строках приведенного кода описаны переменные flag и user. Далее делается проверка, существует ли в базе данных пользователь с заданным именем путем обращения к созданной ранее функции CustomerExist, результат работы которой присваивается переменной user. Если пользователь зарегист-
рирован в базе данных (user=true), то переменной flag присваивается значение false и работа функции завершается. Если пользователь в системе не зарегистрирован, то параметры команды InsertCommand1 получают значения, открывается соединение с базой данных, выполняется метод ExecuteNonQuery и соединение с базой данных закрывается. Переменная flag получает значение true (запись о пользователе добавлена) и функция завершает свою работу. Поскольку команда Insert не возвращает набора данных, то ее необходимо выполнять именно при помощи метода ExecuteNonQuery.
Созданная ранее функция CustomerExist проверяет только наличие в базе данных записи с параметрами пользователя. Для проверки корректности введенного пользователем имени и пароля необходимо написать еще одну функцию. Назовем ее CustometEnter (листинг 10.3.)
ргг-к-т-—": -■т-тт--- ■;
Листинг 10.3
L -:-i
' Visual Basic
<WebMethod()> Public Function CustomerEnter(ByVal CUSTOMERID As String,Ч ByVal PASS As String) As Boolean
Dim ds As New DataSet()
Dim flag As Boolean
Dim str As String
SqlSelectCommand1.Parameters("@CUSTOMERID").Value=CUSTOMERID CustomersSqlDataAdapter.Fill(ds)
Try
str=ds.Tables(0).Rows(0).Item("pass")
If Trim(str)=Trim(PASS) Then
flag=True
Else
flag=False
End If
Catch
flag=False
End Try
ds.Dispose()
CustomerEnter=flag
End Function
//C#
[WebMethod]
public bool CustomerEnter (string CUSTOMERID, string PASS)
{
DataSet ds;
ds=new DataSet("Customers") ;
bool flag ;
string str;
sqlSelectCommand1.Parameters["@CUSTOMERID"].Value=CUSTOMERID;
CustomerssqlDataAdapter.Fill(ds) ;
try
{
str=(string) ds.Tables[0].Rows[0]["pass"];
flag=true;
if (alltrim(str)=alltrim(PASS))
{
flag=true;
} else
{
flag=false;
}
}
catch
{
flag=false;
}
ds.Dispose();
return flag;
)
Она во многом идентична функции CustomerExist. Отличается же она тем, что у нее два параметра (имя и пароль). Кроме того, в блоке Try...Catch переменной str присваивается пароль, полученный из базы данных, который затем сравнивается с паролем, введенным пользователем. Если эти пароли совпадают, то переменной flag присваивается значение true, то есть указывается, что идентификация пользователя выполнена успешно.
Итак, будем считать, что вопрос с идентификацией и регистрацией пользователя на уровне Web-сервиса решен, теперь необходимо разработать основные функции серверной части приложения.
Функции работы с каталогом товаров
Кроме регистрации и идентификации пользователей, на уровне Web- сервиса необходимо реализовать функции работы с каталогом товаров — получение категорий продуктов и данных о них. Функция получения данных о продуктах (GetProducts) в качестве параметров должна принять имя пользователя и пароль для идентификации прав пользователя, а также категорию товара. Если идентификационные параметры корректны, то она сформирует набор данных с товарами и передаст его приложению-клиенту (товары будут сгруппированы по категориям). Таким образом, в этой части приложения необходимо использовать таблицу Products.
Для реализации данной функции выполните следующие действия.
Из вкладки Data окна ТооlBох перетащите на вкладку дизайнера Web-сервиса объект SqlDataAdapter. Будет запущен мастер конфигурации адаптера данных. В окно построителя запросов этого мастера добавьте таблицу Products и сформируйте следующий запрос (рис. 10.11).
SELECT ProductID, ProductName, CategoryID, UnitPrice
FROM Products
WHERE(CategoryID=@CategoryID)WHERE(CategoryID=@CategoryID)<<I Output | Sort Type | Sort Order | CriteriaI Output | Sort Type | Sort Order | CriteriaS' Regenerate parameters colection for this command.S' Regenerate parameters colection for this command.Query BuilderQuery Builder|_I* (Al Columns) I v ProductID v’productName|_I* (Al Columns) I v ProductID v’productNameAlias liableProducts ProductsProductsAlias liableProducts ProductsProductsOK| Cancel |OK| Cancel |Column ProductNao CategorylDUnitPriceColumn ProductNao CategorylDUnitPrice< M.|< M.|SELECT ProductID, ProductName, CategorylD, UnitPriceFROM ProductsWHERE (CategorylD e ©CategorylD)SELECT ProductID, ProductName, CategorylD, UnitPriceFROM ProductsWHERE (CategorylD e ©CategorylD)Рис. 10.11 . Формирование запроса для метода GetProducts в окне Query BuilderРис. 10.11 . Формирование запроса для метода GetProducts в окне Query Builder■ ©CategorylD■ ©CategorylD
WHERE(CategoryID=@CategoryID)
WHERE(CategoryID=@CategoryID)
<
<
I Output | Sort Type | Sort Order | Criteria
I Output | Sort Type | Sort Order | Criteria
S' Regenerate parameters colection for this command.
S' Regenerate parameters colection for this command.
Query Builder
Query Builder
|_I* (Al Columns) I v ProductID v’productName
|_I* (Al Columns) I v ProductID v’productName
Alias liable
Products Products
Products
Alias liable
Products Products
Products
OK| Cancel |
OK| Cancel |
Column ProductNao CategorylD
UnitPrice
Column ProductNao CategorylD
UnitPrice
< M.|
< M.|
SELECT ProductID, ProductName, CategorylD, UnitPrice
FROM Products
WHERE (CategorylD e ©CategorylD)
SELECT ProductID, ProductName, CategorylD, UnitPrice
FROM Products
WHERE (CategorylD e ©CategorylD)
Рис. 10.11 . Формирование запроса для метода GetProducts в окне Query Builder
Рис. 10.11 . Формирование запроса для метода GetProducts в окне Query Builder
■ ©CategorylD
■ ©CategorylD
В окне свойств Properties созданного адаптера данных измените его имя (свойство Name) на ProductsSqlDataAdapter.
Перейдите на вкладку редактора программного кода и сформируйте Web-метод GetProducts (листинг 10,4).
■<■ ■.^.^^•••••••••••••■■••»*р.“<><><<</**и»м>«>*»м Y*—*"»—”tf•••ill•«••■•~••w•••■•••••н•~и««f.^„|l^н^^ш^ •«••«,>••„•••••«••♦••*•••••■•• I
Листинг 10.4
' Visual Basic
<WebMethod()> Public Function GetProducts(ByVal CUSTOMERID As String, ByVal PASS As String, ByVal CategoryID As Intl6) As DataSet
Dim Products As New DataSet()
Dim user As Boolean
user=CustomerEnter(CUSTOMERID, PASS)
If user Then
SqlSelectCoraraand2.Parameters("@CategoryID").Value=
CategoryID
ProductsSqlDataAdapter.Fill(Products)
End If
Return Products
End Function
//C#
[WebMethod]
public DataSet GetProducts (string CUSTOMERID, string PASS, int CategoryID)
{
DataSet Products;
Products=new DataSet("Products");
bool user ;
user=CustomerEnter(CUSTOMERID, PASS);
if (user)
{
sqlSelectCommand2.Parameters["@CategoryID"],Value=CategoryID;
ProductsSqlDataAdapter.Fill(Products);
}
return Products;
}
На вход данному методу передаются следующие параметры: имя CUSTOMERID, пароль пользователя PASS, категория товара CategoryID. Приложению-клиенту метод возвращает набор данных (содержимое таблицы Products, в разрезе одной категории товара).
В первой и второй строках создаются объектная переменная Products (набор данных) и логическая переменная user. В третьей строке осуществляется идентификация пользователя путем обращения к функции CustomerEnter, которой передаются в качестве параметров имя и пароль пользователя. Если пользователь зарегистрирован в системе (user=true), то присваивается значение параметру CategoryID команды select адаптера данных ProductsSqlDataAdapter и заполняется набор данных Products.
Желательно сразу проверить корректности работы функции. Для этого выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в контекстном меню выберите Build and Browse. Появится страница с описанием методов Web-сервиса.
Щелкните левой кнопкой мыши на ссылке GetProducts, после чего появится страница тестирования созданного Web-метода.
Наберите существующее в базе данных имя (ANTON), пароль (3), категорию товара (1) и нажмите кнопку Invoke (рис. 10.12).
Если все было сделано правильно, то данный метод вернет набор данных с содержимым таблицы products в XML-формате (рис. 10.13).
Start Page Servicel.asmz.vb [Design] i Sorvrcel.gsmx.vb । Browse - Sersacel Web Service
- «Products diffgr:id="Products2" msdata:rowOrder=4">
<ProductID>2«/ProductID>
<ProductNarne>Chang</ProductName>
<CategorylD> !</CategorylD>
<UnitPrice> 19</UnitPrice>
</Products>
- «Products diffgr:id="Products3* msdata:rowOrder="2">
<ProductID>24«/Product!D>
<ProductName>Guarana Fantastica«/ProductName>
<CategorylD>l«/CategorylD>
<UnitPrice>4.5«/UnitPrice>
</Products>
- «Products diffgr:id="Products4* msdata:rowOrder=‘3*> <ProductID>34«/ProductlD>
<ProductName>Sasquatch Ale«/ProductName>
<CategoryID>l«/CategoryID>
<UnitPnce>14</UnitPnce>
Рис. 10.13. Результаты работы Web-метода GetProducts в формате XML
На вход функции, которая формирует каталог, кроме пароля и имени клиента необходимо передать еще и категорию товара. Значит в Web-сервисе должен быть реализован метод, который может передать клиентскому приложению содержимое таблицы с категориями товаров (GetCategories). Эта функция в качестве параметров должна принять имя и пароль для идентификации прав пользователя. Если идентификационные параметры корректны, то она должна сформировать набор данных с категориями товаров и передать его внешнему приложению. Таким образом, в этой части приложения необходимо использовать таблицу categories.
Для реализации данной функции (Web-метода) выполните следующие действия.
Из вкладки Data окна ТооlBох перетащите мышью на вкладку дизайнера Web-сервиса объект SqlDataAdapter. Будет запущен мастер конфигурации адаптера данных. В окно построителя запросов этого мастера добавьте таблицу Categories и сформируйте следующий запрос (рис. 10.14).
SELECT CategoryID, CategoryName FROM Categories
В окне свойств Properties созданного адаптера данных измените его имя (СВОЙСТВО Name) на CategoriesSqlDataAdapter.
Перейдите на вкладку редактора программного кода и сформируйте Web-метод GetCategories (листинг 10.5).
Листинг 10.5Листинг 10.5Рис. 10.14. Формирование запроса для метода GetCategories в окне Query BuilderРис. 10.14. Формирование запроса для метода GetCategories в окне Query Builder
Листинг 10.5
Листинг 10.5
Рис. 10.14. Формирование запроса для метода GetCategories в окне Query Builder
Рис. 10.14. Формирование запроса для метода GetCategories в окне Query Builder
' Visual Basic
<WebMethod()> Public Function GetCategories(ByVal CUSTOMERID As String,’Ъ ByVal PASS As String) As DataSet
Dim Categories As New DataSet()
Dim user As. Boolean
user=CustomerEnter(CUSTOMERID, PASS)
If user Then
CategoriesSqlDataAdapter.Fill(Categories)
End If
Return Categories
End Function
//C#
[WebMethod]
public DataSet GetCategories (string CUSTOMERID, string PASS) {
DataSet Categories;
Categories=new DataSet("Categories");
bool user ;
user=CustomerEnter(CUSTOMERID, PASS); if (user)
{
CategoriesSqlDataAdapter.Fill(Categories);
}
return Categories;
}
На вход данному методу передаются следующие параметры: имя CUSTOMERID, пароль пользователя PASS. Приложению-клиенту метод возвращает набор данных — содержимое таблицы Categories, в разрезе одной категории товара.
В первой и второй строках создаются объектная переменная Categories (набор данных) и булевая переменная user. В третьей строке осуществляется идентификация пользователя путем обращения к функции CustomerEnter, которой передаются в качестве параметров имя и пароль пользователя. Если пользователь зарегистрирован в системе (user=true), то заполнятся набор данных Categories.
Желательно сразу проверить корректности работы этой функции. Для этого выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите пункт Build and Browse. Появится страница с описанием методов Web-сервиса.
Щелкните левой кнопкой мыши на ссылке GetCategories, появится страница тестирования созданного Web-метода.
Наберите существующее в базе данных имя клиента (ANTON), пароль (3), категорию товара (1) и нажмите кнопку Invoke (рис. 10.15).
: Startkage i Service! .asrra.vb [Design] , Service!,а:тхлЬ Browse - Service 1 Web Service I
Servicel
Click here for a complete list of operations,
GetCategories
Test
To test the operation using the HTTP GET protocol, dick the 'Invoke' button,
ParameterValue
CUSTOMERID: [aNTON
PASS:[з
Invoke I
Рис. 10.15. Страница тестирования Web-метода GetCategories
Если все было сделано правильно, то данный метод вернет набор данных с содержимым таблицы Categories в XML-формате (рис. 10.16).
Рис. 10.16. Результаты работы Web-метода GetCategories в формате XML
10.3.3. Функции для работы с заказами клиентов
Реализуем на уровне Web-сервиса функцию получения данных из таблицы с заказами клиентов (GetOrders). Эта функция в качестве параметров должна принять имя и пароль для идентификации прав пользователя, кроме того, имя служит для выборки заказов именно этого клиента. Если идентификационные параметры корректны, то она должна сформировать набор данных с заказами и передать его внешнему приложению. Таким образом, в данной части приложения необходимо использовать таблицу Orders.
Для реализации описанной функции выполните следующие действия.
Из вкладки Data окна ToolBox перетащите на вкладку дизайнера Web-сервиса объект SqlDataAdapter. Будет запущен мастер конфигурации адаптера данных. В окно построителя запросов этого мастера добавьте таблицы Orders и сформируйте следующий запрос (рис. 10.17).
SELECT OrderID, CustomerID, OrderDate
FROM Orders
WHERE(CustomerID=@CustomerID)
В окне свойств Properties созданного адаптера данных измените его имя (СВОЙСТВО Name) На OrdersSqlDataAdapter.
Перейдите на вкладку редактора программного кода и сформируйте Web-метод GetOrders (листинг 10.6).
Рис. 10.17. Формирование запроса для метода GetOrders в окне Query Builder
~—~~..~~~——~^«.^.^.„„„„.^ад. .......««.«Wnm-nm-^-W^—^M^W.~meiV1«iW**WVHW.W м. Листинг 10.6 „.;.....,.;.............
' Visual Basic
<WebMethod()> Public Function GetOrders(ByVal CUSTOMERID As String,Ъ
ByVal PASS As String) As DataSet Dim Orders As New DataSet() Dim user As Boolean user=CustomerEnter(CUSTOMERID, PASS) If user Then SqlSelectCommand5.Parameters("@CustomerID").Value =ъ CUSTOMERID
OrdersSqlDataAdapter.Fill(Orders)
End If
Return Orders
End Function
//C#
[WebMethod]
public DataSet GetOrders (string CUSTOMERID, string PASS) {
DataSet Orders;
Orders=new DataSet("Orders");
bool user ;
user=CustomerEnter(CUSTOMERID, PASS);
if (user)
{
sqlSelectCommand5Paraineters ["@CustomerID"] . Value=CUSTOMERID;
OrdersSqlDataAdapter.Fill(Orders);
}
}return Orders;
На вход данному методу передаются следующие параметры: имя CUSTOMERID и пароль пользователя PASS. Приложению-клиенту метод возвращает набор данных — заказы клиента.
В первой и второй строках создаются объектная переменная Orders (набор данных) и логическая переменная user. В третьей строке осуществляется идентификация пользователя путем обращения к функции CustomerEnter, которой передаются в качестве параметров имя и пароль пользователя. Если пользователь зарегистрирован в системе (user=true), то присваивается значение параметру CustomerID команды select адаптера данных Orders SqlDataAdapter И заполняется набор данных Orders.
Необходимо проверить корректность работы созданной функции. Для этого выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите пункт Build and Browse. Появится страница с описанием методов Web-сервиса.
Щелкнителевойкнопкой мышинассылкеGetOrders,послечегопоя
вится страница тестирования созданного Web-метода.
Наберите существующее в базе данных имя (ANTON), пароль (3) и нажмите кнопку Invoke (рис. 10.18).
Если все было сделано правильно, то данный метод вернет набор данных с содержимым таблицы orders в XML-формате (рис. 10.19).
Пользователь должен иметь возможность добавлять в базу данных новые заказы, для чего мы реализуем на уровне Web-сервиса функцию формирования нового заказа (AddOrders). Эта функция в качестве параметров должна принять имя и пароль для идентификации прав пользователя и выборки заказов именно этого клиента. Если идентификация прошла успешно, то функция должна добавить в базу данных запись с новым заказом клиента, датированным текущим днем. Функция также должна вернуть вы-
звавшему ее приложению признак успешности выполнения данной операции. Таким образом эта часть приложения также использует таблицу Orders.
Рис. 10.18. Страница тестирования Web-метода GetOrders
SU-'Psj- Jswv-’:.«a -b [Desujn] я'»'* aw ■• Hr : aar'Aret wab 'гтг* http://lDcal
- cOrders diffgr:id="Orders V msdata:rowOrder="O*>
<OrderID>10365</OrderID>
<CustomerlD>ANTON</CustomerID>
<OrderDate>1996-ll-27T00:0O:00.nn00O00 + 03:00</OrderDate>
</Orders>
- <Orders diffgr:id="Order$2* msdata:rowOrder="r>
<Order!D>10507</OrderID>
<Custom0rID>AMTOM</CustomerID>
<OrderDate> 1997-04- 15T00:00:00.0000000+04:00</0rder0ate>
Рис. 10.19. Результаты работы Web-метода GetOrders в формате XML
Для реализации метода AddOrders будет использован уже созданный нами ранее адаптер данных OrdersSqlDataAdapter. При его создании кроме команды Select была создана и команда добавления данных insert. Вы можете посмотреть текст этой команды, для чего выполните следующие действия.
Левой кнопкой мыши выделите объект OrdersSqlDataAdapter на панели дизайнера и перейдите в окно свойств Properties.
В окне свойств Properties объекта OrdersSqlDataAdapter раскройте узел InsertCommand и найдите строку со свойством CommandText.
Щелкните мышью на кнопке в строке CommandText, будет открыто окно построителя запросов с текстом команды добавления нового заказа (рис. 10.20).
INSERT INTO Orders
(CustomerID, OrderDate)
VALUES (@CustomerID, @OrderDate);
SELECT OrderID, CustomerID, OrderDate
FROM Orders
WHERE (OrderID=@@IDENTITY)
INSERT INTO Orders
(CustomerlD, OrderDate)
VALUES (©CustomerlD, ©OrderDate);
SELECT OrderlD, CustomerlD, OrderDate FROM Orders
WHERE (OrderlD = ©©IDENTITY)
I _ L ..1...
17 Regenerate parameters collection for tl OK | Cancel
Рис. 10.20. Формирование запроса для метода AddOrders в окне Query Builder
Закройте окно Query Builder, перейдите на вкладку редактора программ
ного кода и сформируйте Web-метод AddOrders (листинг 10.7).
пгпт?"■.-•:"7T"":"™—- - r™;
Листинг 10.7i
' Visual Basic
<WebMethod()> Public Function AddOrders(ByVal CUSTOMERID As String,ъ
ByVal PASS As String) As Boolean
Dim user As Boolean
Dim uspex As Boolean
Dim Dat As Date
Dat=DateTime.Today
user=CustomerEnter(CUSTOMERID, PASS)
If user Then
Try
OrdersSqlDataAdapter.InsertCommand.Parameters
("@CustomerID").Value=CUSTOMERID
OrdersSqlDataAdapter.InsertCommand.Parameters
("@OrderDate").Value=Dat
SqlConnection1.Open()
OrdersSqlDataAdapter.InsertCommand.ExecuteNonQuery()
SqlConnection1.Close()
uspex=True
Catch
uspex=False
End Try
Else
uspex=False
End If
Return uspex
End Function
//C#
[WebMethod]
public bool AddOrders (string CUSTOMERID, string PASS)
{
bool user;
bool uspex;
DateTime Dat=new DateTime();
Dat= DateTime.Today;
user=CustomerEnter(CUSTOMERID, PASS);
if (user)
{
try
{
OrdersSqlDataAdapter.InsertCommand.Parameters
["@CustomerID"].Value=CUSTOMERID;
OrdersSqlDataAdapter.InsertCommand.Parameters^>
["@OrderDate"].Value=Dat;
SqlConnection1.Open();
OrdersSqlDataAdapter.InsertCommand.ExecuteNonQuery();
SqlConnection1.Close();
uspex=true;
}
catch
{
uspex=false;
}
} else
{
uspex=false;
}
return uspex;
}
На вход данному методу передаются следующие параметры: имя CUSTOMERID и пароль пользователя PASS. Приложению-клиенту метод возвращает значение переменной uspex: она имеет значение true при успешном добавлении записи, false в том случае, если заказ не был добавлен.
В первых строках создаются логические переменные user, uspex и Dat (для хранения текущей даты). Затем переменной Dat присваивается значение текущей даты. В следующей строке осуществляется идентификация пользователя путем обращения к функции CustomerEnter, которой передаются в качестве параметров имя и пароль пользователя. Если пользователь зарегистрирован в системе (user=true), то в блоке Try...Catch выполняется добавление нового заказа. В частности параметры команды insert — CustomerID, OrderDate получают значения, открывается соединение с базой данных, вызывается на исполнение команда адаптера данных InsertCommand, закрывается соединение с базой данных и переменной uspex присваивается значение true. Если по каким-либо причинам происходит сбой в выполнении такой последовательности команд или пользователь не зарегистрирован в системе, то переменная uspex получает значение false.
Необходимо проверить корректность работы созданной функции, для чего выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите пункт Build and Browse. Появится страница с описанием методов Web- сервиса.
Щелкнителевойкнопкоймышинассылке AddOrders,послечегопоя
вится страница тестирования созданного Web-метода.
Наберите существующее в базе данных имя пользователя (ANTON), пароль (3) и нажмите кнопку Invoke (рис. 10.21).
Если все было сделано правильно, то данный метод вернет значение true в XML-формате (рис. 10.22).
rsit Pagevb[L" u , S' ■ /ice I c vh Browse - Service! Web Service I I
Servicel
Click hvre for a complete list of operations.
AddOrders
Test
To test the operation using the HTTP GET protocol, click the 'Invoke' button.
ParameterValue
CUSTOMERID: [ANTON
PASS:|3'
Invoke ]
Рис. 10.21. Страница тестирования Web-метода AddOrders
http://local...=ANION&PASS=3 | 'art -age ' ., ■ »! □:.<,i vb[Des-grj ; .
<?xml version=”i.o‘ encoding=‘utf-8* ?>
<boolean xmlns="http://tempuri.org/":>true</boDlean>
Рис. 10.22. Результаты работы Web-метода AddOrders в формате XML
Пользователь должен также иметь возможность удалить заказ из базы данных, для чего мы реализуем на уровне Web-сервиса функцию снятия существующего заказа DelOrders. Эта функция в качестве параметров должна принять имя и пароль для идентификации прав пользователя, а также номер того заказа, который необходимо удалить. Если идентификационные параметры корректны, то она должна удалить из базы данных запись с заказом, а также записи с содержимым этого заказа. Функция должна вернуть вызвавшему ее приложению признак успешности выполнения данной операции. Таким образом, эта часть приложения использует две таблицы Orders И Order Details.
Для реализации функции DelOrders будет использован уже созданный нами ранее адаптер данных Orders SqlDataAdapter. При его создании кроме команды Select была создана и команда удаления данных Delete. Вы можете посмотреть текст этой команды, для чего выполните следующие действия.
Левой кнопкой мыши выделите объект OrdersSqlDataAdapter на панели дизайнера и перейдите в окно Properties.
В окне свойств объекта OrdersSqlDataAdapter раскройте узел Delete
Command и найдите строку со свойством CommandText.
Щелкните мышью на кнопке в строке CommandText, будет открыто окно построителя запросов с текстом команды удаления заказа. Скорректируйте текст запроса, приведя его к следующему виду (рис. 10.23).
DELETE FROM Orders WHERE (OrderID=@Original_OrderID)
Рис. 10.23. Формирование запроса для метода DelOrders в окне Query Builder
Закройте окно Query Builder.
Кроме удаления записи в таблице orders необходимо удалить и содержимое указанного заказа из таблицы Order Details. Для этого необходимо создать и сконфигурировать новый объект DataCommand, для чего выполните следующие действия.
Из вкладки Data окна ToolBox перетащите мышью на вкладку дизайнера Web-сервиса объект SqlCommand.
Войдите в окно свойств Properties созданного объекта SqlCommand, найдитесвойствоName идайтеему новоезначение -
DelDetailsSqlCommand.
Определите значение свойству Connection, для чего раскройте вершину этого свойства, далее раскройте ветку Existing и выберите созданное соединение SqlConnectionl.
Щелкните левой кнопкой мыши кнопку в свойстве CommandText, после чего откроется окно построителя запросов Query Builder.
Добавьте в построитель запросов таблицу order Details и введите текст следующего запроса (рис. 10.24).
DELETE FROM [Order Details] WHERE (OrderID=@Original_OrderID)
Рис. 10.24. Формирование запроса для метода DelOrders в окне Query Builder
Закройте окно Query Builder, перейдите на вкладку редактора программного кода и сформируйте Web-метод DelOrders (листинг 10.8).
; Листинг 10,8
' Visual Basic
WebMethod()> Public Function DelOrders(ByVal CUSTOMERID As String,ъ
ByVal PASS As String, ByVal OrgerID As Int32) As Boolean
Dim user As Boolean
Dim uspex As Boolean
user=CustomerEnter(CUSTOMERID, PASS)
If user Then
Try
OrdersSqlDataAdapter.DeleteCommand.Parametersь
("@Original_DrderID").Value=OrgerID
DelDetailsSqlCommand.Parametersь
("@Original_OrderID").Value=OrgerID
SqlConnection1.Open()
DelDetailsSqlCommand.ExecuteNonQuery()
OrdersSqlDataAdapter.DeleteCommand.ExecuteNonQuery()
SqlConnection1.Close()
uspex=True
Catch
uspex=False
End Try
Else
uspex=False
End If
Return uspex
End Function
//C#
[WebMethod]
public bool DelOrders (string CUSTOMERID, string PASS, int OrgerID)
{
bool user ;
bool uspex ;
user=CustomerEnter(CUSTOMERID, PASS);
if (user)
{
try
{
OrdersSqlDataAdapter.DeleteCommand.Parametersь
["@Original_OrderID"].Value=OrgerID;
DelDetailsSqlCommand.Parametersъ
["@Original_OrderID"].Value=OrgerID;
SqlConnection1.Open();
DelDetailsSqlCommand.ExecuteNonQuery();
OrdersSqlDataAdapter.DeleteCommand.ExecuteNonQuery();
SqlConnection1.Close();
uspex=true;
}
catch
{
uspex=false;
}
}
else
{ uspex=false;
} return uspex;
}
16 Зак 873
На вход данному методу передаются следующие параметры: имя CUSTOMERID, пароль пользователя PASS и номер удаляемого заказа OrderID. Приложению-клиенту метод возвращает значение переменной uspex: она имеет значение true при успешном удалении записей, false — в противном случае.
В первых строках создаются логические переменные user и uspex. В следующей строке осуществляется идентификация пользователя путем обращения к функции CustomerEnter, которой передаются в качестве параметров имя и пароль пользователя. Если пользователь зарегистрирован в системе (user=true), то в блоке Try...Catch выполняется удаление заказа. В частности параметр @Originai_OrderID команды DeleteCommand адаптера данных ordersSqlDataAdapter и такой же параметр команды DelDetailsSqlCommand получают значение номера удаляемого заказа OrderID, затем открывается соединение с базой данных, вызывается на исполнение командаDelDetailsSqlCommand и команда адаптера данных DeleteCommand, закрывается соединение с базой данных и переменной uspex присваивается значение true. Если по каким-либо причинам происходит сбой в выполнении этой последовательности команд или пользователь не зарегистрирован в системе, то переменная uspex получает значение false.
Необходимо проверить корректность работы функции, для чего выполните следующие действия.
Выделите МЫШЬЮ Объект OrdersSqlDataAdapter.
Щелкните правой кнопкой мыши на нем и в появившемся контекстном меню выберите пункт Preview Data.
В открывшемся диалоговом окне Data Adapter Preview заполните набор данных информацией для любого пользователя (рис. 10.25).
Запомните любой номер существующего в базе данных заказа (например, 11089) и закройте окно.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите Build and Browse. Появится страница с описанием методов Web-сервиса.
Щелкнителевой кнопкоймышинассылкеDelOrders,послечегопоя
вится страница тестирования созданного Web-метода.
Наберите существующее в базе данных имя клиента (ANTON), пароль (3), заказ 11089 и нажмите кнопку Invoke (рис. 10.26).
Если все было сделано правильно, то данный метод вернет значение true в XML-формате (рис. 10.27).
Рис. 10.25. Окно просмотра содержимого таблиц базы данных (таблица Orders)
Рис. 10.26. Страница тестирования Web-метода DelOrders
http://1oc6lh™8<OroerID=11089 । -••" =ь ■- vL ^l ^■‘ ci ■ I Sefvi^LesmA.vti
<7xml version=‘1.0” encoding=“utf-8“ ?>
cboofean xmlns=*http://tempuri.org/'>true</boolear>2>
Функции работы с содержимым заказов клиентов
Реализуем на уровне Web-сервиса еще одну функцию — GetDetails, которая позволит пользователям получить содержимое сделанных ими заказов. Эта функция в качестве параметров должна принять имя и пароль для идентификации прав пользователя, а также идентификатор заказа. Если идентификационные параметры корректны, то она должна сформировать набор данных с содержимым заказа и передать его приложению-клиенту. Таким образом, в этой части приложения необходимо использовать таблицу Order Details.
Для реализации метода GetDetails выполните следующие действия.
Из вкладки Data окна TooIBox перетащите мышью на вкладку дизайнера Web-сервиса объект SqiDataAdapter. Будет запущен мастер конфигурации адаптера данных. В окно построителя запросов этого мастера добавьте таблицы Products, order Details и сформируйте следующий запрос (рис. 10.28).
SELECT [Order Details].OrderID, Products.ProductName, [Order Details] . OnitPrice, [Order Details].Quantity
FROM [Order Details] LEFT OUTER JOIN
Products ON [Order Details].ProductID=Products.ProductID
WHERE ([Order Details].OrderID=@OrderID)
Рис. 10.28. Формирование запроса для метода GetDetails а окне Query Builder
В окне свойств Properties созданного адаптера данных измените его имя (СВОЙСТВО Name) на DetailsSqlDataAdapter.
Перейдите на вкладку редактора программного кода и сформируйте
Web-меТОД GetDetails (ЛИСТИНГ 10.9).
Листинг 10.9
' Visual Basic
<WebMethod()> Public Function GetDetails(ByVal CUSTOMERID Asч> String,ByValPASSAsString,ByVal OrderIDAsInt32)AsDataSet
Dim Details As New DataSet() Dim user As Boolean user=CustomerEnter(CUSTOMERID, PASS) If user Then
SqlSelectCommand3.Parameters("@OrderID"),Value=OrderID DetailsSqlDataAdapter.Fill(Details)
End If
Return Details
End Function
//C#
[WebMethod]
public DataSet GetDetails (string CUSTOMERID, string PASS, int OrderID)
{
DataSet Details;
Details=new DataSet("Details");
bool user ;
user=CustomerEnter(CUSTOMERID, PASS);
if (user)
sqlSelectCommand3.Parameters["@OrderID"].Value=OrderID;
DetailsSqlDataAdapter.Fill(Details);
}
return Details;
}
На вход данному методу передаются следующие параметры: имя CUSTOMERID, пароль пользователя PASS, номер заказа OrderID. Приложению- клиенту метод возвращает набор данных — детали заказа.
В первой и второй строках создаются объектная переменная Details (набор данных) и логическая переменная user. В третьей строке осуществляется идентификация пользователя путем обращения к функции CustomerEnter, которой передаются в качестве параметров имя и пароль пользователя. Если пользователь зарегистрирован в системе (user=true), то присваивается значение параметру OrderID команды Select адаптера данных DetailsSqlDataAdapter и заполняется набор данных Details.
Пользователь должен иметь возможность добавлять в заказ новый продукт, для чего реализуем на уровне Web-сервиса функцию добавления в заказ нового продукта — AddDetails. Эта функция в качестве параметров должна принять имя и пароль для идентификации прав пользователя, номер заказа OrderID, номер добавляемого продукта ProductID, цену продукта UnitPrice и количество заказываемого товара Quantity. Если идентификационные параметры корректны, то метод должен добавить в заказ новый элемент (продукт). Функция должна вернуть вызвавшему ее приложению признак успешности выполнения данной операции. Таким образом, эта часть приложения использует таблицу Order Details.
Для реализации функции AddDetails будет использован уже созданный нами ранее адаптер данных DetailsSqlDataAdapter. При его создании кроме команды select была создана и команда добавления данных insert. Вы можете посмотреть или ввести текст этой команды, для чего выполните следующие действия.
Левой кнопкой мыши выделите объектDetailsSqlDataAdapter на пане
ли дизайнера и перейдите в окно свойств Properties.
В строке InsertCommand нажмите левой кнопкой мыши кнопку и выберите New в появившемся списке.
Раскройте свойство connection и выберите соединение с именем SqlConnectionl.
В окне свойств Properties объектаDetailsSqlDataAdapterв узле
InsertCommand найдите свойствоCommandText.
Щелкните мышью на кнопке рядом со свойством CommandText, будет открыто окно построителя запросов с текстом команды добавления нового заказа. Введите текст данного запроса и приведите его к следующему виду (рис. 10.29).
INSERT INTO [Order Details]
(OrderID, ProductID, UnitPrice, Quantity)
VALUES (@OrderID, @ProductID, @UnitPrice, @Quantity)
Рис. 10.29. Формирование запроса для метода AddDetails в окне Query BuilderРис. 10.29. Формирование запроса для метода AddDetails в окне Query Builder
Рис. 10.29. Формирование запроса для метода AddDetails в окне Query Builder
Рис. 10.29. Формирование запроса для метода AddDetails в окне Query Builder
Закройте окно Query Builder, перейдите на вкладку редактора программного кода и сформируйте Web-методAddDetails (листинг ШЛО).
i *®еvrg—"™ «га
Листинг 10.10
?••••• ••»w«.»ew»w»^...«.#.*.A..e.«««niVw4™
' Visual Basic
<WebMethod()> Public Function AddDetails(ByVal CUSTOMERID As String,ъ ByVal PASSAsString,ByValOrderIDAsInt32,ByValProductIDAs’Ь
Int32, ByVal UnitPrice Аз Double, ByVal Quantity As Intl6) As Boolean Dim user As Boolean Dim uspex As Boolean user=CustomerEnter(CUSTOMERID, PASS) If user Then
Try
DetailsSqlDataAdapter.InsertCommand.Parameters
("@OrderID").Value=OrderID
DetailsSqlDataAdapter.InsertCommand.Parameters
("@ProductID"),Value=ProductID
DetailsSqlDataAdapter.InsertCommand.Parameters9
("@UnitPrice").Value=UnitPrice
DetailsSqlDataAdapter.InsertCommand.Parameters
("@Quantity").Value=Quantity
SqlConnection1.Open()
DetailsSqlDataAdapter.InsertCommand.ExecuteNonQuery()
SqlConnection1.Close()
uspex=True
Catch
uspex=False
End Try
Else
uspex=False
End If
Return uspex
End Function
//C#
[WebMethod]
public bool AddDetails (string CUSTOMERID, string PASS, int OrgerID, ъ int ProductID, double UnitPrice, int Quantity)
{
bool user ;
bool uspex ;
user=CustomerEnter(CUSTOMERID, PASS);
if (user)
{
try
{
DetailsSqlDataAdapter.InsertCommand.Parametersь
("@OrderID"]Value=OrgerID;
DetailsSqlDataAdapter.InsertCommand.Parameters
["@ProductID"].Value=ProductID;
DetailsSqlDataAdapter.InsertCommand.Parameters^>
["@UnitPrice"].Value=UnitPrice;
DetailsSqlDataAdapter.InsertCommand.Parametersь
["@Quantity"].Value=Quantity;
SqlConnection1.Open();
DetailsSqlDataAdapter.InsertCommand.ExecuteNonQuery();
SqlConnection1.Close();
uspex=true;
}
catch {
uspex=false;
}
}
else
{
uspex=false;
} return uspex;
}
На вход данному методу передаются следующие параметры: имя CUSTOMERID, пароль пользователя PASS, номер заказа OrderID, номер добавляемого продукта ProductID, цену продукта UnitPrice, количество заказываемого товара Quantity, Приложению-клиенту метод возвращает значение переменной uspex: она имеет значение true при успешном добавлении записи и false — в том случае, если продукт не был добавлен в заказ.
В первых строках создаются логические переменные user и uspex. В следующей строке осуществляется идентификация пользователя путем обращения к функции CustomerEnter, которой передаются в качестве параметров имя и пароль пользователя. Если пользователь зарегистрирован в системе (user=true), то в блоке Try...Catch выполняется добавление в заказ нового продукта. В частности, параметры команды адаптера данных — order ID, ProductID, UnitPrice, Quantity получают значения, открывается соединение с базой данных, вызывается на исполнение команда адаптера данных InsertCommand, закрывается соединение с базой данных и переменной uspex присваивается значение true. Если по каким-либо причинам происходит сбой в выполнении этой последовательности команд или пользователь не зарегистрирован в системе, то переменная uspex получает значение false.
Необходимо проверить корректность работы метода AddDetails. Для этого найдите в базе данных существующий номер заказа и номер продукта, например, с помощью SQL Enterprise Manager, после чего выполните следующие действия.
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите пункт Build and Browse. Появится страница с описанием методов Web-сервиса.
Щелкните левой кнопкой мыши на ссылке AddDetails — появится страница тестирования созданного Web-метода.
Наберите существующее в базе данных имя (ANTON), пароль (3) и прочие параметры и нажмите кнопку Invoke (рис. 10.30).
V rviceLnsn’...A» [Design] ; Sr- sr cl .nr,, »ь Browse - Service! Web Service |
Servicel
Click here for a complete list of operations.
AddDetails
Test
To test the operation using the HTTP GET protocol, click the 'Invoke' button.
ParameterValue
CUSTOMERID: |ANTON
PASS:|з
OrderlD:(11065
ProductID:|1
UnitPrice:(100
Quantity:|2
Invoke |
Рис. 10.30. Страница тестирования Web-метода AddDetails
Если все было сделано правильно, то данный метод вернет значение true в XML-формате (рис. 10.31).
http://localh...l00&Quantity=2 | DerviceLaSm: /ЬГСчЯгп] | Seracni^y ,vb
<?xml version=‘1.0" encoding=,utf-8’ 7>
<boolean xmlns=“http:/ /tempuri .org/*>true</boolean>
Рис. 10.31. Результаты работы Web-метода AddDetails в формате XML
Пользователь должен иметь возможность удалять продукт из заказа, для чего реализуем на уровне Web-сервиса функцию удаления продукта из существующего заказа — DelDetails. Эта функция в качестве параметров должна принять имя и пароль пользователя, номер заказа OrderID и номер продукта, который необходимо удалить ProductID. Если идентификационные параметры пользователя корректны, то метод должен удалить из базы данных запись с указанным номером товара. Функция должна вернуть вызвавшему ее приложению признак успешности выполнения данной операции. Таким образом, эта часть приложения использует таблицу order Details.
Для реализации Web-метода DelDetails будет использован уже созданный нами ранее адаптер данных DetailsSqlDataAdapter. При его создании кро-
ме команды select была создана и команда удаления данных Delete. Вы можете посмотреть текст этой команды, для чего выполните следующие действия.
Левой кнопкой мыши выделите объект DetailsSqlDataAdapter на панели дизайнера и перейдите в окно Properties.
В окне свойств объекта DetailsSqlDataAdapter раскройте узел Delete Command и найдите строку со свойством CommandText. Если эта команда еще не создана, то в узле Delete Command выберите элемент New, после чего в строке свойства Connection выберите соединение sqlConnection1.
Щелкните мышью на кнопке в строкеCommandText,будет открыто окно построителя запросов с текстом команды удаления заказа. Отредактируйте текст запроса, приведя его к следующему виду (рис. 10.32).
DELETE FROM [Order Details]
WHERE (OrderID=@Original_OrderID) AND (ProductID=@Original_ProductID)
Рис. 10.32. Формирование запроса для метода DelDetails в окне Query Builder
Закройте окно Query Builder, перейдите на вкладку редактора программного кода и сформируйте Web-метод DelDetails (листинг 10.11).
Visual Basic
<WebMethod()> Public Function DelDetails(ByVal CUSTOMERID As ъ
String, ByVal PASS As String, ByVal OrderID As Int32, ByVal ProductIDъ
As Int32) As Boolean
Dim user As Boolean
Dim uspex As Boolean
user=CustomerEnter(CUSTOMERID, PASS)
If user Then
Try
DetailsSqlDataAdapter.DeleteCommand.Parameters
("@Original_OrderID").Value=OrgerID
DetailsSqlDataAdapter.DeleteCommand.Parametersъ
("@Original_ProductID"),Value=ProductID
SqlConnection1.Open()
DetailsSqlDataAdapter.DeleteCommand.ExecuteNonQuery()
SqlConnection1.Close()
uspex=True
Catch
uspex=False
End Try
Else
uspex=False
End If
Return uspex End Function
//C#
[WebMethod]
publicboolDelDetails(stringCUSTOMERID, stringPASS, intOrderID,Ч>
int ProductID)
{
bool user ;
bool uspex ;
user=CustomerEnter(CUSTOMERID, PASS); if (user) { try {
DetailsSqlDataAdapter.DeleteCommand.Parameters
["@Original_OrderID"],Value=OrderID;
DetailsSqlDataAdapter.DeleteCommand.Parametersь
["@Original_ProductID"].Value=ProductID;
SqlConnection1.Open();
DetailsSqlDataAdapter.DeleteCommand.ExecuteNonQuery (); SqlConnection1.Close();
uspex=true;
} catch
{ uspex=false;
}
} else {
uspex=false;
}
return uspex;
}
На вход данному методу передаются следующие параметры: имя CUSTOMERID, пароль )пользователя PASS и номер его заказа OrderID, а также номер удаляемого продукта ProductID. Приложению-клиенту метод возвращает значение переменной uspex: она имеет значение true при успешном удалении записи, false в том случае, если продукт не был удален из заказа.
В первых строках создаются логические переменные user и uspex. В следующей строке осуществляется идентификация пользователя путем обращения к функции CustomerEnter, которой передаются в качестве параметров имя и пароль пользователя. Если пользователь зарегистрирован в системе (user=true), то в блоке Try...Catch выполняется удаление продукта из заказа. В частности, параметры команды DeleteCommand адаптера данных DetailsSqlDataAdapter — Original_OrderID И Original_ProductID — получают значения, открывается соединение с базой данных, вызывается на исполнение команда адаптера данных DeleteCommand, закрывается соединение с базой данных и переменной uspex присваивается значение true. Если по каким-либо причинам происходит сбой в выполнении данной последовательности команд или пользователь не зарегистрирован в системе, то переменная uspex получает значение false.
Необходимо проверить корректность работы созданной функции. Для этого войдите в режим предварительного просмотра данных, возвращаемых адаптером DetailsSqlDataAdapter и запомните номер любого заказа и продукта, входящего в заказ, например, заказ — 11065, продукт — 54 (рис. 10.33) и выполните следующие действия.
Рис. 10.33. Просмотр содержимого таблицы OrderDetails в окне предварительного просмотра данных
В окне Solution Explorer щелкните правой кнопкой мыши на файле Servise1.asmx и в появившемся контекстном меню выберите пункт Build and Browse. Появится страница с описанием методов Web-сервиса.
Щелкните левой кнопкой мыши на ссылке DelDetails, появится страница тестирования созданного Web-метода.
Наберите существующее в базе данных имя клиента (ANTON), пароль (3), номер заказа (11065), номер продукта (54) и нажмите кнопку Invoke (рис. 10.43).
Зег лссз ®mx,vb[t>ragn] 1 'serxel-WfAb Browse • Service! Web Service |
Servicel
Click here for a complete list of operations.
DelDetails
Test
To test the operation using the HTTP GET protocol, click the 'Invoke' button.
ParameterValue
CUSTOMER1D: |aNTON
PASS:[5
OrgerlD:|1106S
ProductlD:[54
Invoke ’
Рис. 10.34. Страница тестирования Web-метода DelDetails
Если все было сделано правильно, то данный метод вернет значение true в XML-формате (рис. 10.35).
http://localh.^&ProductlD=S4 | S«wcei -згпг.уЬ[О«»зп1 I Ser -cel v,'r . r-o I
<?xml versions’1.0" encoding=’utf-8" ?>
<boolean xmlns="http://tempuri,org/’>true</boolean>
Рис. 10.35. Результаты работы Web-метода DelDetails в формате XML
На этом закончим разработку серверной части приложения и перейдем к формированию клиентской части.
Разработка клиентской части приложения
Клиентская часть будет реализована в виде Web-приложения и будет состоять из набора Web-форм. На стартовой странице будет выполняться регистрация новых пользователей, а также идентификация зарегистрированных пользователей. Имя и пароль должны передаваться каждой функции Web- сервиса и использоваться практически на каждой странице сайта, где обеспечивается доступ к базе данных. При этом пользователь должен ввести имя и пароль всего один раз, после чего эти параметры должны быть сохранены. Обычно после идентификации пользователя эти параметры сохраняются в коллекции SessionState.
Первый шаг — создание Web-приложения, для чего необходимо выполнить следующие действия.
В строке меню File откройте подменю New, а затем выберите пункт Project.
В появившемся диалоговом окне New Project необходимо сделать следующее:
в дереве Project Types выберите тип проекта Visual Basic Projects или Visual C# Projects;
в области Templates выберите тип приложения ASP.NET Web Application;
в поле Location, введите полный адрес для вашего приложения. Он должен включать http://, имя сервера и имя проекта. У вас должен быть установлен Web-сервер (IIS) версии 5,0 и выше, а также .NET Framework. Если Web-сервер установлен на вашем компьютере, то в качестве имени сервера можно задать http://localhost. Выберем для нашего проекта имя MyWebSite (рис. 10.36).
Рис. 10.36. Окно создания нового Web-проекта
Примечание
Если у вас есть открытое приложение, то установите переключатель Close Solution.
Когда вы нажмете кнопку ОК, то сформируется новый Web-проект, который будет размещен в корневом каталоге Web-сервера, заданного выше. Кроме того, будет создана страница Web-формы с именем WebForm1.aspx.
Смените имя Web-формы WebForm1.aspx на Default.aspx — она будет стартовой страницей на Web-сайте.
.4.1. Разработка Web-формы для регистрации и идентификации пользователей
На Web-форме будут задействованы следующие элементы управления: текстовые поля для ввода и редактирования данных, метки для описания назначений текстовых полей, кнопки для вызова методов Web-сервиса. Кроме того, для придания Web-странице более привлекательного вида добавим на нее элемент image и вставим в него любую картинку (на реальном сайте это может быть эмблема фирмы), а также изменим фон нашей страницы.
Для добавления на форму рисунка — эмблемы фирмы — выполните следующие действия.
Из вкладки HTML окна Toolbox перетащите на форму объект image.
Щелкните правой кнопкой мыши на объекте image и в контекстном меню выберите пункт Properties. Откроется диалоговое окно <IMG> Property Pages. Нажмите кнопку в строке image source и найдите подходящую картинку на вашем компьютере, после чего нажмите кнопку ОК (рис. 10.37).
Рис. 10.37. Диалоговое окно <IMG> Property Pages
ПримечаниеПримечание
Примечание
Примечание
При разработке сайта все используемые рисунки перенесите в папку images вашего Web-сервера, например, C:\lnetpub\wwwroot\images\, и ссылайтесь на файлы с рисунками именно из этой папки. Если рисунки будут располагаться в других папках, то они "потеряются", когда к вашей Web-странице будут обращаться пользователи из сети Интернет.
Для изменения фона Web-формы выполните следующие действия.
Щелкните правой кнопкой мыши в любом свободном месте Web- формы.
В появившемся контекстном меню выберите пункт Properties. Откроется диалоговое окно DOCUMENT Property Pages. Нажмите кнопку в
строке Background image и найдите подходящую для фона картинку в каталогах вашего компьютера, после чего нажмите кнопку ОК (рис. 10.38).
Рис. 10.38. Диалоговое окно DOCUMENT Property Pages
При разработке сайта все рисунки, используемые для фона, также должны располагаться в папке images вашего Web-сервера, например, C:\Inetpub\wwwroot\images\.
Для добавления элементов управления к форме выполните следующие действия.
Извкладки WebFormsокнаToolboxперетащитенаформуэлементы
управления и сконфигурируйте их свойства (табл. 10.1).
Таблица 10.1. Значения свойств элементов управления Web-формы
Элементы
Назначение
Свойства
TextBox
Ввод имени
ID:
TextBox1
TextBox
Ввод пароля
ID:
TextBox2
TextBox
Ввод повтора пароля
ID:
TextBox3
TextBox
Вводнаименованияфирмы
ID:
TextBox4
Таблица 10.1. (окончание)
Элементы
Назначение
Свойства
TextBox
Ввод имени (при входе в систему)
ID: TextBox5
TextBox
Ввод пароля (при входе в систему)
ID: TextBox6
Button
Регистрация нового пользователя
ID: Button1
Text: Зарегистрироваться
Button
Вход пользователя в систему
ID: Button2
Text: Вход
Добавьте метки перед каждым элементом управления для описания его назначения.
Расположите элементы управления на форме согласно рис. 10.39.
Start Page Default.aspx* | Defaut.Mp’-vb |
Добро пожаловать на сайт нашей компании
Регистрация нового пользователяВходное имяПарольПовтор пароляФирмаГ У : ii'. : :; ' ЗарегистрироватьсяРегистрация нового пользователяВходное имяПарольПовтор пароляФирмаГ У : ii'. : :; ' ЗарегистрироватьсяВходзарегистрированного пользователя
Регистрация нового пользователя
Входное имя
Пароль
Повтор пароля
Фирма
Г У : ii'
. : :; ' Зарегистрироваться
Регистрация нового пользователя
Входное имя
Пароль
Повтор пароля
Фирма
Г У : ii'
. : :; ' Зарегистрироваться
Входное имя I
Пароль ; ]
■:. Вход
Рис. 10.39. Расположение элементов управления на форме Default.aspx
В текстовых полях, которые используются для ввода пароля, присвойте свойствуTextMode значениеPassword.
Как правило, на формах регистрации пароль вводится дважды, чтобы убедится, что пользователь при вводе не допустил ошибки.
Из вкладки Web Forms окна Toolbox перетащите на форму элемент CompareValidator и расположите его рядом с текстовым полем TextBox3.
Выделите данный элемент управления проверки правильности данных, перейдите в окно свойств Properties, установите свойства, приведенные в табл. 10.2.
Таблица 10.2. Значения свойств элементов управления Web-формы
Свойства
Значения
ControlToValidate
TextBox3
Text
*
ErrorMessage
Пароли не согласованы.
ControlToCompare
TextBox2
Operator
Equal
Display
Dynamic
Чтобы вывести более подробную информацию об ошибках ввода данных, можно использовать элемент управления ValidationSummary. Этот элемент отображает значение свойства ErrorMessage любого элемента управления проверки правильности данных, который обнаружил ошибку. Если найдено несколько ошибок, то ValidationSummary сможет отобразить их список.
Для отображения ошибок при проверке правильности данных выполните следующие действия.
Из вкладки Web Forms окна Toolbox перетащите на форму элемент ValidationSummary. Расположите его на том месте формы, где есть место для нескольких строк текста.
Установите формат отображения ошибок, выбрав один из пунктов списка свойства DisplayMode.
Установите желаемые значения для свойств Font и ForeColor текста отображения ошибок.
Кроме того, в нижней части формы расположите серверный элемент управления Label, который мы будем использовать для того, чтобы выводить сообщения пользователям в случаях их неверных действий- После этих преобразований форма примет вид как на рис. 10.40.
Вся основная функциональность этой Web-формы нами уже реализована на уровне Web-сервиса. Чтобы вызвать соответствующие методы Web-сервиса нужно, во-первых, добавить ссылку на Web-сервис, во-вторых — создать обработчик события нажатия двух кнопок. Начнем с добавления Web-ссылки.
Рис. 10.40. Добавление элементов контроля вводимых данных на форму Default.aspx
Для добавления Web-ссылки на Web-сервис выполните следующие действия.
В меню Project нажмите Add Web Reference.
В поле Address диалогового окна Add Web Reference введите адрес Web- сервиса, к которому необходимо обратиться, например,http: //
<servername>/MyWebServicel/Service1.asmx
Если вы создавали Web-сервис на вашем локальном компьютере, то необходимо набрать http://localhost/MyWebService1/Service1.asmx и нажать клавишу <ENTER> (рис. 10.41).
Рис. 10.41. Диалоговое окно Add Web Reference
В завершение нажмите кнопку Add Reference в окне Add Web Reference.
На следующем шаге создадим обработчик события нажатия кнопки Зарегистрироваться. Дважды щелкните на ней и в созданный шаблон обработчика события нажатия кнопки введите следующий код (листинг 10.12).
Листинг 10.12
' Visual Basic
Private Sub Button1_Click(ByVal sender Аз System.Object, ByVal e As%>
System.EventArgs) Handles Button1.Click
Dim ws As New localhost.Service1()
Dim flag As Boolean
flag=ws.CustomerExist(TextBox1.Text)
If flag Then
Label1.Text="Пользователь с таким именем уже есть въ
системе"
Else
ws.RegUser(TextBox1.Text, TextBox2.Text, TextBox3.Text) Session.Clear()
Session.Add("login", TextBox1.Text)
Session.Add("pass", TextBox2.Text)
Response.Redirect("main.aspx")
End If
End Sub
//C#
private void Button1_Click(object sender, System.EventArgs e)
{
localhost.Service1 ws=new localhost.Service1() ;
bool flag;
flag=ws.CustomerExist(TextBox1.Text);
if (flag)
{
Label1.Text="Пользователь с таким именем уже есть^
в системе";
}
else
{
ws.RegUser(TextBox1.Text, TextBox2.Text, TextBox3.Text);
Session.Clear();
Session.Add("login", TextBox1.Text);
Session.Add("pass", TextBox2.Text); Response.Redirect("main.aspx");
} }
В первой строке создается объектная переменная ws, которая формируется на основе созданного нами ранее Web-сервиса и ссылки, указанной в WebReference. Дальше объявляется переменная flag. После ввода регистрационных данных в первую очередь необходимо проверить, не содержится ли уже в базе данных указанное имя. Это делается в третьей строке путем обращения к функции Web-сервиса CustomerExist, в которую в качестве параметра передается имя пользователя. Если пользователь с таким именем уже есть в системе, то переменная flag получит значение true и в метку Label будет вставлено сообщение "Пользователь с таким именем уже есть в системе". В противном случае будет вызван метод Web-сервиса RegUser, который внесет в базу данных регистрационные сведения о новом пользователе. В качестве параметров функции передается та информация, которую пользователь внес в текстовые поля. После вызова этой функции необходимо сохранить имя и пароль пользователя в элементах коллекции Session, чтобы использовать их во время всего сеанса работы пользователя с сайтом без повторного ввода. Для этого сначала принудительно очищается содержимое коллекции при помощи метода Clear, а затем с помощью метода Add добавляется в коллекцию два элемента: имя (login) и пароль (pass). В качестве значений этих элементов указываются введенное пользователем содержимое соответствующих текстовых полей.
После того, как имя и пароль сохранены, пользователя необходимо переадресовать на Web-страницу, которая предоставляет доступ к соответствующим информационным ресурсам Web-сайта. В данном примере эта страница будет иметь имя main.aspx, мы создадим ее немного позже.
В случае, если пользователь уже ранее регистрировался в системе, необходимо проверить, есть ли в базе данных соответствующие регистрационные данные. Если они есть, то необходимо запомнить имя, пароль и отправить на страницу с информационными ресурсами сайта.
На следующем шаге мы создадим обработчик события нажатия кнопки Вход. Дважды щелкните на ней и в созданный шаблон обработчика события нажатия кнопки введите следующий код (листинг 10.13).
Листинг 10.13
' Visual Basic
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
Dim ws As New localhost.Service1()
Dim flag As Boolean
flag=ws.CustomerEnter(TextBox5.Text, TextBox6.Text)
If flag Then
Session.Clear()
Session.Add("login", TextBox5.Text)
Session.Add("pass" , TextBox6.Text)
Response.Redirect("main.aspx")
Else
Label1.Text="Неверный пароль или имя"
End If
End Sub
//C#
private void Button2_Click(object sender, System,EventArgs e)
{
localhost.Service1 ws=new localhost.Service1();
bool flag;
flag=ws.CustomerEnter(TextBox5.Text, TextBox6.Text);
if (flag)
{
Session.Clear();
Session.Add("login", TextBox5.Text);
Session.Add("pass", TextBox6.Text);
Response.Redirect("main.aspx");
}
else
{
Label1.Text="Неверный пароль или входное имя";
}
}
Функция во многом аналогична предыдущей. В первых двух строках описываются переменные. Далее выполняется обращение к методу CustomerEnter созданного ранее Web-сервиса — в качестве параметров методу передается входное имя и пароль пользователя. Если пользователь действительно зарегистрирован в базе данных, то переменная flag получает значение true, в коллекции Session запоминаются параметры пользователя и он направляется на страницу с информационными ресурсами сайта.
Создайте пустую страницу с именем main.aspx, после чего убедитесь в работоспособности вашей Web-формы, Для этого на панели инструментов нажмите кнопку Start и, вводя допустимые и недопустимые значения в текстовые поля, протестируйте логику работы программных модулей (рис. 10.42).
Рис. 10.42. Окно регистрации пользователя на этапе выполнения приложения
Теперь следует подробнее рассказать об очень важном объекте Session, который мы использовали в приведенных выше листингах. Данный объект реализует механизм поддержки сеансов работы пользователей. В частности, позволяет идентифицировать пользователя и отслеживать его работу с сайтом с момента входа. То есть разработчик имеет возможность запрограммировать сопровождение пользователя в его непрерывном "путешествии" по страницам сайта. Часто информацию, введенную пользователем на одних страницах сайта, требуется использовать на других страницах. При этом заранее неизвестно, в какой последовательности пользователь будет посещать те или иные страницы. Информация, сохраненная в коллекции Session, постоянно сохраняется в элементах коллекции на протяжении всего сеанса работы пользователя с сайтом и доступна из программного кода любой страницы. Таким образом, элементы коллекции Session, можно использовать как переменные, в которых можно сохранить любую информацию с
одной страницы сайта, чтобы потом использовать ее на других страницах в течение всего сеанса работы пользователя с сайтом.
Разработка Web-формы для получения доступа к каталогу товаров
Каталог товаров разместим на Web-форме с именем main.aspx, которую мы создали в предыдущем разделе (на данный момент эта форма пустая). На Web-форме будут задействованы следующие элементы управления: DropDownList — для выбора категории товаров, DataGrid — для отображения содержимого каталога товаров, кнопка Button — для перехода на страницу с заказами клиента. На данной странице для получения информации из базы данных будут использованы два метода созданного нами ранее Web- сервиса: метод GetCategories — для получения перечня категорий товаров и заполнения им элемента DropDownList, метод GetProducts — для получения перечня товаров и заполнения им элемента DataGrid. Кроме того, для придания Web-странице более привлекательного вида добавим на нее элемент image и вставим в него любую картинку (она должна символизировать характер продаваемых товаров), изменим фон нашей страницы (сделаем его соответствующим фону страницы регистрации пользователей), а также добавим элемент Label, в котором отобразим для пользователей назначение данной страницы.
Для добавления на форму рисунка выполните следующие действия.
Из вкладки HTML окна Toolbox перетащите на форму объект image.
Щелкните правой кнопкой мыши на объекте image и в появившемся контекстном меню выберите пункт Properties. Откроется диалоговое окно IMG Property Pages. Нажмите кнопку в строке Image source и найдите подходящую картинку на вашем компьютере, после чего щелчком на кнопке ОК закройте окно (рис. 10.43).
Рис. 10.43. Диалоговое окно IMG Property Pages
Для изменения фона Web-формы выполните следующие действия.
Щелкните правой кнопкой мыши в любом свободном месте Web- формы.
В появившемся контекстном меню выберите пункт Properties. Откроется диалоговое окно DOCUMENT Property Pages. Щелкните на кнопке в строке Background image и найдите подходящую для фона картинку, после чего нажмите кнопку ОК (рис. 10.44).
Рис. 10.44. Диалоговое окно DOCUMENT Property Pages
При разработке сайта все рисунки, используемые для фона, также должны располагаться в папке images Web-сервера, например, С:\Inetpub\wwwroot\images\.
Для добавления элементов управления к форме выполните следующие действия.
ИзвкладкиHTMLокнаToolboxперетащитенаформуэлементуправ
ления Label, произведите двойной щелчок на нем и введите текст — "Каталог товаров". Щелкните на элементе правой кнопкой мыши и в контекстном меню выберите пункт Build Style. В открывшемся окне Style Builder назначьте по вашему усмотрению размер и цвет шрифта.
ИзвкладкиWebFormsокнаToolboxперетащитена формуэлементы
управления DropDownList И DataGrid.
Выделите мышью элемент DataGrid, щелкните на этом элементе правой кнопкой мыши и в контекстном меню выберите пункт Auto Format. Выберите любой, понравившийся вам стиль форматирования (в примере использован Professional1).
Из вкладки Web Forms окна Toolbox перетащите на форму элементы управления Button. В окне Properties данного элемента найдите свойство Text и введите в него новое название кнопки заказы.
Расположите элементы управления на форме согласно рис. 10.45.
На следующем шаге к данной странице необходимо добавить соответствующую функциональность. В данном случае при открытии страницы необходимо заполнить данными элемент управления DropDownList. Затем, когда пользователь выберет категорию интересующего его товара, нужно заполнить данными элемент управления DataGrid.
Рис. 10.45. Расположение элементов управления на форме main.aspx
Щелкните дважды левой кнопкой мыши в любом свободном месте формы, после чего откроется редактор программного кода. Найдите обработчик события загрузки страницы Page_Load и внесите в него следующий программный код (листинг 10.14).
Листинг 10.14
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, ByVal e Assv System. EventArgs) Handles MyBase.Load
If Not IsPostBack Then
Dim ws As New localhost.Service1()
Dim ds As New DataSet()
Dim log, pass As String
log=Session.Item("login")
pass=Session.Item("pass")
ds.Merge(ws.GetCategories(log, pass))
DropDownList1.DataSource=ds
DropDownList1.DataMember="Categories"
DropDownList1.AutoPostBack=True
DropDownList1.DataTextField="CategoryName"
DropDownList1.DataValueField="CategoryID"
DropDownList1.DataBind()
End If
End Sub
//С#
private void Page_Load(object sender, System.EventArgs e)
{
if (! Page.IsPostBack)
{
localhost.Service1ws=newlocalhost.Service1();
DataSet ds;
ds=new DataSet("Categories");
string log;
string pass;
log=(string) Session["login"];
pass=(string)Session["pass"];
ds.Merge(ws.GetCategories(log, pass));
DropDownList1.DataSource=ds;
DropDownList1.DataMember="Categories";
DropDownList1.AutoPostBack=true;
DropDownList1.DataTextField="CategoryName";
DropDownList1.DataValueField="CategoryID";
DropDownList1.DataBind();
}
}
Загрузка данными элемента DropDownList выполняется в блоке после оператора ifNot IsPostBack,тоестьэтапроцедураделаетсятолькоодинраз,
при первой загрузке страницы. В первых строках выполняется объявление переменных: ws — объектная переменная для ссылки на используемый приложением Web-сервис, ds — набор данных, log и pass — текстовые переменные для хранения значений имени и пароля.
На следующем шаге переменные log и pass получают значения имени и пароля из соответствующей коллекции элемента session — имя и пароль были сохранены в этой коллекции на странице идентификации пользователя.
Далее заполняется набор данных ds путем вызова его метода Merge. Фактически же вызывается метод GetCategories созданного ранее Web-сервиса, которому в качестве параметров передаются имя и пароль пользователя. В итоге, всего одной строкой программного кода набор данных ds заполняется записями из таблицы Categories базы данных Northwind.
В конце формируются свойства элемента управления DropDownList и осуществляется его связывание с набором данных ds. В качестве источника данных DataSource задается объект набор данных — ds. В качестве таблицы источника данных DataMember задается таблица — Categories. Свойству AutoPostBack присваивается значение true, что означает автоматическую передачу выбора пользователя на сервер. Поле categoryName будет показываться в списке элемента DropDownList, Значение ключевого поля CategoryID можно будет использовать в приложении по усмотрению пользователя — значение этого ключевого поля будет соответствовать выбранной пользователем категории товара.
Щелкните дважды левой кнопкой мыши на элементе управления DropDownList, после чего откроется редактор программного кода и сформируется обработчик события изменения пользователем индекса отображаемого В списке элемента DropDownList1_SelectedIndexChanged. В обработчик данного события внесите следующий программный код (листинг 10.15).
Листинг 10.15 >.'....'..>..оа.молмим^МоЛоЛхийаххама/ааОхоЛажо'Лхо^хх^^а.^м^^м^ aaBaaaa—a№...~...'n.aUl4l
' Visual Basic
Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As^ Sys- tem.Object, ByVal e Аs System.EventArgs) Handles Drop-
DownList1.SelectedIndexChanged
Dim ws As New localhost.Service1()
Dim ds As New DataSet()
Dim log, pass As String
Dim categoryid As String
log=Session.Item("login")
pass=Session.Item("раss")
categoryid=DropDownList1.SelectedItem.Value
ds.Merge(ws.GetProducts(log, pass, categoryid))
DataGrid1.DataSource=ds
DataGrid1.DataBind()
End Sub
//C#
privateprivatevoid DropDownList1_SelectedIndexChanged(object sender, ^ Sys-
private
private
tem.EventArgs e)
{
localhost.Service1 ws=new localhost.Service1();
DataSet ds;
ds=new DataSet("Categories");
string log;
string pass;
string categoryid;
log=(string) Session["login"];
pass=(string)Session["pass"];
categoryid=DropDownList1.SelectedItem.Value;
short category=System.Convert.ToInt16(categoryid);
ds.Merge(ws.GetProducts (log, pass, category));
DataGrid1.DataSource=ds;
DataGrid1.DataBind();
}
В первых строках выполняется объявление переменных: ws — объект для ссылки на используемый приложением Web-сервис, ds — набор данных, log и pass — текстовые переменные для принятия значения имени и пароля, categoryid — переменная для хранения выбранной пользователем категории товара.
На следующем шаге переменные log и pass получают значения имени и пароля из соответствующей коллекции элемента session, имя и пароль должны быть сохранены в этой коллекции на странице идентификации пользователя.
Далее переменной categoryid присваивается значение кода категории товара, который пользователь выбрал в элементе управления DropDownList.
На следующем шаге заполняется набор данных ds путем вызова метода Merge. Фактически же вызывается метод GetProducts созданного ранее Web-сервиса, которому в качестве параметров передаются имя и пароль пользователя, а также категория интересующего товара. В итоге, всего одной строкой программного кода набор данных ds заполняется записями из таблицы Products базы данных Northwind.
В конце формируются свойства элемента управления DataGrid. В качестве источника данных DataSource задается объект набор данных ds и осуществляется его связывание с набором данных.
Теперь можем проверить корректность работы созданной нами Web-формы. Для этого запустите приложение, введите имя и пароль на странице идентификации пользователя. После того, как откроется страница с каталогом товаров, в элементе DropDownList выберите любую категорию товаров. В объекте DataGrid отобразятся записи с характеристиками различных товаров (рис. 10.46). Выберите другую категорию товаров, заполнение сетки должно соответственно измениться.
Рис. 10.46. Форма main.aspx на этапе работы приложения
Нам осталось добавить функциональность кнопки Заказы — при ее нажатии должна появляться форма с заказами клиента. Дважды щелкните левой кнопкой мыши кнопку и в редакторе кода введите следующую команду (листинг 10.16).
Листинг 10.16
' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As^ System. EventArgs) Handles Button1.Click
Response.Redirect("zakaz.aspx")
End Sub
//C#
private void Button1_Click(object sender, System.EventArgs e) {
Response.Redirect("zakaz.aspx") ;
}
Здесь выполняется всего одна команда — вызов формы zakaz.aspx, в которой можно будет работать с заказами клиента.
Конечно, созданная нами страница требует некоторой доработки, например, нужно сформировать удобочитаемые заголовки столбцов элемента DataGrid, сделать разбивку этого элемента на страницы. Тем не менее, мы уже добились главной цели — требуемой функциональности приложения.
Разработка Web-формы для получения доступа к заказам клиентов
Для работы с заказами клиентов мы создадим новую Web-форму с именем zakaz.aspx, для чего выполните следующие действия.
В меню Project выберите опцию Add Web Form, после чего откроется диалоговое окно Add New Item.
На вкладке Template данного окна выделите элемент Web Form, а в поле Name введите имя создаваемой формы "zakaz.aspx" и нажмите кнопку Open (рис. 47).
Рис. 10.47. Окно добавления к проекту новой Web-формы
После этого форма будет добавлена к проекту. На Web-форме будут нами задействованы следующие элементы управления:
Q DropDownList — для выбора номера заказа:
Q DataGrid — для отображения содержимого заказа (перечня товаров);
Q несколько кнопок Button для инициализации следующих действий: добавление заказа, удаление заказа, добавление товара в заказ, возврат на предыдущую страницу;
Q удаление товара из заказа реализуем с помощью кнопки, которая будет размещена непосредственно в строке с удаляемым товаром;
Q кроме того, разместим на форме две метки Label для отображения по- ясняющихнадписей.
На данной странице для взаимодействия с базой данных будут использованы следующие методы Web-сервиса: метод GetOrders для получения перечня заказов клиента и заполнения им элемента DropDownList, метод GetDetails для получения перечня товаров, составляющих заказ, и заполнения им элемента DataGrid. Методы AddOrders и DelOrders для добавления нового и удаления существующего заказа. Метод DeltDetails — для удаления товаров из заказа. Кроме того, для придания Web-странице более привлекательного вида изменим ее фон, приведя его в соответствие остальным страницам сайта).
Для изменения фона Web-формы выполните следующие действия.
Щелкните правой кнопкой мыши в любом свободном месте Web- формы.
В появившемся контекстном меню выберите пункт Properties. Откроется диалоговое окно DOCUMENT Property Pages. Нажмите кнопку в строке Background image и найдите на компьютере подходящую для фона картинку, после чего нажмите кнопку ОК (рис. 10.48).
Рис. 10.48. Диалоговое окно DOCUMENT Property Pages
При разработке сайта все рисунки, используемы для фона, также должны располагаться в папке images Web-сервера, например, C:\Inetpub\wwwroot\images\.
Для добавления элементов управления к форме выполните следующие действия.
Из вкладки HTML окна Toolbox перетащите на форму два элемента управления Label.
Двойным щелчком на элементе откройте его для редактирования и введите текст Заказы. Щелкните на этом же элементе правой кнопкой мыши и в контекстном меню выберите пункт Build Style. В открывшемся окне Style Builder назначьте по своему усмотрению размер и цвет шрифта.
Повторите эти действия для второй метки Label, с той лишь разницей, что в нее необходимо внести текст товары в заказе.
ИзвкладкиWeb FormsокнаToolboxперетащитенаформуэлементы
управления DropDownList, DataGrid.
Выделите мышью элемент DataGrid, щелкните на нем правой кнопкой мыши и в контекстном меню выберите пункт Auto Format. Выберите любой понравившийся стиль форматирования (например, Professional1).
Добавьте к элементу DataGrid колонку с кнопками для обеспечения возможности удаления записи. Для этого выделите мышью элемент DataGrid, в окне его свойств Property нажмите на ссылку Property Builder, после чего откроется диалоговое окно DataGrid Properties.
В нем перейдите на вкладку Columns и в левом дереве Available columns раскройте узел Button Column.
Выделите левой кнопкой мыши колонку с названием Delete и нажмите кнопку > для переноса колонки в правую область Selected Columns.
В поле Text введите наименование колонки Удалить, в списке Button Туре выберите PushButton и нажмите кнопку ОК (рис. 10.49).
Из вкладки Web Forms окна Toolbox перетащите на форму четыре элемента управления Button. В свойство Text этих элементов введите следующий текст: Button1 — Добавить заказ, Button2 — Удалить заказ, Button3 — Добавить товар, Button4 — <-Каталог товаров.
Расположите элементы управления на форме согласно рис. 10.50.
На следующем шаге к данной странице необходимо добавить соответствующую функциональность. В частности, при открытии страницы необходимо заполнить данными о заказах клиента элемент управления DropDownList. Затем, когда пользователь выберет интересующий его заказ, нужно заполнить данными о товарах, составляющих заказ, элемент управления DataGrid.
Рис. 10.49. Диалоговое окно DataGrid Properties
Рис. 10.50. Расположение элементов управления на форме zakaz.aspx
Щелкните дважды левой кнопкой мыши в любом свободном месте формы, после чего откроется редактор программного кода. Найдите обработчик события загрузки страницы Page_Load и внесите в него следующий программный код (листинг 10.17).
Листинг 10,17
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As -: System. EventArgs) Handles MyBase.Load
If Not IsPostBack Then
Dim ws As New localhost.Service1()
Dim dsOrders As New DataSet()
Dim dsDetais As New DataSet()
Dim log, pass As String
Dim orderid As String
log=Session.Item("login")
pass=Session.Item("pass") dsOrders.Merge(ws.GetOrders(log, pass)) DropDownList1.DataSource=dsOrders DropDownList1.DataMember="Orders" DropDownList1.AutoPostBack=True DropDownList1.DataTextField="OrderID"
DropDownList1.DataBind()
orderid=DropDownList1.SelectedItem.Value dsDetais.Merge(ws.GetDetails(log, pass, orderid)) DataGrid1.DataSource=dsDetais
DataGrid1.DataBind()
Session.Item("OrderID")=orderid
End If
End Sub
//C# private void Page_Load(object sender, System.EventArgs e)
{
if (! Page.IsPostBack)
{ localhost.Service1 ws=new localhost.Service1();
DataSet dsOrders;
dsOrders=new DataSet("Orders");
DataSet dsDetais;
dsDetais=new DataSet("[Orders Detais]");
string log;
string pass;
string orderid;
log=(string) Session["login"];
pass=(string) Session["pass"];
dsOrders.Merge(ws.GetOrders(log, pass));
DropDownList1.DataSource=dsOrders;
DropDownList1.DataMember="Orders";
DropDownList1.AutoPostBack=true;
DropDownList1.DataTextField="OrderID";
DropDownList1.DataBind();
orderid=DropDownList1.SelectedItem.Value;
short order=System.Convert.ToInt16(orderid);
dsDetais.Merge(ws.GetDetails(log, pass, order));
DataGrid1.DataSource=dsDetais;
DataGrid1.DataBind();
Session["OrderID"]=orderid;
}
}
Загрузка данными элемента DropDownList выполняется в блоке после оператора ifNotIsPostBack,тоестьэтапроцедура делаетсятолькоодинраз,
при первой загрузке страницы. В первых строках выполняется объявление переменных: ws — объект для ссылки на используемый приложением Web- сервис, dsOrders — набор данных (заказы), dsDetais — набор данных (детали заказа), log и pass — текстовые переменные для принятия значения имени и пароля, orderid — номер выбранного пользователем заказа.
На следующем шаге переменные log и pass получают значения имени и пароля из соответствующей коллекции элемента session (имя и пароль были сохранены в ней на странице идентификации пользователя).
Далее заполняется набор данных dsOrders, путем вызова его метода Merge. При этом фактически вызывается метод GetOrders созданного ранее Web- сервиса, которому в качестве параметров передаются имя и пароль пользователя. В итоге, всего одной строкой программного кода набор данных dsOrders заполняется записями из таблицы Orders базы данных Northwind.
Затем формируются свойства элемента управления DropDownList и осуществляется его связывание с набором данных dsOrders. В качестве источника данных DataSource задается объект набор данных — dsOrders. В качестве таблицы источника данных DataMember задается таблица — Orders. Свойству AutoPostBack присваивается значение true, означающее автоматическую передачу выбора пользователя на сервер. Поле OrderID будет показываться всписке элементаDropDownList.
Наконец, переменной orderid присваивается значение номера текущего заказа и заполняется набор данных dsDetais. Фактически же вызывается метод GetDetails созданного ранее Web-сервиса, которому в качестве параметров передаются имя, пароль пользователя и номер заказа. Наконец, формируются свойства объекта DataGrid, и он связывается с набором данных dsDetais. В последнем операторе в коллекции Session запоминается номер текущего заказа — он нам пригодится на странице добавления в заказ нового элемента, которую мы будем создавать в следующем разделе.
Щелкните дважды левой кнопкой мыши на элементе управления DropDownList, после чего откроется редактор программного кода и будет Выведен Обработчик DropDownList1_SelectedIndexChanged события изменения пользователем индекса отображаемого в списке элемента. Внесите в подпрограмму следующий программный код (листинг 10.18).
nz7ГГ— 1
Листинг 10.18
' Visual Basic
Private Sub DropDownList1_SelectedIndexChanged(ByVal sender AsSys-
tem.Object, ByVal e As System.EventArgs) Handles Drop- DownList1.SelectedIndexChanged
Dim ws As New localhost.Service1()
Dim dsDetais As New DataSet()
Dim log, pass As String
Dim orderid As String
log=Session.Item("login")
pass=Session.Item("pass")
orderid=DropDownList1.SelectedItem.Value dsDetais.Merge(ws.GetDetails(log, pass, orderid)) DataGrid1.DataSource=dsDetais
DataGrid1.DataBind()
Session.Item("OrderID")=orderid
End Sub
//С#
private void DropDownList1_SelectedIndexChanged(object sender, System. EventArgs e)
{
localhost.Service1 ws=new localhost.Service1();
DataSet dsDetais;
dsDetais=new DataSet("[Orders Detais]");
string log;
string pass;
string orderid;
log=(string) Session["login"];
pass=(string)Session["pass"] ;
orderid=DropDownList1.SelectedItem.Value;
short order=System.Convert.ToInt16(orderid) ;
dsDetais.Merge(ws.GetDetails(log, pass, order));
DataGrid1.DataSource=dsDetais ;
DataGrid1.DataBind();
Session["OrderID"]=orderid;
}
В первых строках выполняется объявление переменных: ws — объект переменная для ссылки на используемый приложением Web-сервис, dsDetais — набор данных (детали заказа), log и pass — текстовые переменные для принятия значения имени и пароля пользователя, orderid — номер выбранного пользователем заказа.
На следующем шаге переменные log и pass получают значения имени и пароля из соответствующей коллекции элемента session (имя и пароль были сохранены в этой коллекции на странице идентификации пользователя).
Затем переменной orderid присваивается значение номера текущего заказа и заполняется набор данных dsDetais. При этом фактически вызывается метод GetDetails созданного ранее Web-сервиса, которому в качестве параметров передаются имя, пароль пользователя и номер заказа. Наконец, формируются свойства объекта DataGrid, и он связывается с набором данных dsDetais. В последнем операторе в коллекции session запоминается номер текущего заказа.
На этом шаге мы реализовали процедуры загрузки страницы и смены пользователем номера заказа, т. е. просмотр данных. Теперь необходимо реализовать функции, которые будут связаны с нажатием имеющихся на форме кнопок. Начнем с функций добавления и удаления заказов.
Дважды щелкните на кнопке Добавить заказ и в сформированный шаблон обработчика события нажатия кнопки добавьте следующий код (листинг 10.19).
.................................. - _.™....._..„...........T...n..._.,.Jr.,._n_.„„ _.......„.„г...„т..._—,„ .^...
Листинг 10.19
:....:IlL-L—
' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As4>
System.EventArgs) Handles Button1.Click
'Добавить заказ
Dim ws Аs New localhost.Service1( )
Dim dsOrders As New DataSet()
Dim log, pass As String
Dim uspex As Boolean
log=Session.Item("login")
pass=Session.Item("pass")
uspex=ws.AddOrders( log, pass)
If uspex Then
dsOrders. Merge (ws.GetOrders(log, pass) ) DropDownList1.DataSource=dsOrders DropDownList1.DataBind()
End If
End Sub
//C#
private void Button1_Click(object sender, System.EventArgs e)
{
//Добавить зказ
localhost.Service1 ws=new localhost.Service1();
DataSet dsOrders;
dsOrders=new DataSet("Orders");
string log;
string pass;
bool uspex;
log=(string) Session["login"];
pass=(string)Session["pass"];
uspex=ws.AddOrders(log, pass);
if (uspex)
{
dsOrders.Merge(ws.GetOrders(log, pass));
DropDownList1.DataSource=dsOrders;
DropDownList1.DataBind();
}
}
В первых строках выполняется объявление переменных: ws — объектная переменная для ссылки на используемый приложением Web-сервис, dsOrders — набор данных (заказы), log и pass — текстовые переменные для принятия значения имени и пароля, uspex — признак успешного выполнения операции добавления заказа.
На следующем шаге переменные log и pass получают значения имени и пароля из соответствующей коллекции элемента session, в которой были сохранены имя и пароль на странице идентификации пользователя.
Затем вызывается метод AddOrders созданного ранее Web-сервиса для добавления заказа, которому в качестве параметров передаются имя и пароль пользователя. Результаты работы этого Web-метода присваиваются переменной uspex. Далее в блоке IF проверяется успешность выполнения операции добавления заказа. Если заказ был добавлен в базу данных, то обновляется набор данных dsOrders и элемент DropDownList. Таким образом, добавленный заказ появится в выпадающем списке.
Дважды щелкните на кнопке Удалить заказ и в код шаблона обработчика события нажатия кнопки добавьте следующие команды (листинг 10.20).
Листинг 10.20
' Visual Basic
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As^ Sys- tem.EventArgs) Handles Button2.Click
'Удалить заказ
Dim ws As New localhost.Service1()
Dim dsOrders As New DataSet()
Dim log, pass As String
Dim orderid As String
Dim uspex As Boolean
log=Session.Item("login")
pass=Session.Item("pass")
orderid=DropDownList1.SelectedItem.Value uspex=ws.DelOrders(log, pass, orderid)
If uspex Then
dsOrders.Merge(ws.GetOrders(log, pass))
DropDownList1.DataSource=dsOrders
DropDownList1.DataBind()
End If
End Sub
//C#
private void Button2_Click(object sender, System.EventArgs e) {
//'Удалить заказ
localhost.Service1 ws=new localhost.Service1();
DataSet dsOrders;
dsOrders=new DataSet("Orders");
string log;
string pass;
string orderid;
bool uspex;
log=(string) Session["login"];
pass=(string)Session["pass"];
orderid=DropDownList1.SelectedItem.Value;
short order=System.Convert.ToInt16(orderid);
uspex=ws.DelOrders(log, pass, order);
if (uspex)
{
dsOrders.Merge(ws.GetOrders(log, pass));
DropDownList1.DataSource=dsOrders;
DropDownList1.DataBind();
}
}
В первых строках выполняется объявление переменных: ws — объектная переменная для ссылки на используемый приложением Web-сервис, dsOrders — набор данных заказов, log и pass — текстовые переменные для принятия значения имени и пароля, orderid — номер выбранного пользователем заказа, uspex — признак успешного выполнения операции удаления заказа.
На следующем шаге переменные log и pass получают значения имени и пароля из соответствующей коллекции элемента session, имя и пароль были сохранены в этой коллекции на странице идентификации пользователя.
Затем присваивается значение переменной orderid (номер удаляемого заказа) и вызывается метод DelOrders созданного ранее Web-сервиса для удаления заказа, которому в качестве параметров передаются имя, пароль пользователя и номер заказа. Результаты работы этого Web-метода присваиваются переменной uspex. Далее в блоке IF проверяется успешность выполнения операции удаления заказа. Если заказ был удален из базы данных, то обновляется набор данных dsOrders и элемент DropDownList. Таким образом, удаленный заказ исчезает из выпадающего списка.
Дважды щелкните на кнопке <-Каталог товаров и добавьте следующие команды в его программный код (листинг 10.21),
Листинг 10.21
' Visual Basic
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As^ System. EventArgs) Handles Button4.Click
Response.Redirect("main.aspx")
End Sub
//C#
private void Button4_Click(object sender, System.EventArgs e)
{
Response.Redirect("main.aspx");
}
После нажатия на кнопку <-Каталог товаров пользователь должен вернуться на предыдущую страницу main.aspx к каталогу товаров.
Ну и, наконец, дважды щелкните на кнопке Добавить товар и в сформированный обработчик события нажатия кнопки добавьте следующий код (листинг 10.22).
рт - —3 ;— —- : - ,
Листинг 10.22
•
' Visual Basic
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As’Ъ System. EventArgs) Handles Button3.Click
Response,Redirect("AddProducts.aspx")
End Sub
//C#
private void Button3_Click(object sender, System.EventArgs e)
{
Response.Redirect("AddProducts.aspx");
}
При нажатии на кнопку Добавить товар пользователь должен попасть на следующую страницу — AddProducts.aspx, на которой он будет иметь возможность добавлять в выбранный на текущий момент заказ новые товары. Созданием этой страницы мы займемся в следующем разделе.
Разработка Web-формы для добавления товаров в заказ клиента
Для работы с заказами клиентов создадим новую Web-форму с именем AddProducts.aspx. Для создания формы выполните следующие действия.
В меню Project выберите пункт Add Web Form, после чего откроется диалоговое окно Add New Item.
2, На вкладке Template данного окна выделите элемент Web Form, а в поле Name введите имя создаваемой формы AddProducts.aspx и нажмите кнопку Open.
Затем форма будет добавлена к проекту. На Web-форме нами будут задействованы следующие элементы управления:
О DropDownList — для выбора категории товара;
Q DataGrid — для отображения товаров определенной категории;
Q две кнопки Button — для инициализации следующих действий: добавление товара в заказ и возврат на предыдущую страницу;
Q кроме того, разместим на форме текстовое поле (для ввода количества заказываемого товара);
Q разместим два элемента Label для отображения поясняющих надписей.
На данной странице для взаимодействия с базой данных будут использованы следующие методы созданного нами ранее Web-сервиса: метод GetCategories — для получения категорий товара и заполнения им элемента DropDownList, метод GetProducts — для получения перечня товаров и заполнения им элемента DataGrid, методы AddDetails — для добавления нового товара в заказ. Кроме того, для придания Web-странице более привлекательного вида изменим ее фон — сделаем его соответствующим фону остальных страниц сайта.
Для изменения фона Web-формы выполните следующие действия.
Щелкните правой кнопкой мыши в любом свободном месте Web- формы.
В появившемся контекстном меню выберите пункт Properties. Откроется диалоговое окно DOCUMENT Property Pages. Нажмите кнопку в строке Background image и найдите на компьютере подходящую для фона картинку, после чего нажмите кнопку ОК.
Для добавления элементов управления к форме выполните следующие действия.
ИзвкладкиHTMLокнаToolboxперетащитенаформудваэлемента
управления Label.
Дважды щелкните на одном из них левой кнопкой мыши и введите следующий текст категория товара. Щелкните на этом же элементе правой кнопкой мыши и в контекстном меню выберите пукнт Build Style. В открывшемся окне Style Builder назначьте по своему усмотрению размер и цвет шрифта.
Повторите действия шага 2 для второй надписи, с той лишь разницей, что в нее необходимо внести текст количество.
ИзвкладкиWeb FormsокнаToolboxперетащитенаформуэлементы
управления DropDownList и DataGrid.
Выделите мышью элемент DataGrid, щелкните на этом элементе правой кнопкой мыши и в контекстном меню выберите пункт Auto Format. Выберите любой, понравившийся вам стиль форматирования (например, Professional1).
Добавьте к элементу DataGrid колонку с кнопками для обеспечения возможности выделения записи. Для этого выделите мышью элемент DataGrid, в окне свойств Property нажмите на ссылку Property Builder, после чего откроется диалоговое окно DataGrid Properties.
В нем перейдите на вкладку Columns и в левом поле Available columns раскройте узел Button Column.
Выделите левой кнопкой мыши колонку с наименованием Select и нажмите кнопку > для переноса этой колонки в правый список Selected Columns.
В поле Text введите наименование колонки Отметить, в списке Button Туре выберите PushButton и нажмите кнопку ОК (рис. 10.51).
Рис. 10.51. Диалоговое окно DataGrid Properties
Из вкладки Web Forms окна Toolbox перетащите на форму два элемента управления Button. Свойству Text этих элементов задайте следующий значения: Button1 — Добавить в заказ, Button2 — <-Назад к
заказам.
И. Расположите элементы управления на форме согласно рис. 10.52.
Рис. 10.52. Расположение элементов управления на форме AddProducts.aspx
На следующем шаге к данной странице необходимо добавить соответствующую функциональность. В частности, при открытии страницы необходимо заполнить данными о категориях товаров элемент управления DropDownList. Затем, когда пользователь выберет одну из категорий товара, нужно заполнить данными о товарах элемент управления DataGrid.
Щелкните дважды левой кнопкой мыши в любом свободном месте формы, после чего откроется редактор программного кода. Найдите обработчик события загрузки страницы Page_Load и внесите в него следующий программный код (листинг 10.23).
Листинг 10,23
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As '<■ Sys- tem.EventArgs) Handles MyBase.Load
If Not IsPostBack Then
Dim ws As New localhost.Service1()
Dim ds As New DataSet()
Dim dsProducts As New DataSet()
Dim log, pass As String
Dim categoryid As String
log=Session.Item("login")
pass=Session.Item("pass")
ds.Merge(ws.GetCategories(log, pass))
DropDownList1.DataSource=ds
DropDownList1.DataMember="Categories"
DropDownList1.AutoPostBack=True
DropDownList1.DataTextField="CategoryName"
DropDownList1.DataValueField="CategoryID"
DropDownList1.DataBind()
categoryid=DropDownList1.SelectedItem.Value
dsProducts.Merge(ws.GetProducts(log, pass, categoryid))
DataGrid1.DataSource=dsProducts
DataGrid1.DataBind()
End If
End Sub
//C#
private void Page_Load(object sender, System,EventArgs e) {
if (! Page.IsPostBack)
{
localhost.Service1 ws=new localhost.Service1();
DataSet ds;
ds=new DataSet("Categories");
DataSet dsProducts;
dsProducts=new DataSet("Products");
string log;
string pass;
string categoryid;
log=(string)Session["login"];
pass=(string)Session["pass"];
ds.Merge(ws.GetCategories(log, pass));
DropDownList1.DataSource=ds;
DropDownList1.DataMember="Categories";
DropDownList1.AutoPostBack=true;
DropDownList1.DataTextField="CategoryName";
DropDownList1.DataValueField="CategoryID";
DropDownList1.DataBind();
categoryid=DropDownList1.SelectedItem.Value;
short category=Systern.Convert.ToInt16(categoryid);
dsProducts.Merge(ws.GetProducts(log, pass, category));
DataGrid1.DataSource=ds.Products;
DataGrid1.DataBind();
}
}
Загрузка данными элемента DropDownList выполняется в блоке после оператора if Not IsPostBack, то есть эта процедура делается только один раз, при первой загрузке страницы. В первых строках выполняется объявление переменных: ws — объект переменная для ссылки на используемый приложением Web-сервис, ds — набор данных (категории товаров), dsProducts — набор данных (товары), log и pass — текстовые переменные для принятия значения имени и пароля, categoryid — номер выбранной пользователем категории товара.
На следующем шаге переменные log и pass получают значения имени и пароля из соответствующей коллекции элемента session — имя и пароль были сохранены в этой коллекции на странице идентификации пользователя.
Далее заполняется набор данных ds путем вызова его метода Merge. Фактически же вызывается метод GetCategories созданного ранее Web-сервиса, которому в качестве параметров передаются имя и пароль пользователя. В итоге, всего одной строкой программного кода набор данных ds заполняется записями из таблицы Categories базы данных Northwind.
Затем формируются свойства элемента управления DropDownList и осуществляется его связывание с набором данных ds. В качестве источника данных DataSource задается объект набор данных ds. В качестве таблицы источника Данных DataMember задается таблица Categories. Свойству AutoPostBack присваивается значение true — автоматически передавать выбор пользователя на сервер. Поле CategoryName будет отображено в списке DropDownList. Поле CategoryID связывается со свойством DropDownList1.DataValueField.
Наконец, переменной categoryid присваивается значение номера текущей категории товара, и заполняется набор данных dsProducts. При этом фактически вызывается метод GetProducts созданного ранее Web-сервиса, которому в качестве параметров передаются имя, пароль пользователя и категория товара. Наконец, формируются свойства объекта DataGrid и он связывается с набором данных dsProducts.
Щелкните дважды левой кнопкой мыши на элементе управления DropDownList, после чего откроется редактор программного кода со сформированным обработчикомDropDownList1_SelectedIndexChanged события
изменения выбора в списке. Внесите в обработчик следующий программный код (листинг 10.24).
Листинг 10.24
' Visual Basic
Private Sub DropDownList1_SelectedIndexChanged(ByVal sender AsSy Sys- tem.Object, ByVal e As System.EventArgs) Handles Drop-
DownList1.SelectedIndexChanged
Dim ws As New localhost.Service1()
Dim dsProducts As New DataSet()
Dim log, pass As String
Dim categoryid As String
log=Session.Item("login")
pass=Session.Item("pass")
categoryid=DropDownList1.SelectedItem.Value
dsProducts.Merge(ws.GetProducts(log, pass, categoryid))
DataGrid1.DataSource=dsProducts
DataGrid1.DataBind()
End Sub
//C#
private void DropDownList_SelectedIndexChanged(object sender, ^ Sys- tem.EventArgs e)
{
localhost.Service1 ws=new localhost.Service1();
DataSet dsProducts;
dsProducts=new DataSet("Products");
string log;
string pass;
string categoryid;
log=(string) Session["login"];
pass=(string)Session["pass"];
categoryid=DropDownList1.SelectedItem.Value;
short category=System.Convert.ToInt16(categoryid);
dsProducts.Merge(ws.GetProducts(log, pass, category));
DataGrid1.DataSource=dsProducts;
DataGrid1.DataBind();
}
В первых строках выполняется объявление переменных: ws — объект- ссылка на используемый приложением Web-сервис, dsProducts — набор данных, log и pass — текстовые переменные для принятия значения имени и пароля, categoryid — переменная для хранения выбранной пользователем категории товара.
На следующем шаге переменные log и pass получают значения имени и пароля из соответствующей коллекции элемента session (имя и пароль были сохранены в ней на странице идентификации пользователя).
Далее переменной categoryid присваивается значение кода категории товара, который пользователь выбрал в элементе управления DropDownList.
На следующем шаге заполняется набор данных dsProducts путем вызова метода Merge. При этом фактически вызывается метод GetProducts созданного ранее Web-сервиса, которому в качестве параметров передаются имя и пароль пользователя, а также категория интересующего его товара. В итоге всего одной строкой программного кода набор данных dsProducts заполняется записями из таблицы products базы данных Northwind.
Наконец, формируются свойства элемента управления DataGrid. В качестве источника данных DataSource задается объект набор данных dsProducts и осуществляется его связывание с набором данных.
На этом шаге мы реализовали процедуры загрузки страницы и смены пользователем категории товара, т. е. просмотр данных. Теперь необходимо реализовать функции, которые будут связаны с нажатием имеющихся на форме кнопок. Начнем с функций выделения того товара, который необходимо добавить в заказ — эта кнопка расположена в первой колонке элемента DataGrid.
Дважды щелкните на элементе управления DataGrid и в обработчик события нажатия кнопки (выделение строки элемента DataGrid) добавьте следующий код (листинг 10.25).
| Листинг 10.25
' Visual Basic
Private Sub DataGrid1_SelectedIndexChanged(ByVal sender As ^
System.Object, ByVal e As System.EventArgs) Handles Data-
Grid1.SelectedIndexChanged
TextBox1.Text=1
End Sub
//C#
private void DataGrid1_SelectedIndexChanged(object sender, ^
System.EventArgs e)
{
TextBox1.Text="1";
}
Здесь элементу управления TextBox (количества товара, включаемого в заказ) задается значение 1, впоследствии это значение может быть изменено по усмотрению пользователя.
Дважды щелкните на кнопке Добавить в заказ и в сформированный обработчик события нажатия кнопки добавьте следующий код (листинг 10.26).
; Листинг 10.26
I
' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e Asл Sys- tem.EventArgs) Handles Button1.Click
'Добавить продукт в заказ
Dim OrderID As Int32
Dim ProductID As Int32
Dim UnitPrice As Double
Dim Quantity As Int16
Dim str As String
Dim ws As New localhost.Service1()
Dim log, pass As String
Dim uspex As Boolean
log=Session.Item("login")
pass=Session,Item("pass")
str=Session.Item("OrderID")
OrderID=CType(str, Int32)
ProductID=CType(DataGrid1.SelectedItem.Cells(1).Text, Int32)
UnitPrice=CType(DataGrid1.SelectedItem.Cells(4).Text, Double)
Quantity=CType(TextBox1.Text, Int16) uspex=ws.AddDetailsь
(log, pass, OrderID, ProductID, UnitPrice, Quantity)
End Sub
//C#
private void Button1_Click(object sender, System.EventArgs e)
{
int OrderID;
int ProductID;
double UnitPrice;
short Quantity;
string str;
localhost.Service1 ws=new localhost.Service1();
string log;
string pass;
bool uspex;
log=(string) Session["login"];
pass=(string)Session["pass"];
str= (string) Session["OrderID"];
OrderID=System.Convert.ToInt16 (str);
ProductID=System.Convert.ToInt16(DataGrid1.SelectedItem.b
Cells[1].Text);
UnitPrice=System.Convert.ToInt16(DataGrid1.SelectedItem.ъ
Cells[4].Text);
Quantity=Systein.Convert.ToInt16(TextBox1.Text);
uspex=ws.AddDetails(log, pass, OrderID, ProductID,*ъ
UnitPrice, Quantity);
}
В первых строках выполняется объявление переменных: переменные для принятия значений характеристик добавляемого товара (OrderID — номер заказа, ProductIDидентификатор товара, UnitPrice — цена товара,
Quantity — количество товара, str — строковая переменная). Кроме того, объявляются: ws - объект-ссылка на используемый приложением Web- сервис, log и pass — текстовые переменные для принятия значения имени и пароля, uspex — признак успешного выполнения операции добавления товара в заказ.
На следующем шаге переменные log, pass и str получают значения имени, пароля и номера заказа из соответствующей коллекции элемента session.
Затем присваивается значение переменным, характеризующим выбранный пользователем товар (с преобразованием их значений к требуемому типу) и вызывается метод AddDetails Web-сервиса, который осуществляет добавление товара в заказ. Методу в качестве параметров передаются имя, пароль пользователя и характеристики добавляемого товара. Результаты работы Web-метода присваиваются переменной uspex.
Дважды щелкните на кнопке <-Назад к заказам и в сформированный обработчик события нажатия кнопки добавьте следующий код (листинг 10.27).
Листинг 10.27
' Visual Basic
Private Sub Button2_Click(ByVal sender Аз System.Object, ByVal e As^ System. EventArgs) Handles Button2.Click
Response.Redirect("Zakaz.aspx")
End Sub
//C#
private void Button2_Click(object sender, System.EventArgs e)
{
Response.Redirect("Zakaz.aspx");
}
При нажатии на эту кнопку пользователь должен вернуться на предыдущую страницу Zakaz.aspx к выбору заказов.
На форме Zakaz.aspx осталось реализовать последнюю функцию — удаление товара из заказа. Для этого необходимо написать программный код для обработки события активизации Команды DeleteCommand объекта DataGrid. Для формирования обработчика данного события:
Q для Visual Basic — войдите в редактор программного кода и из выпадающего списка в левой верхней части окна выберите элемент управления DataGrid, а из выпадающего списка в правой верхней части окна — элемент DeleteCommand;
Q для С# — выделите на форме элемент управления DataGrid и войдите в окно свойств Properties, в котором нажмите на кнопку Events в верхней части окна, дважды щелкните левой кнопкой мыши в строке DeleteCommand ИЛИ наберите В ЭТОЙ строке DataGrid1_DeleteCommand.
Будет создан обработчик события DataGrid1_DeleteCommand, дополните его следующим кодом (листинг 10.28).
Листинг 10.28
' Visual Basic
Private Sub DataGrid1_DeleteCommand(ByVal source As Object, ByVal^
e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles^
DataGrid1.DeleteCommand
'Удалить продукт из заказа
Dim ws As New localhost.Service1()
Dim dsDetais As New DataSet 0
Dim log, pass As String
Dim OrderID As Int32
Dim ProductID As Int32
Dim uspex As Boolean Dim index As Integer index=e.Item.ItemIndex log=Session.Item("login") pass=Session.Item("pass") OrderID=CType(DataGrid1.Items(index).Cells(1).Text, Int32) ProductID=CType(DataGrid1.Items(index).Cells(2).Text, Int32) uspex=ws.DelDetails(log, pass, OrderID, ProductID)
If uspex Then
OrderID=DropDownList1.SelectedItem.Value dsDetais.Merge(ws.GetDetails(log, pass, OrderID)) DataGrid1.DataSource=dsDetais
DataGrid1.DataBind()
End If
End Sub
//C#
private void DataGrid1_DeleteCommand(object source,ъ System.Web.UI.WebControls.DataGridCommandEventArgs e) {
//Удалить продукт из заказа localhost.Service1 ws=new localhost.Service1();
DataSet dsDetais;
dsDetais=new DataSet(" [Orders Detais] ") ; string log;
string pass;
int OrderID; int ProductID; bool uspex; int index;
index=e.Item.ItemIndex;
log=(string) Session["login"]; pass=(string)Session["pass"]; OrderID=System.Convert.ToInt16(DataGrid1.Items [index] . V
Cells[1].Text);
ProductID=System.Convert.ToInt16(DataGrid1.Items[index].ъ
Cells[2].Text);
uspex=ws.DelDetails(log, pass, OrderID, ProductID);
if (uspex)
{
OrderID = ъ
System.Convert.ToInt16(DropDownList1,SelectedItem.Value); dsDetais.Merge(ws.GetDetails (log, pass, OrderID));
DataGrid1.DataSource=dsDetais;
DataGrid1.DataBind();
}
}
В первых строках выполняется объявление переменных: ws — объект для ссылки на используемый приложением Web-сервис, dsDetais — набор данных, log и pass — текстовые переменные для принятия значения имени и пароля.
Далее выполняется объявление переменных: переменные для принятия значений характеристик удаляемого товара (OrderID — номер заказа, ProductID идентификатор товара), uspex — признак успешного выполнения операции добавления товара в заказ, index — индекс строки элемента управления DataGrid, из которой удаляется товар,
На следующем шаге переменные log, pass получают значения имени и пароля из коллекции элемента session, а переменные OrderID и ProductID - значения номера заказа и номера товара из соответствующих колонок той строки элемента управления DataGrid, в которой пользователь нажал кнопку Удалить.
Затем и вызывается метод DelDetails Web-сервиса для удаления товара из заказа. Методу в качестве параметров передаются имя, пароль пользователя и характеристики удаляемого товара. Результаты работы этого Web-метода присваиваются переменной uspex. После этого в блоке IF проверяется успешность выполнения операции удаления товара и, в том случае, если товар удален из заказа, выполняется обновление содержимого заказа — вызывается метод Web-сервиса GetDetails и элемента DataGrid, отображающего данные.
10.4.5, Тестирование приложения
Итак, мы реализовали все те функции, которые требуются для работы нашего приложения и теперь можно проверить работоспособность страниц, обеспечивающих работу с заказами. Для этого запустите приложение, вве-
дите имя и пароль на странице идентификации пользователя. После того, как откроется страница с каталогом товаров, перейдите на страницу с заказами. На ней можно последовательно просмотреть все заказы клиента, добавить новый заказ или удалить существующий (рис. 10.53).
<-Каталогтоваров
Заказы
Добавить заказ |
Удалить заказ *
110365
Товары в заказе Добавить товар |
Рис. 10.53. Форма zakaz.aspx на этапе работы приложения
Если нажать на кнопку Добавить товар, то откроется страница, на которой можно изменить категорию товара, отметить заказ любого товара, изменить его количество и добавить в текущий заказ (рис. 10.54).
<-Назад к заказам
Категория товаров I Produce
Добавить в заказ |2Количество
Рис. 10.54. Форма Add Products.aspx на этапе работы приложения
Итак, в этом приложении мы создали несколько страниц Web-сайта, которые обеспечивают взаимодействие с базой данных. На первой странице осуществляется регистрация пользователя в системе (ввод в базу данных информации с удаленного компьютера) и проверка прав доступа к информационным ресурсам (ввод регистрационных данных пользователя и сравнение их с теми, которые хранятся в базе данных). На второй странице производится выборка из базы данных информации с учетом тех критериев, которые задал пользователь. На последующих страницах происходит добавление и удаление информации из таблиц удаленной базы данных. В процессе работы над примером мы научились запоминать регистрационные параметры пользователя и использовать их при обращении к тем или иным информационным ресурсам. Иными словами, мы научились базовым приемам работы с удаленными данными через страницы Web-сайта.
Причем на созданных нами страницах нет ни одного элемента, обеспечивающего взаимодействие с базой данных, все реализовано на уровне Web- сервиса. Единственное, что нам нужно было сделать для получения доступа к методам Web-сервиса, обеспечивающим взаимодействие с базой данных — это добавить к приложению соответствующую Web-ссылку.
Конечно, созданное приложение довольно далеко от идеала, в частности, необходимо изменить заголовки элементов DataGrid, добавить выдачу сообщений пользователю об успешности или неудачи выполнения некоторых операций, поработать с дизайном и т. д. Но в данном примере сознательно упускались эти детали, чтобы максимально упростить программный код и сосредоточится на базовых приемах реализации взаимодействия удаленных пользователей с базами данных.
На сегодняшний день в Интернете имеется достаточно много Web-сайтов, реализованных на основе .NET технологий. Вы можете посмотреть в работе один из них, если загляните на страничку по адресу http://www.santayr- auto.ru. Это представительство в Интернете компании, занимающейся торговлей запасными частями к автомобилям. В качестве хранилища данных используется MS SQL Server 2000, а программное обеспечение полностью написано в среде Visual Studio .NET с использованием языка программирования Visual Basic.