
- •Санкт-Петербургский колледж управления и экономики «Александровский лицей» Горохова т.Н.
- •Раздел 1. Информационные системы и информационная безопасность, темы 1.8-1.13
- •Оглавление
- •1. Проектирование windows-приложений ис
- •1.1. Доступ к данным в Windows-формах с использованием элемента управления DataGrid
- •Построение Windows-формы.
- •Доступ к данным в Windows-формах с использованием элемента управления DataGrid
- •Создание проекта и формы
- •Создание набора данных DataSet
- •Создание и конфигурирование элементов доступа к данным Connection и DataAdapter
- •1.2. Доступ к данным в Windows-формах с использованием текстовых полей. Создание объекта DataSet
- •Добавление элемента управления DataGrid для отображения данных
- •Заполнение элемента управления DataGrid данными
- •1.3.Выборка и сортировка данных через запросы с параметрами
- •Создание проекта и Windows-формы
- •Создание и конфигурирование объектов DataConnection и DataAdapter
- •Создание набора данных
- •Добавление элементов отображения данных
- •Добавление кода для заполнения набора данных
- •Связывание текстовых полей с набором данных
- •Добавление навигации по записям
- •Отображение номера текущей записи
- •Тестирование работы приложения
- •1.4. Работа со связанными таблицами в Windows-формах
- •Создание проекта и Windows-формы
- •Конфигурирование DataConnection и Data Adapter
- •Создание набора данных Dataset
- •Создание реляционных связей между таблицами набора данных
- •Добавление элементов отображения данных
- •Отображение издательств в элементе ListBox
- •Отображение наименований книг в элементе DataGrid
- •Заполнение набора данных
- •Тестирование приложения
- •1.5. Представление связанных таблиц в элементе управления DataGrid
- •Создание проекта и Windows-формы
- •Конфигурирование объектов DataConnection и DataAdapter
- •Добавление элементов управления
- •Заполнение набора данных и создание реляционных связей
- •Тестирование приложения
- •1.6. Добавление, удаление и обновление записей в Windows-формах
- •Создание проекта и формы
- •Создание и конфигурирование элементов доступа к данным
- •Формирование программного кода
- •2. Построение asp-приложений ис с достутом данных через ado.Net
- •2.1.Создание web-проекта и формы .Работа с данными в web-формах
- •2.2. Прямой доступ к базе данных (с помощью хранимых процедур, с данными доступными для чтения)
- •Общие сведения об объекте DataCommand
- •Работа объектов DataCommand
- •Множественные результирующие наборы записей
- •Выполнение команд данных
- •Использование DataCommand адаптером данных
- •2.3.Управление презентацией данных в web-формах
- •Добавление объекта DataCommand к форме или компоненту
- •Свойства объекта Da taCommanc
- •Установка и получение параметров объекта DataCommand
- •Получение возвращаемых значений
- •Выполнение команд, которые возвращают наборы данных
- •Выполнение обновления или модификации базы данных с использованием DataCommand
- •Задание команды Data Command, возвращающей одно значение
- •3. Доступ к бд через web-сервисы
- •3.1.Структура и назначение Web-сервисов
- •3.2.Создание Web-сервисов
- •3.3.Доступ к Web-сервису из клиентского приложения
- •3.4.Реализация бизнес-логики распределенных приложений на основе Web -сервисов
- •3.5.Доспуп к Web-сервисы из Web-приложений
- •3.6. Доступ к Web-сервисам из - Windows -приложений
- •4.Отладка программного изделия
- •4.1.Кодирование программного изделия
- •4.2.Метод индукции.
- •4.3.Метод дедукции.
- •5.Тестирование программного изделия
- •5.1.Определение и принципы тестирования
- •5.2. Методы тестирования программ
- •5.3. Методы проектирования тестовых наборов данных
- •6.Проектирование интерфейсов прикладного программного обеспечения
- •6.1. Виды интерфейсов
- •6.2. Области применения каждого вида
- •6.3.Проектирование интерфейсов
- •Список использованной и рекомендуемой литературы
- •Список электронных источников информации
Мастер создаст объект OleDbConnectionl, содержащий информацию о том, как получить доступ к базе данных, и объект OleDbDataAdapterl, который содержит запрос, указывающий, какие колонки какой таблицы требуется получить из базы данных. Причем оба объекта не содержат самих данных. Следующим шагом необходимо создать еще один объект, который и примет выбранные из базы данные.
Рис. 13.Текст, сформированного запроса
Рис. 14.Перечень элементов, созданных мастером конфигурирования адаптера данных
1.2. Доступ к данным в Windows-формах с использованием текстовых полей. Создание объекта DataSet
После того, как вы задали к какой базе данных необходимо подключиться и определись с информацией, которую желаете получить (через SQL-запросы адаптера данных), вы можете создать объект, который будет содержать сами данные — DataSet. При этом Visual Studio сгенерирует набор данных автоматически, базируясь на запросе, который был определен в адаптере данных.
Для создания набора данных выполните следующие действия.
В меню Data выберите пункт Generate DataSet.
После этого появиться диалоговое окно Generate Dataset (рис.15).
Рис.15. Диалоговое окно Generate Dataset
В появившемся окне вам предложено создать новый DataSet с именем DataSetl, который будет принимать из oleDbDataAdapterl аблицу authors.
Убедитесь, что установлен флажок Add this dataset to the designer, и нажмите кнопку ОК.
В результате Visual Studio сгенерирует класс DataSet1 и схему, которая его описывает — файл DataSet1.xsd. Этот файл можно увидеть в окне Solution Explorer.
В итоге Visual Studio добавит к форме компонент DataSet1.
Итак, вы сделали абсолютно все, чтобы получить требуемую информацию из базы данных (при этом не написали ни строчки программного кода). Теперь необходимо добавить на форму элемент, который позволит отобразить полученную информацию — DataGrid.
Добавление элемента управления DataGrid для отображения данных
В этом разделе вы добавите на форму традиционный элемент управления DataGrid, который обычно используется для отображения всех записей, содержащихся в наборе данных. Как альтернативный вариант отображения информации можно использовать элементы управления TextBox, однако это потребует добавления на форму элементов, позволяющих выполнять навигацию (перемещение) по записям набора данных. При использовании DataGrid в этом нет необходимости.
Для добавления элемента управления DataGrid на форму выполните следующие действия.
Щелкните левой кнопкой мыши в любом свободном месте формы Forml, чтобы форма стала активной и получила фокус.
Из вкладки Windows Forms окна Toolbox, перетащите элемент DataGrid на форму (рис. 16).
Рис.16.Элемент DataGrid в окне Toolbox
3. Нажмите клавишу <F4> для перехода в окно свойств элемента DataGrid.
4. В свойстве DataSource выберите DataSet1 в качестве источника данных (не выбирайте DataSetll.authors).
5. В Свойстве DataMember выберите таблицу authors.
Установив эти два свойства, вы фактически связали DataGrid с таблицей authors из набора данных DataSet1. После этих действий в сетке данных DataGrid появились столбцы с заголовками полей выводимых данных.
6. Измените размер DataGrid так, чтобы в сетке данных было видно несколько колонок и строк (рис. 17) .
Рис.17.Расположение элемента DataGrid на форме
Заполнение элемента управления DataGrid данными
Несмотря на то, что между элементом DataGrid и набором данных DataSet на этапе проектирования установлена связь, заполнение сетки данными автоматически не происходит. Вы должны инициировать этот процесс, вызвав соответствующие методы в программном коде.
Для заполнения DataGrid данными необходимо выполнить следующие действия.
Из вкладки Windows Forms окна Toolbox перенесите на форму элемент управления Button.
Измените свойство кнопки Text с Buttonl на Загрузить.
Двойным щелчком на кнопке создайте заготовку модуля обработки события Click.
Очистите набор данных DataSetn методом clear, затем заполните его данными, используя метод Fill элемента OleDbDataAdapterl.
Следующий программный код иллюстрирует вызов этих методов.
Листинг
‘ Visual Basic
Private Sub Buttonl_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Buttonl.Click
DataSetll.Clear()
OleDbDataAdapterl.Fill(DataSetll)
End Sub
// C#
private void Buttonl.Click(object sender, System.EventArgs e)
{
DataSetll.Clear();
OleDbDataAdapterl.Fill(DataSetll);
}
Как видите, программные коды на Visual Basic и на С# практически ничем не отличаются (за исключением некоторых синтаксических особенностей С#). Запустите ваше приложение, нажмите кнопку Загрузить — и вы увидите результаты работы только что написанной программы (рис. 18).
Рис.18.Элемент DataGrid с загруженными в него данными.
Итак, в результате проделанной работы создана Windows-форма, в которой отображена информация, полученная из базы данных.
1.3.Выборка и сортировка данных через запросы с параметрами
Традиционно при работе с информационными системами пользователю нужна не вся информация из базы данных. Например, требуется выбрать заказы только определенного клиента или книги одного автора и т. п. В этом случае пользователь вводит в определенные элементы формы (или выбирает из справочных таблиц) некую ключевую информацию, на основе которой формируется запрос, возвращающий только заказанные данные.
Использование запросов с параметрами обеспечивает вашему приложению более эффективную работу, позволяя получать отфильтрованные и отсортированные записи и значительно снизить сетевой трафик.
В следующем примере вы модифицируете Windows-форму, которая будет показывать только определенных авторов из базы данных Pubs SQL-севера. Пользователи будут вводить код штата США (например, са для Калифорнии) и объект DataSet будет заполняться данными только тех авторов, которые проживают в данном штате. Для этого необходимо добавить на форму элемент, обеспечивающий пользователю ввод кода штата, модифицировать объекты доступа к данным таким образом, чтобы они возвращали только необходимые пользователю записи.
Для реализации этого примера вам необходимо иметь доступ к базе данных pubs, которая устанавливается при инсталляции MS SQL Server.
Для реализации примера потребуется несколько шагов:
создание формы;
создание и конфигурирование набор данных, на этом этапе будет создан и SQL-запрос, который будет заполнять набор данных записями из базы данных;
добавление элементов отображения информации на форме;
добавление программного кода, который будет обновлять набор данных после того, как пользователь присвоит новые значения параметрам запроса;
добавление программного кода, чтобы обеспечить перемещение между записями набора данных.
Создание проекта и 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-форму в окне дизайнера.
На следующем шаге добавьте к форме и сконфигурируйте набор данных в следующей последовательности.
Создайте адаптер данных, с использованием соответствующего мастера. Адаптер данных содержит SQL-запрос, который будет считывать информацию из таблицы базы данных и передавать ее объекту DataSet. Мастер поможет создать SQL-запрос, а также соединение с базой данных.
Сгенерируйте схему набора данных. При создании схемы Visual Studio создаст и новый класс DataSet, который будет добавлен к форме.
Создание и конфигурирование объектов DataConnection и DataAdapter
Для создания и конфигурирования объектов DataConnection и DataAdapter выполните следующие действия.
Из вкладки Data окна Toolbox, перенесите на форму объект OleDbDataAdapter.
Будет запущен мастер Data Adapter Configuration Wizard, который поможет создать объекты DataConnection и DataAdapter.
В мастере выполните следующие действия.
На второй странице создайте или выберите соединение, указывающее на базу данных Pubs вашего SQL-сервера (рис. 19).
Рис.19. Выбор соединения, указывающего на базу
На третьей странице укажите, что вы хотите использовать SQL- запрос для обращения к базе данных.
На четвертой странице создайте следующий SQL-запрос (рис. 20):
Рис.20. Формирование запроса в окне Query Builder
SELECT au_id, au_lname, state FROM authors WHERE (state=?)
Вопросительный знак (?) представляет собой метку-заполнитель для параметра. (Если вы используете класс SqlDataAdapter, то на месте знака вопроса будет стоять переменная для принятия значения от параметра, например @state.)
Примечание
Для помощи формирования SQL-запроса нажмите Query Builder, чтобы запустить мастер формирования запросов Query Builder. Чтобы сформировать метку-заполнитель для параметра, введите вопросительный знак в столбец Criteria для поля state.
Мастер создаст соединение с базой данных (объект OleDbConnection1) и адаптер данных (объект OleDbDataAdapterl).
Адаптер данных фактически будет содержать четыре SQL-запроса: один для выборки записей, который вы собственно и создали на основе предложения select, а также три дополнительных запроса — для модификации, добавления и удаления записей (на основе предложений update, insert и delete).
В этом примере мы будем использовать только один запрос на выборку записей на основе предложения select. Перечень параметров команды SelectCommand можно посмотреть в окне свойств (рис. 21).
Рис 21. Доступ к коллекции параметров SelectCommand
Сам SQL-запрос с предложением select будет храниться в свойстве SelectCommand адаптера данных. Свойство SelectCommand представляет собой объект команды данных (объект типа OleDbCommand), в котором содержится не только SQL-запрос, но и другая информация, необходимая для выполнения SQL-запроса. Наиболее важным элементом команды данных является коллекция параметров parameters. Эта коллекция содержит набор параметров (типа OleDbParameter), причем каждый параметр соответствует одной из меток-заполнителей (поименованному параметру) SQL-запроса. В этом примере мы использовали одну метку-заполнитель, значит, в коллекции Parameters метке-заполнителю будет соответствовать единственный параметр — значение для поля state (рис. 22).
Рис 22. Коллекция параметров команды SelectCommand
По умолчанию, Data Adapter Configuration Wizard при формировании параметров присваивает им имена соответствующих столбцов таблицы базы данных. В нашем примере задана только одна метка-заполнитель для столбца state, соответственно мастером будет создан один параметр с именем state. Позже мы узнаем, как присвоить значение этому параметру перед выполнением SQL-запроса.
Создание набора данных
После того, как созданы объекты соединения с базой данных и адаптер данных, можно создать набор данных. В Visual Studio можно сгенерировать набор данных автоматически, основываясь на SQL-запросе, который был создан в адаптере данных. Набор данных — это экземпляр класса DataSet, создаваемого на основе XML-схемы (xsd-файла), в которой описываются элементы данного класса (таблицы, колонки и ограничения).
Для создания DataSet нужно выполнить следующие шаги.
1. В меню Data выберите пункт Generate DataSet.
Появится диалоговое окно Generate Dataset (рис. 23).
Рис 23. Диалоговое окно Generate Datase
2. Задайте набору данных имя dsAuthors, убедитесь, что установлен флажок Add this dataset to the designer и затем нажмите кнопку ОК.
После этого Visual Studio сгенерирует класс типизированного набора данных (dsAuthors) и схему, которая описывает его структуру. Схема будет содержаться в файле dsAuthors.xsd, который появится в окне Solution Explorer. Если вы в окне Solution Explorer нажмете кнопку Show All Files на верхней панели, то будет видно, что файл схемы имеет зависимый файл (с расширением vb или cs, в зависимости от используемого языка программирования), содержащий код, который определяет ваш новый класс набора данных (рис. 24).
Рис 24. Окно Solution Explorer после нажатия кнопки Show All Files
Наконец, Visual Studio добавит к форме экземпляр этого класса набора данных (с именем DsAuthors1 в Visual Basic, или dsAuthors1 в С#).
К этому моменту мы создали все элементы, для того, чтобы получить информацию из базы данных и поместить ее в набор данных. Все готово для создания формы, на которой можно отобразить эти данные.
Добавление элементов отображения данных
Для реализации данного примера нужно расположить на форме элементы, с помощью которых пользователь сможет ввести значение штата (текстовое поле state), которое потребуется для выполнения запроса, и отобразить информацию об авторах, полученную из базы данных. Для отображения информации будут использоваться текстовые поля.
Добавьте к форме следующие элементы, дав им те имена, которые приведены в табл. 1.
Добавьте на форму элементы label (напротив каждого текстового поля) и внесите в них функциональное назначение каждого поля. Расположите элементы на форме как показано на рис. 25.
|
Таблица 1 Элементы управления и их свойства
|
||
Элементы |
Назначение элемента |
Имя элемента (Name) |
Значение свойства Text |
TextBox |
Позволяет пользователям вводить обозначение штата (критерий поиска авторов) |
txtStateParameter |
(Пустая строка) |
Button |
Выполняет запрос и заполняет набор данных |
btnShow |
Показать авторов |
TextBox |
Отображает идентификатор автора |
txtAuthorlD |
(Пустая строка) |
TextBox |
Отображает фамилию автора |
txtAuthorLName |
(Пустая строка) |
TextBox |
Отображает штат, в котором живет автор (для демонстрации правильности работы запроса) |
txtAuthorState |
(Пустая строка) |
Рис 25. Расположение элементов отображения данных
Добавление кода для заполнения набора данных
Когда форма появится на экране, набор данных будет пустой (он не заполняется автоматически). В данном примере процедура заполнения объекта DataSet данными будет активизироваться принудительно, когда пользователь нажмет кнопку Показать авторов. При ее нажатии будет выполняться запрос, указанный в адаптере данных, а результаты работы запроса будут помещаться в набор данных.
Перед выполнением запроса ему нужно будет передать значение параметра (код штата). Значение параметра будем брать из текстового поля txtstateParameter, в которое пользователь будет вводить интересующий его штат. Для выполнения запроса будет вызываться метод Fill адаптера данных. Запрограммируйте эти действия.
Дважды щелкните кнопку Показать авторов, чтобы создать процедуру обработки события Click. Добавьте код к обработчику этого события:
Установите значение единственного параметра, требуемого для выполнения SQL-запроса. Параметру присвойте то значение, которое пользователь введет В текстовом Поле txtstateParameter.
Вызовите метод очистки набора банных clear. Если набор данных не очищать, то записи, возвращаемые SQL-запросом, будут каждый раз добавляться в конец набора данных при нажатии на кнопку Показать авторов.
Вызовите метод Fill адаптера данных, передавая ему в качестве параметра тот набор данных, который нужно заполнить.
Описанные выше действия приведены в следующем программном коде.
Листинг
' Visual Basic
Private Sub btnShow_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShow.Click
OleDbDataAdapterl.SelectCommand.Parameters("state").Value=txtstateParameter.Text DsAuthorsl.Clear()
OleDbDataAdapterl.Fill(DsAuthorsl)
End Sub
// C#
private void btnShow_Click(object sender, System.EventArgs e)
{
OleDbDataAdapterl.SelectCommand.Parameters["state"].Value =txtstateParameter.Text;
dsAuthorsl.Clear() ;
OleDbDataAdapterl.Fill(dsAuthorsl);
}
Связывание текстовых полей с набором данных
Три текстовых поля txtAuthorlD, txtAuthorLName, txtAuthorState предназначены для того, чтобы отображать информацию из отдельных записей таблицы authors набора данных. Для того чтобы при смене записей значения текстовых полей обновлялись автоматически, необходимо связать столбцы таблицы данных с текстовыми полями. Механизм связывания гарантирует корректность обновления текстовых полей при смене записей.
Фактически можно связать любое свойство текстового поля с любым столбцом набора данных. В данном примере мы свяжем свойство Text текстового поля с именем столбца, который требуется отобразить.
Связывание текстовых полей с набором данных необходимо выполнить в следующей последовательности.
Вернитесь во вкладку дизайнера формы.
Выделите мышью первое текстовое поле (txtAuthorio) и нажмите клавишу <F4>, чтобы открыть окно свойств Properties.
Раскройте узел DataBindings свойства Text разверните узел авторов dsAuthors и из раскрывающегося списка выберите au_id (рис. 26).
Рис 26. Связывание текстового поля с колонкой таблицы набора данных
Повторите шаги 2 и 3 для двух оставшихся текстовых полей, связав их с полями таблицы DsAuthorsl.authors.au_lname и DsAuthorsl.authors.state.
Итак, мы реализовали возможность отображать содержание записей набора Данных в текстовых полях. Однако у нас пока нет возможности перемещаться между записями набора данных.
Добавление навигации по записям
В заключении добавим к форме элементы, обеспечивающие навигации по записям объекта DataSet. В этом примере мы добавим две кнопки Предыдущая и Следующая, а также добавим текстовое поле, в котором будет отображаться номер текущей записи.
Для получения номера текущей записи таблицы данных используется свойство Position, которое доступно через объект BindingContext. Чтобы перемещаться по записям таблицы набора данных, нужно изменять значение этого свойства. Чтобы определить сколько записей находится в таблице данных, нужно получить значение свойства count объекта BindingContext. Для добавления объектов навигации выполните следующие действия.
Добавьте к форме две дополнительные кнопки, установив их свойства в соответствии с табл. 2.
|
Таблица 2 Свойства элементов управления Button |
Name (имя) |
Text (текст) |
BtnNext BtnPrevious |
Следующая Предыдущая |
2. Создайте обработчик события нажатия кнопки Предыдущая. Добавьте программный код декремента (уменьшения на единицу) свойства Position объекта BindingContext. Код будет выглядеть следующим образом (листинг).
Листинг
' Visual Basic
Private Sub btnPrevious_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrevious.Click
Me.BindingContext(DsAuthorsl, "authors").Position -=1
End Sub
// C#
private void btnPrevious_Click(object sender, System.EventArgs e)
{
this.BindingContext[dsAuthorsl, "authors"].Position -=1;
}
3. Сделайте то же самое для кнопки Следующая, только увеличьте значение свойства Position на единицу (листинг).
Листинг
' Visual Basic
Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As System. EventArgs) Handles btnNext.Click
Me.BindingContext(DsAuthorsl, "authors").Position+=1
End Sub
// C#
private void btnNext_Click(object sender, System.EventArgs e)
{
this.BindingContext[dsAuthorsl, "authors"].Position+=1;
}
Отображение номера текущей записи
Наконец, вы можете создать showPosition метод отобразить позицию текущих записей.
1. Добавьте к форме элемент TextBox, и назовите его txtPosition (рис. 27).
Рис 27. Расположение на форме элементов навигации по записям
Примечание
Присвойте свойству Enabled значение False, чтобы пользователи могли видеть номер текущей записи, но не могли изменить его значение.
2.
Создайте в форме процедуру с именем
showPosition. В этой процедуре получите
количество записей в таблице и номер
текущей записи от объ
екта
BindingContext и отобразите эти значения в
текстовом поле. Программный код листинга
демонстрирует эти действия.
Листинг
' Visual Basic
Private Sub ShowPosition()
Dim iCnt As Integer
Dim iPos As Integer
iCnt=Me.BindingContext(DsAuthorsl, "authors").Count
If iCnt=0 Then
txtPosition.Text="(No records)"
Else
iPos=Me.BindingContext(DsAuthorsl,"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[dsAuthorsl, "authors"].Count;
iPos=this.BindingContext[dsAuthorsl, "authors"].Position+1;
if (iCnt==0)
{
txtPosition.Text="(No records)";
}
else
{
txtPosition.Text=iPos.ToString() + " of " + iCnt.ToString() ;
}
}
3. Добавьте обращение к процедуре ShowPosition в тех фрагментах приложения, где текущая запись могла измениться. Для данного примера это необходимо сделать в следующих местах:
После обращения к методу Fill в обработчике события click кнопки Показать авторов.
После изменения текущей записи в обработчике события click кнопок Предыдущая и Следующая. Например, законченный фрагмент кода для кнопки Предыдущая будет выглядеть следующим образом (листинг).
Листинг
' Visual Basic
Private Sub btnPrevious_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrevious.Click
Me.BindingContext(DsAuthorsl, "authors").Position -=l
ShowPosition()
End Sub
// C#
private void btnPrevious_Click(object sender, System.EventArgs e)
{
this.BindingContext[dsAuthorsl, "authors"].Position -=1;
ShowPosition ();
}
Тестирование работы приложения
Вы можете теперь проверить работу данной формы, чтобы удостовериться, что она отображает именно те данные, которые вы запрашиваете при вводе параметра.
Для тестирования работы формы выполните следующие действия.
Нажмите клавишу <F5> для запуска формы.
Когда форма появится на экране, введите код штата Калифорния (са) в соответствующем текстовом поле, и затем нажмите кнопку Показать авторов.
В текстовых полях будет отображена информация из базы данных о первом авторе, который живет в Калифорнии.
3. Нажимайте кнопки Предыдущая и Следующая, чтобы убедится в корректности перемещения по записям (рис. 28).
Рис 28. Форма во время работы приложения
4. Введите значение нового кода штата в текстовое поле (например, UT для штата Юта), и затем нажмите кнопку Показать авторов.
Вы увидите, что будет отображен новый автор и изменится количество записей.
Есть некоторые дополнения, которые можно добавить в это приложение для удобства работы пользователя.
□ Не вводить коды штатов в текстовое поле, а выбирать их из раскрывающегося списка. Для этого необходимо добавить к форме еще один адаптер данных с SQL-запросом:
SELECT DISTINCT state FROM authors
Затем сгенерировать второй набор данных и связать его с элементом ListBox.
□ В случае отсутствия возвращаемых-записей (в штате нет авторов) выдать соответствующее сообщение, для чего нужно проверить свойство Count объекта BindingContext на нулевое значение. Реализация проверки показана в листинге.
Листинг
' Visual Basic
Private Sub btnShow_Click(ByVal sender As System.Object, ByVal e As System. EventArgs) Handles btnShow.Click
OleDbDataAdapterl.SelectCommand.Parameters("state").Value=txtStateParameter.Text
DsAuthors1.Clear()
OleDbDataAdapterl.Fill(DsAuthors1)
If Me.BindingContext(DsAuthorsl, "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)
{
OleDbDataAdapterl.SelectCommand.Parameters["state"].Value=txtStateParameter.Text;
dsAuthorsi.Clear() ;
OleDbDataAdapterl.Fill(dsAuthorsl);
if (this.BindingContext[dsAuthorsl, "authors"].Count==0)
{
MessageBox.Show("Нет записей для штата " + txtStateParameter.Text);
txtStateParameter.Focus();
}
else
{
ShowPosition();
}
}
□ Отобразить информацию об авторах в сетке данных (DataGrid), а не в текстовых полях, чтобы видеть одновременно несколько записей.
□ Добавить кнопки, которые позволят пользователю добавлять, редактировать и удалять записи об авторах и т. п.
1.4. Работа со связанными таблицами в Windows-формах
Во многих приложениях необходимо работать с данными, которые отображают информацию из нескольких связанных таблиц (использовать реляционные отношения между родительской и дочерней таблицами). Например, Пользователь имеет запись с информацией о клиенте и хочет видеть заказы, сделанные этим клиентом.
Разъединенная модель набора данных в Visual Studio позволяет работать не только с дискретными таблицами в вашем приложении, но и определять отношения между ними. Тогда можно использовать эти отношения, чтобы перемещаться между связанными записями.
Этот приложение иллюстрирует простой, но законченный пример работы со связанными таблицами в наборе данных. Мы создадим Windows-форму, в которой отображается информация об издательствах (родительская таблица), и об изданных ими книгах (дочерняя таблица).
Пример предполагает прохождение следующих шагов:
создание Windows-формы;
создание и конфигурирование набора данных, который содержит две таблицы, создание реляционных отношений между таблицами;
добавление элементов отображения данных и связывание их с соответствующими объектами хранения данных;
формирование программного кода, обеспечивающего заполнение набора данных;
тестирование работы формы.
Создание проекта и 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 и Data Adapter
Работа над созданием соединения и адаптера данных будет происходить следующим образом. Сначала необходимо сформировать адаптеры данных, которые содержат SQL-запросы, заполняющие наборы данных информацией на этапе работы приложения. Как часть этого процесса, автоматически будет создано соединение с базой данных. Для конфигурации адаптеров данных будет использоваться соответствующий мастер. Для данного приложения нужно будет создать два адаптера данных, один, чтобы заполнять данными таблицу Publishers, другой для получения данных из таблицы Titles.
Для создания соединения и адаптеров данных выполните следующие действия.
1. Из вкладки Data окна Toolbox перенесите на форму объект OleDbDataAdapter.
Примечание
Вы можете также использовать объект SqlDataAdapter, который оптимизирован для работы SQL Server версии 7.0 и выше.
Будет запущен мастер Data Adapter Configuration Wizard, который поможет создать объекты DataConnection и DataAdapter.
2. В мастере выполните следующие действия:
На второй странице создайте или выберите соединение, указывающее на базу данных Pubs вашего SQL-сервера;
На третьей странице укажите, что вы хотите использовать именно SQL-запрос для обращения к базе данных;
На четвертой странице создайте следующий SQL-запрос (рис. 29):
SELECT pub_id, pub__name FROM publishers
Примечание
Для помощи формирования SQL-запроса нажмите Query Builder, чтобы запустить мастер формирования запросов Query Builder.
3. Щелкните кнопку Finish для завершения работы мастера.
Мастер создаст соединение с базой данных (объект oieDbConnectioni) и адаптер данных (объект oieDbDataAdapteri), который будет содержать SQL-запрос для получения записей из таблицы Publishers.
Рис 29. Формирование запроса в окне Query Builder
Перетащите на форму второй объект OleDbDataAdapter. Снова будет запущен мастер Data Adapter Configuration Wizard.
В окне мастера выполните следующие действия.
На второй странице выберите то же самое соединение, которое вы использовали или создали для работы с таблицей Publishers.
На третьей странице укажите, что вы хотите использовать именно SQL-запрос для обращения к базе данных;
На четвертой странице создайте следующий SQL-запрос для обращения К таблице Titles.
SELECT titleJLd, title, pub_id, price FROM titles
Примечание
В предложение select необходимо обязательно включить столбец pub_id.
6. Мастер добавит на форму еще один адаптер данных OleDbDataAdapter2. На следующем этапе необходимо будет сгенерировать набор данных.
Создание набора данных Dataset
После того как созданы соединение с базой данных и адаптеры данных, можно создать набор данных. В Visual Studio можно сгенерировать набор данных автоматически, основываясь на SQL-запросах, которые были созданы в адаптерах данных. Набор данных — это экземпляр класса Dataset, создаваемого на основе XML-схемы (xsd-файла), в которой описываются элементы этого класса (таблицы, колонки и ограничения).
Для создания Dataset нужно выполнить следующие шаги.
1. В меню Data выберите пункт Generate DataSet.
Появится диалоговое окно Generate Dataset.
2. Установите переключатель New и задайте набору данных новое имя —dsPublishersTitles. Удостоверьтесь, что в списке таблиц, которые будут добавлены к набору данных (Choose which table(s) to add to the dataset), присутствуют две таблицы: Publishers и Titles (рис. 30), и рядом с ними стоят флажки. Установите флажок Add this dataset to the designer и нажмите кнопку ОК. В результате Visual Studio сгенерирует типизированный набора данных(DsPubiishersTities) и схему, которая определяет структуру этого набора данных. Эта схема (файл DsPublishersTitles.xsd) появится в окне Solution Explorer.
Рис 30. Включение в набор данных двух таблиц
Наконец, Visual Studio добавит к форме экземпляр нового класса набора данных (DsPublishersTitlesl или dsPublishersTitlesl, В зависимости от того, какой язык программирования вы используете).
Создание реляционных связей между таблицами набора данных
В нашем наборе данных содержится две таблицы, которые в базе данных имеют отношения "один ко многим". Однако набор данных — это пассивный контейнер, который не может использовать те связи между таблицами, которые заданы в базе данных. В объекте DataSet реляционные отношения между таблицами нужно задавать явно, через специально предназначенный для этих целей объект.
Примечание
Обратите внимание, что в данном примере в наборе данных таблицы Publisher и Titles физически не объединяются между собой. Через два адаптера данных можно работать с этими двумя таблицами совершенно независимо (добавлять, удалять, модифицировать записи, перемещаться по записям и пр.). В тоже время имеется возможность установить реляционные отношения и рассматривать их как взаимосвязанный набор данных.
Рис 31. Таблицы Publisher и Titles
Рис 32 Диалоговое окно Edit Relation
Для создания реляционных отношений между таблицами нужно выполнить следующие действия.
1. В Solution Explorer дважды щелкните левой кнопкой мыши на схеме набора данных, который вы только что создали (элемент DsPublishersTitles.xsd).
В окне XML Designer откроется вкладка Schema, в которой будут отражены две таблицы набора данных (рис. 31).
2. Из вкладки XML Schema окна Toolbox перетащите мышью объект Relation на таблицу Titles (дочерняя таблица).
Откроется диалоговое окно Edit Relation со значениями параметров связи этих двух таблиц, установленными по умолчанию (рис. 32).
3 Подтвердите, что вы согласны со значениями, установленными по умолчанию в диалоговом окне Edit Relation (табл. 3).
Таблица 3
Значения параметров для установления реляционных связей |
|
Параметр |
Значение параметра (Value) |
Name (имя) |
Publisherstitles |
Parent element (Родительский элемент) |
Publishers |
Child element (Дочерний элемент) |
Titles |
Key Fields (Ключевое поле) |
pub id |
Foreign Key Fields (Поля внешнего ключа) |
pub id |
Create foreign key constraint only |
не установлен |
(Ограничение внешнего ключа) |
|
Остальные значения, не указанные в таблице 3, не важны для выполняемого примера.
Щелкните мышью кнопку ОК для закрытия диалогового окна Edit Relation.
В окне XML Designer появится изображение реляционного отношения между двумя таблицами (рис. 33).
Рис 33. Связанные таблицы в окне XML Designer
Если возникнет потребность изменить параметры связи между таблицами, то нужно щелкнуть правой кнопкой мыши на значке отношения и выбрать пункт Edit Relation в контекстом меню.
6 Сохраните схему и закройте окно XML Designer.
На этом этапе все готового для того, чтобы добавить к форме элементы отображения данных.
Добавление элементов отображения данных
В этом разделе мы добавим на форму несколько элементов управления-ListBox для отображения списка издательств и DataGrid для отображениянаименований книг выбранного издательства. Также добавим элементы Labels для описания элементов формы.
Отображение издательств в элементе ListBox
Элемент ListBox будет отображать названия издательств (содержание таблицы Publishers). Этот элемент позволяет отобразить несколько записей (список издательств).
Вернемся к нашей форме (с именем по умолчанию Forml), которая была открыта при создании проекта. Если вы еще находитесь в окне XML Designer, то переключитесь на вкладку дизайнера формы (выбрав соответствующую позицию табуляции в верхней части текущего окна).
1. Из вкладки Windows Forms окна Toolbox, перетащите на форму элемент ListBox.
Нажмите клавишу <F4> для перехода в окно Properties.
В свойстве DataSource Выберите набор данных DsPublishersTitlesl или dsPublishersTitiesi (в зависимости от языка программирования VB или С#) в качестве источника данных.
В свойстве DispiayMember активизируйте раскрывающийся список. Из списка выберите таблицу Publishers, разверните узел Publishers и затем выберите поле, содержащее наименование издательства — pub_name.
Когда эта процедура будет закончена, свойству DispiayMember будет присвоено значение — publishers, pubname (рис. 34).
Таким образом вы связали элемент ListBox с полем наименования издательства pub_name таблицы издательств publishers.
Рис 34. Связывание элемента ListBox c полем таблицы набора данных
Теперь добавим на форму элемент Label1 и свойству Text этого элемента присвоим значение Наименование издательства (рис. 35).
Рис 35. Расположение на форме элементов отображения
Отображение наименований книг в элементе DataGrid
Каждое издательство может иметь список изданных книг. Каждая книга имеет несколько атрибутов: наименование, автора, год издания и пр. Чтобы отобразить информацию о книгах нужно использовать элемент управления, который может отображать не только несколько записей, но и несколько столбцов. Для этих целей подходит элемент управления DataGrid. Для этого примера мы сконфигурируем DataGrid таким образом, чтобы он показывал только наименования книг, изданных выбранным издательством. Свяжем DataGrid He С таблицей Titles, а С объектом publisherstitles, созданным ранее, который устанавливает реляционные отношения между таблицами Publishers и Titles. Объект publisherstitles представляет собой свойство таблицы Publishers. Во время работы приложения каждый раз, когда пользователь будет перемещаться к новому издательству (выбирая его в списке), будет срабатывать соответствующий метод объекта связи данных. При этом из дочерней таблицы будут отбираться только те записи, которые относятся к выбранной записи родительской таблицы. Для добавления и связывания с данными объекта DataGrid выполните следующие действия.
1. Из вкладки Windows Forms окна Toolbox, перетащите на форму элемент
DataGrid.
2. В свойстве DataSource выберите набор данных DsPublishersTitlesl или dsPubiishersTitiesi (в зависимости от языка программирования VB или С#) в качестве источника данных.
3. Задайте свойству DataMember значение publishers.publisherstitles.
Наберите это значение с помощью клавиатуры или выберите из выпадающего списка (рис. 36).
Рис 36. Связывание элемента DataGrid с объектом реляционных отношений
Установка этих двух свойств связывает элемент DataGrid с объектом реляционных отношений между таблицами. При этом в сетке данных будут всегда отображаться дочерние записи с информацией о книгах издательства, установленного в родительской таблице.
4. Измените размеры сетки данных так, чтобы можно было видеть несколько строк и столбцов (рис. 37).
Рис 37. Расположение на форме элемента управления DataGrid
Заполнение набора данных
Хотя элемент отображения данных на форме связан с набором данных, он сам не заполняется данными автоматически. Этот процесс нужно активизировать из программного кода.
Для заполнения набора данных необходимо выполнить следующие действия.
Дважды щелкните мышью на форме, чтобы создать обработчик события загрузки формы Load.
В обработчике события загрузки формы очистите набор данных, который вы создали ранее (DsPubiishersTitiesi), и затем вызовите метод Fill для двух адаптеров данных, указав им в качестве параметра этот же набор данных. В результате этого будут заполнены данными обе таблицы (Publishers И Titles).
Ниже приведен соответствующий программный код (листинг).
Листинг
' Visual Basic
Private Sub Forml_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DsPublishersTitles1.Clear()
OleDbDataAdapterl.Fill(DsPubiishersTitles1)
OleDbDataAdapter2.Fill(DsPublishersTitles1)
End Sub
// C#
private void Forml_Load(object sender, System.EventArgs e)
{
dsPublishersTitlesl.Clear();
oleDbDataAdapterl.Fill(dsPublishersTitlesl);
oleDbDataAdapter2.Fill(dsPublishersTitlesl);
}
Тестирование приложения
Теперь можно проверить работу форму, чтобы удостовериться в корректности ее работы. Для проверки работы приложения выполните следующие шаги.
Нажмите клавишу <F5> для запуска приложения.
Когда форма будет отображена:
проверьте, что в элементе управление ListBox отображаются наименования издательств;
выбирая различные издательства, убедитесь, что в сетке данных отображаются книги только выбранных издательств (рис. 38).
Рис 38. Отображение результатов работы приложения
Итак, в примере этого раздела были решены две задачи: создан набор данных с двумя таблицами и отношениями между ними и создана Windows-форма, которая отобразила связанные данные. Можно несколько усовершенствовать этот пример:
изменить настройки и дизайн элемента DataGrid для улучшения его внешнего вида;
создать реляционные отношения динамически, в программном коде (в примере реляционные отношения создавались на этапе разработки приложения в XML Designer).
1.5. Представление связанных таблиц в элементе управления DataGrid
В предыдущем примере мы рассмотрели возможность работы со связанными таблицами базы данных с представлением их в различных визуальных элементах управления. Однако эту задачу можно решить с использованием единственного элемента управления, причем уровень иерархии связанных таблиц особой роли не играет. В Visual Studio для этих целей можно использовать элемент управления DataGrid, который имеет встроенный механизм отображения информации из таблиц, имеющих реляционные связи. В примере этого раздела мы рассмотрим три связанные между собой таблицы: Заказчики, Заказы и Детали заказа. Для выполнения этого примера воспользуемся базой данных Northwind, которая поставляется вместе с SQL Server, и где есть соответствующие таблицы: Customers, Orders и Order Details.
Модель набора данных в Visual Studio позволяет работать не только с отдельными таблицами в вашем приложении, но и определять отношения между ними. Тогда можно использовать эти отношения, чтобы перемешаться между связанными записями.
Пример предполагает выполнение следующих этапов:
создание Windows-формы;
создание соединения с базой данных;
создание и конфигурирование адаптеров данных, которые обеспечивают взаимодействие с тремя таблицами базы данных;
добавление элемента управления DataGrid и кнопки (для загрузки и отображения данных);
формирование программного кода, обеспечивающего заполнение набора данных, формирования реляционных связей и связывание набора данных с DataGrid;
тестирование работы приложения.
Создание проекта и Windows-формы
Для создания Windows-формы выполните следующие действия.
Из меню File выберите подменю New, а затем пункт Project.
Появиться диалоговое окно New Project.
В дереве Project Types выберите тип проекта — Visual Basic Projects или Visual C# Projects, и в области Templates укажите вид приложения — Windows Application.
Если у вас открыто другое приложение, то установите переключатель Close Solution в окне New Project.
Задайте проекту новое имя, которое будет уникальным и отражать суть разрабатываемого приложения. Например, в данном случае назовем этот проект winRelation. После задания имени проекта нажмите кнопку ОК.
В примере этого раздела мы не будем создавать набор данных на этапе проектирования. Он будет создан динамически в ходе выполнения приложения. Однако сами таблицы должны быть доступны в приложении, для чего мы создадим три адаптера данных и один объект подключения к базе данных. Так же динамически будут созданы и реляционные связи между таблицами.
Конфигурирование объектов DataConnection и DataAdapter
Сначала необходимо создать адаптеры данных, которые содержат SQL-запросы, заполняющие наборы данных информацией на этапе работы приложения. Как часть этого процесса будет автоматически создано соединение с базой данных. Для конфигурации адаптеров данных будет использоваться соответствующий мастер. Для данного приложения нужно будет создать три адаптера данных для заполнения данными таблиц Customers, Orders и Order Details.
1. На вкладке Data окна Toolbox, дважды щелкните на объекте SqlDataAdapter.
Будет запущен мастер Data Adapter Configuration Wizard, который поможет создать объекты DataConnection и DataAdapter.
2. В мастере выполните следующие действия:
На второй странице создайте или выберите соединение, указывающее на базу данных Northwind вашего SQL-сервера.
На третьей странице укажите, что вы хотите использовать SQL- запрос для обращения к базе данных — установите Use SQL statements.
На четвертой странице создайте следующий SQL-запрос:
SELECT Customers.* FROM Customers
Примечание
Для помощи формирования SQL-запроса нажмите Query Builder, чтобы запустить мастер формирования запросов Query Builder.
3. Щелкните кнопку Finish для завершения работы мастера.
Мастер создаст соединение с базой данных (объект SqlConnection1) и адаптер данных (объект SqlDataAdapter1), который будет содержать SQL-запрос для получения записей из таблицы Customers.
4. Перетащите на форму второй объект SqlDataAdapter. Снова будет запущен мастер Data Adapter Configuration Wizard.
5. В мастере выполните следующие действия:
На второй странице выберите то же самое соединение, которое вы использовали или создали для работы с таблицей Customers.
На третьей странице укажите, что вы хотите использовать SQL- запрос для обращения к базе данных — установите переключатель Use SQL statements.
На четвертой странице создайте SQL-запрос, чтобы обращаться к таблице orders:
SELECT Orders.* FROM Orders
Мастер добавит на форму еще один адаптер данных SqlDataAdapter2.
6. Перетащите на форму третий объект 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 наберите значение Загрузить.
Расположите элементы управления на форме как показано на рис. 39. На этом работа с элементами управлении будет закончена. Все остальные действия будут выполнены в программном коде.
Рис 39. Расположение элементов управления на форме
Заполнение набора данных и создание реляционных связей
В нашем наборе данных будет содержаться три таблицы, которые в базе данных имеют отношения "один ко многим". Однако, набор данных — это пассивный контейнер, который не может использовать те связи между таблицами, которые заданы в базе данных. В объекте DataSet реляционные отношения между таблицами нужно будет задавать явно, через его свойство Relations.
Для начала нужно будет создать экземпляр класса DataSet, открыть соединение и заполнить набор данных. Причем в объекте DataSet будет содержаться три самостоятельных таблицы: Customers, Orders и Order Details. Несмотря на то, что таблицы на уровне базы данных имеют реляционные связи, в DataSet этих связей не будет, все три таблицы будут совершенно независимы друг от друга. Реляционные связи нужно создать самим, воспользовавшись свойством Relations объекта DataSet. В нашем примере главной родительской таблицей является таблица с информацией о заказчиках — Customers. Для нее дочерней таблицей является таблица с информацией о заказах — Orders. Эти две таблицы имеют связующее ключевое поле CustomerID. В свою очередь таблица Orders является родительской таблицей по отношению к таблице с данными о деталях заказов— Order Details. Эти две таблицы имеют связующее ключевое поле OrderID. Схема связей между таблицами приведена на рис. 40.
Рис 40. Схема связей между таблицами Customers, Orders и Order Details
Элемент отображения данных на форме DataGrid не связан с набором данных и он не заполняется данными автоматически. Эти процессы нужно активизировать с помощью команд программного кода.
1-Дважды щелкните мышью на кнопке формы, чтобы создать обработчик cобытия нажатия кнопки Buttonl_Click.
2. В обработчике события выполним следующие действия:
создадим экземпляр класса DataSet (набор данных ds);
откроем соединение;
заполним данными объект DataSet (набор данных ds);
закроем соединение;
создадим реляционную связь между таблицами customers, Orders;
созданим реляционную связь между таблицами Orders и Order Details;
укажем объекту DataGrid в качестве источника данных набор данных ds;
зададим объекту DataGrid отобразить таблицу customers.
Ниже приведен соответствующий программный код (листинг).
Листинг
' Visual Basic
Private Sub Buttonl_Click(ByVal sender As System.Object, ByVal e As System. EventArgs) Handles Buttonl.Click
Dim ds As New DataSet ()
SqlConnectionl.Open()
SqlDataAdapterl.Fill(ds, "Customers")
SqlDataAdapter2.Fill(ds, "Orders")
SqlDataAdapter3.Fill(ds, "OrderDetails")
SqlConnectionl.Close()
ds.Relations.Add("Заказы",ds.Tables("Customers").Columns("CustomerlD"), _
ds.Tables("Orders").Columns("CustomerlD"))
ds.Relations.Add("Детали заказа",ds.Tables("Orders").Columns("OrderlD"), _
ds.Tables("OrderDetails").Columns("OrderlD"))
DataGridl().DataSource=ds
DataGridl().DataMember="Customers"
End Sub
// C#
private void Buttonl_Click (object sender, System.EventArgs e)
{
DataSet ds;
SqlConnectionl.Open ();
SqlDataAdapterl.Fill(ds, "Customers");
SqlDataAdapter2.Fill(ds, "Orders");
SqlDataAdapter3.Fill(ds, "OrderDetails");
SqlConnectionl.Close ();
ds.Relations.Add("Заказы",ds.Tables("customers").Columns("CustomerlD"),
ds.Tables("Orders").Columns("CustomerlD"));
ds.Relations.Add("Детали заказа", ds.Tables("Orders") .Columns("OrderlD"),
ds.Tables("OrderDetails").Columns("OrderlD")); DataGridl().DataSource=ds;
DataGridl().DataMember="Customers";
}
Тестирование приложения
Теперь можно выполнить тестирование приложения, чтобы удостовериться в корректности ее работы и возможности отображения в DataGrid содержимого связанных таблиц.
Для проверки работы приложения выполните следующие действия.
Нажмите клавишу <F5> для запуска приложения.
Когда форма будет отображена на экране, вы увидите пустой элемент DataGrid. Нажмите кнопку Загрузить, после этого элемент управления DataGrid заполнится записями из таблицы Customers, содержащей сведения о заказчиках (рис. 41).
Рис 41. Отображение в DataGrid информации из родительской таблицы Customers
Наименования колонок объекта DataGrid получат значения от наименований соответствующих полей базы данных. В первой колонке будет располагаться указатель текущей записи и знак (+), позволяющий получить доступ к записям дочерних таблиц. Щелкните мышью на значке (+) в любой строке, в DataGrid появится дополнительная строка с ссылкой на содержимое дочерней таблицы (в нашем случае появиться ссылка с надписью Заказы (рис. 42).
Рис 42. Отображение в DataGrid ссылки на дочернюю таблицу с информацией о заказах
Как видно из рис. 42, мы получили возможность просмотреть все заказы клиента с именем ANTON. Нажмите на ссылку Заказы, после этого запись с информацией о заказчике ANTON будет перенесена в верхнюю часть DataGrid, а в самом элементе управления появятся записи из дочерней таблицы Orders (рис. 43). В нашем случае будут отображены сведения о заказах, сделанных заказчиком anton.
Рис 43. Отображение в DataGrid информации из родительской таблицы Customers и дочерней таблицы Orders
В левой крайней колонке снова будет виден значок с надписью (+), нажав на него, мы увидим еще одну строку со ссылкой Детали заказа (рис. 44).
Рис 44. Отображение в DataGrid ссылки на дочернюю таблицу с информацией о деталях заказов
То есть теперь, нажав на ссылку Детали заказа мы сможем получить содержимое любого заказа. При этом в верхней части DataGrid появится еще одна строка с указанием номера отображенного заказа (рис. 45).
Рис 45. Отображение в DataGrid информации из родительских таблиц Customers, Orders и дочерней таблицы Orders Details
Знак (+) в левой колонке исчез — это говорит о том, что у данной таблицы нет дочерних таблиц, и она в иерархии реляционных связей является последней.
Справа и слева верхней части DataGrid появились две кнопки, которые позволяют просмотреть колонки родительских таблиц, не поместившиеся на экран. В правом верхнем углу имеется стрелка, нажав на которую можно закрыть дочернюю таблицу и подняться на один уровень вверх (вернуть на экран содержимое родительской таблицы). Кроме того, данный DataGrid позволяет выполнить сортировку любой таблицы на любом уровне иерархии по любой колонке. Для этого достаточно щелкнуть мышью на заголовке колонки. После этого в заголовке колонки появится небольшая стрелка, указывающая порядок сортировки (по возрастанию или убыванию). При повторном щелчке на той же колонке порядок сортировки меняется на обратный.
Этот пример достаточно убедительно демонстрирует преимущество Visual Studio .NET. Нам удалось реализовать возможность отобразить в одном визуальном элементе три взаимосвязанные таблицы с возможностью их сортировки по любому признаку. При этом было написано всего 10 строк программного кода.
1.6. Добавление, удаление и обновление записей в Windows-формах
Рассмотрим взаимосвязанные процедуры добавления, удаления и обновления записей. Это наиболее частые действия, которые выполняют пользователи при работе с базами данных. В качестве элемента отображения данных будет использоваться элемент управления DataGrid. Этот пример иллюстрирует Windows-форму, которая отображает в сетке содержимое таблицы базы данных. С помощью кнопок пользователь будет иметь возможность добавлять или удалять записи из таблицы базы данных, а элемент DataGrid позволит редактировать данные в любой (в том числе и добавленной) строке.
Для того чтобы реализовать пример этого раздела, нужно иметь доступ к базе данных Northwind, которая автоматически устанавливается при инсталляции MS SQL Server. Вам предстоит выполнить следующие шаги:
создать Windows-проект и, соответственно, Windows-фому;
создать соединение с базой данных connection;
создать объект доступа к базе данных DataAdapter;
создать и сконфигурировать набор данных Dataset;
добавить на форму элемент управления DataGrid и связать его с набором данных DataSet;
добавить на форму три элемента управления Button;
добавить программный код для заполнения набора данных DataSet;
добавить программный код, обеспечивающий функциональность кнопок Добавить, Удалить, Обновить.
Создание проекта и формы
Для создания проекта и формы сделайте следующие шаги.
Выберите опцию меню File, укажите New, и затем выберите Project.
В левой части открывшегося окна выберите Visual Basic Projects или Visual C# Projects, и затем в правой — Windows Application.
Если у вас уже открыто какое-либо другое приложение, установите переключатель Close Solution в окне New Project.
Назовите проект уникальным именем, которое будет ассоциироваться у вас с выполняемыми действиями. Например, данный проект можно назвать WinAddDel.
4. Когда вы назначили имя проекта, щелкните кнопку ОК.
Visual Studio создаст новый проект и отобразит Windows-форму в окне дизайнера.
Создание и конфигурирование элементов доступа к данным
Чтобы получить данные на компьютер пользователя необходимо создать соединение с базой данных и элемент DataAdapter, который содержит SQL-запросы, и используется для заполнения данными элемента DataSet. Для создания соединения с базой данных, адаптера данных и элемента DataSet выполните следующие действия.
1 •Перейдите в окно Server Explorer.
Если вы уже ранее создавали соединение с базой данных Northwind, то в окне Server Explorer появится элемент в узле Data Connections, обеспечивающий доступ к базе данных Northwind.
2. В Server Explorer разверните узел с таблицами Tables базы данных
Northwind.
3. Найдите таблицу Categories, выделите поля CategoryID, CategoryName, Description и перетащите их на вкладку дизайнера формы.
После этого на панели дизайнера появятся два объекта: SqlConnection1
и SqlDataAdapterl. Эти компоненты сконфигурированы для того, чтобы обеспечить передачу информации между набором данных (он будет создан чуть позже) и таблицей Categories базы данных Northwind.
4. Щелкните правой кнопкой мыши на объекте SqlDataAdapterl и в появившемся контекстном меню выберите Generate Dataset. После этого откроется диалоговое окно Generate Dataset, в котором по умолчанию будет установлен переключатель New и указана ссылка на таблицу Categories. Нажмите кнопку ОК.
После этого на панели дизайнера появятся объект Dataset11. На этом этапе мы создали все объекты, необходимые для связи приложения с базой данных.
Далее мы добавим на форму традиционный элемент управления — DataGrid, который обычно используется для отображения всех записей, содержащихся в наборе данных. Для добавления элемента управления DataGrid на форму выполните следующие действия.
Щелкните левой кнопкой мыши в любом свободном месте формы Forml, чтобы форма стала активной и получила фокус.
Из вкладки Windows Forms окна Toolbox перетащите элемент DataGrid на форму.
Нажмите клавишу <F4> для перехода в окно свойств элемента DataGrid.
В свойстве DataSource выберите Dataset11 в качестве источника данных (не выбирайте DataSetll. Categories).
В свойстве DataMember выберите Categories.
Установив эти два свойства, вы фактически связали DataGrid с таблицей Categories из набора данных DataSetll. После этих действий в сетке данных DataGrid появились столбцы с заголовками полей выводимых данных.
6. Из вкладки Windows Forms окна Toolbox, перетащите на форму три элемента Button и свойству Text этих элементов присвойте следующие значения: Buttonl — Добавить, Button2 — Удалить, Button3 — Обновить.
7. Перерисуйте элемент управления DataGrid так, чтобы в сетке данных было видно несколько колонок и строк, и расположите элементы на форме в соответствии с рис. 46.
Рис 46. Расположение элементов на форме
Формирование программного кода
Теперь перейдем к формированию программного кода. Начнем с загрузки формы. В обработчике события загрузки формы необходимо заполнить информацией набор данных Dataset (листинг).
Листинг
' Visual Basic
Private Sub Forml_Load(ByVal sender As System.Object, ByVal e As System. EventArgs) Handles MyBase.Load
SqlDataAdapterl.Fill(DataSetll)
End Sub
//C#
Private void Forml__Load (object sender, System. EventArgs e)
{
SqlDataAdapterl.Fill(dataSetll);
}
Набор данных заполняется путем вызова метода Fill адаптера данных.
На следующих шагах последовательно сформируем программный код для обработки событий нажатия кнопок.
Для обеспечения возможности добавления записи будет использована команда SqlInsertcommand1 адаптера данных. Для получения доступа к тексту этой команды выделите мышью объект SqlDataAdapterl, войдите в окно его свойств и найдите строку InsertCommand. Раскройте ее узел, щелкнув на значке (+), найдите свойство CommandText и нажмите кнопку в этой строке.
Из текста этого запроса видно, что для того чтобы добавить запись в таблицу Categories, необходимо задать значения двум параметрам этого SQL-запроса: @CategoryName и @Description. Это обстоятельство нужно учесть при формировании программного кода. Программный код обработки события нажатия кнопки Добавить приведен в листинге.
Листинг
' Visual Basic
Private Sub Buttonl_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Buttonl.Click
'Добавление записи -
SqlDataAdapterl.InsertCommand.Parameters("@CategoryName").Value=""
SqlDataAdapterl.InsertCommand.Parameters("@Description").Value=""
SqlConnectionl.Open()
SqlDataAdapterl.InsertCommand.ExecuteNonQuery()
SqlConnectionl.Close()
DataSetll.Clear()
SqlDataAdapterl.Fill(DataSetll)
End Sub
//C#
private void buttonl_Click(object sender, System.EventArgs e)
{
//Добавление записи
SqlDataAdapterl.InsertCommand.Parameters["@CategoryName"].Value="";
SqlDataAdapterl.InsertCommand.Parameters["@Description"].Value=""; SqlConnectionl.Open();
SqlDataAdapterl.InsertCommand.ExecuteNonQuery();
SqlConnectionl.Close();
dataSetll.Clear();
SqlDataAdapterl.Fill(dataSetll);
}
В первых двух строках программного кода параметры (@CategoryName и @Description) команды InsertCommand адаптера данных SqlDataAdapterl получают значения (в данном случае пустую строку). Затем открывается соединение с базой данных, исполняется команда InsertCommand (запись добавляется в базу данных) и соединение с базой данных закрывается. В следующих двух строках очищается от данных объект DataSetll и заполняется обновленной информацией из базы данных, путем вызова метода Fin адаптера данных. После этого добавленная запись появится в элементе отображения информации DataGrid.
Для обеспечения возможности удаления записи будет использована команда SqlDeleteCommand1 адаптера данных. Для получения доступа к тексту этой команды выделите мышью объект SqlDataAdapterl, войдите в окно его свойств и найдите строку DeleteCommand. Раскройте этот узел, щелкнув на указателе (+), найдите свойство CommandText и нажмите кнопку в этой строке. Откроется окно построителя запросов Query Builder с текстом соответствующего SQL-запроса. Измените текст этого запроса и приведите его к виду (рис. 48)
DELETE FROM Categories WHERE (CategoryID=@Original_CategoryID)
Рис 48. Формирование запроса в окне Query Builder
Из текста этого запроса видно — для того чтобы удалить запись из таблицы Categories, необходимо задать значения параметра @CategoryID этого SQL-запроса. Значение CategoryID можно получить из текущей ячейки элемента отображения данных DataGrid (при этом будет удалена та запись, которую пользователь выделил в объекте DataGrid). Это обстоятельство нужно учесть при формировании программного кода. Программный код обработки события нажатия кнопки Удалить приведен в листинге
Листинг
' Visual Basic
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Удаление записи
Dim row As Intl6
Dim CategoryID As Intl6
row=DataGridl.CurrentCell.RowNumber
CategoryID=DataSetll.Categories(row).CategoryID
SqlDataAdapterl.DeleteCommand.Parameters("@Original_CategoryID").Value=CategoryID
SqlConnectionl.Open()
SqlDataAdapterl.DeleteCommand.ExecuteNonQuery()
SqlConnectionl.Close()
DataSetll.Clear()
SqlDataAdapterl.Fill(DataSetll)
End Sub
//C#
private void button2_Click(object sender, System.EventArgs e)
{
//Удаление записи
int row ;
int CategoryiD;
row=dataGridl.CurrentCell.RowNumber;
CategoryID=dataSetll.Categories[row].CategoryID;
SqlDataAdapterl.DeleteCommand. Parameters["@Original_CategoryID"].Value=CategoryID;
SqlConnectionl.Open();
SqlDataAdapterl.DeleteCommand.ExecuteNonQuery();
SqlConnectionl.Close();
dataSetll.Clear();
SqlDataAdapterl.Fill(dataSetll);
}
В первых двух строках программного кода выполняется объявление переменных: row — номер текущей строки элемента управления DataGrid, CategoryID — идентификатор удаляемой записи (категория товара). Затем переменная row получает значение текущей строки элемента DataGrid, переменная CategoryiD получает значения идентификатора удаляемой записи (из строки с номером row таблицы Categories набора данных DataSetll). Параметр @Original_CategoryID команды DeleteCommand адаптера данных SqlDataAdapterl получает значение из переменной CategoryID. Затем открывается соединение с базой данных, исполняется команда DeleteCommand (запись удаляется из базы данных) и соединение с базой данных закрывается. В следующих двух строках очищается от данных объект DataSetll и заполняется обновленной информацией из базы данных, путем вызова метода Fill адаптера данных. После этого удаленная запись исчезает из элемента отображения информации DataGrid.
Программный код обработки события нажатия кнопки Обновить приведен в листинге
Листинг
' Visual Basic
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System. EventArgs) Handles Button3.Click
'Обновление записей
SqlDataAdapterl.Update(DataSetll)
End Sub
//C#
Private void button3_Click(object sender, System.EventArgs e)
{
SqlDataAdapterl.Update(dataSetll);
}
В этом фрагменте вызывается метод Update адаптера данных SqlDataAdapterl. При этом все обновления, сделанные пользователем передаются в исходную таблицу базы данных.
Итак, мы познакомились с основными приемами получения и обновления данных в традиционных Windows-приложениях, когда пользователи работают в рамках локальной сети. Однако на сегодняшний день большинство компаний нуждаются в распределенных приложениях, когда не только филиалы компании, но и клиентура нуждается в доступе к единым информационным массивам через сеть Интернет. Для этих целей необходимо задействовать несколько иную технологию — Web-программирование и, в частности, активные серверные страницы (Active Server Pages, ASP). B Visual Studio .NET разработка Web-приложений выполняется в той же среде, что и Windows-приложений.
2. Построение asp-приложений ис с достутом данных через ado.Net
2.1.Создание web-проекта и формы .Работа с данными в web-формах
ASP.NET — это серверная технология, которая помогает соединять в одно целое различные части Web и таким образом дает создателям Web-узлов больше возможностей, чем когда-либо прежде. Но прежде чем слишком сильно углубляться в ASP.NET, давайте посмотрим, как же выполняется динамическая обработка.
Динамическая обработка
Internet работает в соответствии с клиент/серверной моделью. При выполнении задания два компьютера работают вместе, пересылая друг другу информацию. Самым распространенным сценарием такой работы является соединение между сервером (компьютером, который хранит информацию) и клиентом (компьютером, которому требуется информация).
Клиентский компьютер отправляет серверной машине запрос на получение информации. Затем сервер в ответ передает клиенту информацию, которую тот запрашивал. Такая парадигма называется моделью "запрос/ответ " и представляет собой составную часть клиент/серверной модели.
Web-сервер — это компьютер, на котором находится информация Web-узла: его HTML-страницы, изображения и так далее. А клиент — это посетитель Web-узла (а если точно, то клиентом является Web-броузер посетителя). Этот принцип продемонстрирован на рис. 49.
Рис 49. Модель «запрос/ответ»
Это великолепный способ общения и передачи информации, хотя чересчур простой и статичный. Передача динамической информации, а также выполнение обработки здесь невозможны. При использовании модели "запрос/ответ" сервер просто ждет, пока кто-либо не отправит ему запрос на какую-либо информацию. Затем в ответ на запрос сервер передает данные, уже хранящиеся на его жестком диске, при этом фактически даже не взглянув на то, что же он передает. Запрос к статичному Web-узлу обычно состоит из таких четырех действий.
Клиент (Web-броузер) показывает местонахождение Web-сервера с помощью его URL (например www.microsoft.com).
Затем клиент делает запрос на страницу (например index.html).
Сервер проверяет файл, на который получен запрос, и обрабатывает любой содержащийся в этом файле код.
Затем сервер преобразует в HTML результаты обработки (если только это нужно) и отправляет клиенту документ, на который поступил запрос.
Клиент принимает документ и отображает его.
Даже при таком многоступенчатом сценарии процесс все равно будет завершен, как только клиент получит страницу. А сервер не будет иметь никакого представления, что же делает клиент, если, конечно, тот не сделает другой запрос.
2.2. Прямой доступ к базе данных (с помощью хранимых процедур, с данными доступными для чтения)
В ADO.NET есть два основных способа, обеспечивающих взаимодействие приложения с данными: использование набора данных (DataSet), работа непосредственно с элементами базы данных (с таблицами, представлениями, хранимыми процедурами и т. п.). В "отсоединенной" модели работы с данными на основе DataSet вы создаете в памяти компьютера некое пустое хранилище, загружаете его данными, используя адаптер данных, работаете с этой информацией (сортируете, фильтруете, изменяете), и затем, по мере необходимости, через тот же адаптер данных, возвращаете все изменения назад в исходную базу данных.
В качестве альтернативы можно работать непосредственно с базой данных. В этой модели используется объект DataCommand, в котором содержится SQL-запрос или имя хранимой процедуры. Команда запускается на исполнение, и если команда не возвращает результата (например, удаление записей), то все действия команды выполняются непосредственно над объектами базы данных (например, удаляется запись из таблицы). Если в результате работы команды из базы возвращается набор записей, то используется объект DataReader для выборки данных.
В некоторых случаях задача вообще не решается путем использования набора данных. Например, если требуется создать элемент базы данных (типа таблица), то это можно делать только с помощью команд (объектов DataCommand).
Общие сведения об объекте DataCommand
Команда данных содержит ссылку на SQL-запрос или хранимую процедуру, которые собственно и реализуют конкретные действия. Команда данных — экземпляр класса OleDbCommand или класса SqlCommand. Как и многие другие подобные классы, OleDbCommand используется как средство доступа к любым данным на основе OLE DB-провайдера, в то время как класс SqlCommand оптимизирован для работы с SQL Server версии 7.0 и выше.
С использованием объекта DataCommand в приложении можно выполнить следующие действия.
□ Исполнять команды select, которые возвращают набор записей. Причем этот набор можно обрабатывать непосредственно, без его загрузки в набор данных DataSet. Для чтения результатов используются объекты OleDbDataReader или SqlDataReader, которые работают в режиме read-only, forward-only (только чтение, только вперед) и могут быть связаны с компонентом визуального отображения данных. Эти объекты полезно использовать в тех случаях, когда имеет место ограничение на ресурсы памяти или требуется высокая скорость загрузки данных.
□ Выполнять DDL-команды (Database Definition Commands, команды определения базы данных), обеспечивающих создание, редактирование, Удаление таблиц, хранимых процедур и других элементов базы данных.
□ Выполнять команды, обеспечивающие получение информации из каталогов баз данных.
□ Выполнять динамические SQL-команды, позволяющие модифицировать, вставлять или удалять записи непосредственно в базе данных, вместо того, чтобы редактировать таблицы набора данных Dataset, а затем копировать эти изменения в базу данных.
□ Выполнять команды, которые возвращают скалярное значение, то есть единственное число или строку (результат поиска пароля пользователя, расчет суммы счета и т.п.).
□ Выполнять команды, которые возвращают данные из базы данных SQL Server (версия 7.0 и выше) в формате XML. Эта возможность используется в Интернет-приложениях. Например, когда нужно выполнить запрос и получить данные в формате XML, обратиться к XSLT-конвертору, чтобы преобразовать данные к HTML-формату и затем послать их браузеру.
Работа объектов DataCommand
Свойства объектов DataCommand содержат всю информацию, необходимую для выполнения команд.
Connection. Ссылка команды на объект Connection, который обеспечивает установление связи с базой данных.
Имя или текст команды. Команда включает текст SQL-запроса или имя хранимой процедуры.
Parameters. Команда может потребовать, чтобы ей передали значения параметров (входные параметры). Кроме того, команда может иметь и возвращаемые параметры в виде одного или нескольких значений. Каждая команда имеет коллекцию параметров, которые вы можете настроить. индивидуально для передачи или получения значений.
Для выполнения команды данных нужно вызвать тот метод, который соответствует возвращаемым результатам. Например, если вы собираетесь получить набор записей, то нужно использовать метод ExecuteReader, который возвращает записи объекту DataReader. Если требуется выполнить обновление, вставку или удаление записей, то требуется вызывать метод ExecuteNonQuery, который возвращает значение количества обрабатываемых строк.
Множественные результирующие наборы записей
Обычно при исполнении команда данных возвращает единственный результирующий набор. Однако команды данных могут выполнять и процедуры, которые возвращают множественные результирующие наборы. Это может быть реализовано несколькими способами. Например, вызов хранимой процедуры, которая возвращает множественные наборы записей. Или в команде может содержаться два или более SQL-запроса или хранимых процедур. В этом случае SQL-запросы или хранимые процедуры будут выполняться последовательно, что приведет к получению множественных результирующих наборов.
Возвращение множественных наборов позволяет оптимально использовать единственное открытое соединение с базой данных в следующих ситуациях:
при выполнении одной командой нескольких запросов, каждый из которых возвращает отдельный набор записей;
при выполнении инструкции update или insert совместно с инструкцией select. Первые выполняют обновление или добавление записей, последняя возвращает из источника данных обновленный набор записей, включая значения, которые автоматически устанавливаются на уровне базы данных (например, значения полей типа "счетчик").
Если вы определяете множественные инструкции или процедуры для команды, то все они должны иметь один и тот же тип. Например, можно выполнить последовательность SQL-запросов или последовательность хранимых процедур. Однако нельзя смешивать хранимые процедуры с SQL-запросами в одной и той же команде.
Выполнение команд данных
После конфигурирования свойств объекта DataCommand вы можете запустить команду на выполнение. Команды данных поддерживают четыре вида возвращаемых результатов.
□ Итоговый набор. В этом случае выполняется SQL-запрос или хранимая процедура, а возвращается одна или более записей. В этом случае в наборе данных может быть "текущей" только одна запись, доступ к которой можно получить с помощью объекта DataReader.
□ Число обработанных записей. Эта ситуация возникает тогда, когда выполняется SQL-запрос или хранимая процедура, которые модифицируют базу данных или изменяют ее структуру (например, удаляются записи, добавляются таблицы или хранимые процедуры).
□ Простое (скалярное) значение. В этом случае выполняется SQL-запрос или хранимая процедура, которые выполняют поиск, вычисляют агрегирующие функции.
□ Данные в формате XML. Эта возможность поддерживается в SQL Server версией 7.0 и выше.
Использование DataCommand адаптером данных
Если вы уже работали с наборами данных и адаптерами данных, то большая описания работы с командами данных вам будет знакома. Фактически, адаптер данных использует команды данных, чтобы выбирать и возвращать записи базе данных. Адаптеры данных могут содержать четыре объекта команды Данных: SelectCommand, UpdateCommand, InsertCoramand и DeleteCommand.
Когда вы используете адаптер данных, то фактически запускаете на исполнение ту или иную команду данных. Например, когда происходит вызов метода Fill объекта DataAdapter, то фактически выполняется команда SelectCommand и используется объект DataReader для заполнения данными таблицы объекта DataSet. Точно так же, когда вызывается метод Update адаптера данных, то выполняется одна из команд (UpdateCommand, InsertCommnand или DeleteCommand). Адаптер данных также проверяет, что командам передаются соответствующие параметры.
2.3.Управление презентацией данных в web-формах
В ADO.NET с помощью объектов DataCommand имеется возможность работать непосредственно с элементами базы данных или любого другого источника данных (таблицы, представления, хранимые процедуры и т. п.) без использования объектов "посредников" (набор данных, адаптер данных). Для использования DataCommand в Visual Studio необходимо выполнить определенную последовательность шагов, как на этапе разработки приложения, так и в период его работы на компьютере пользователя. Для работы с объектом DataCommand вам необходимо выполнить следующие действия.
1. На этапе разработки приложения добавьте объект DataCommand к вашей форме или компоненту и в его конфигурации установите следующие параметры:
задайте, что будет использоваться в теле команды: SQL-запрос или хранимая процедура;
определите параметры, которые необходимы для работы команды.
Во время выполнения приложения, присвойте значения параметрам, которые необходимо передать объекту DataCommand. Обычно значения параметров присваиваются пользователем приложения через визуальные элементы формы или передаются от других компонент приложения.
Запустите команду на выполнение. При этом фактически будет выполнен SQL-запрос или хранимая процедура, связанная с объектом DataCommand. Имя оператора, который запустит команду данных на выполнение, будет зависеть от типа возвращаемых командой данных: набор данных DataSet, скалярное значение, количество обработанных записей или данные в XML-формате.
4. Считайте возвращенные командой значение (или значения) и используй те их в зависимости от специфики вашего приложения.
Добавление объекта DataCommand к форме или компоненту
Перед выполнением команды данных (DataCommand), необходимо добавит экземпляр класса OleDbCommand или SqlCommand к форме или компоненту и сконфигурировать его. В Visual Studio имеется набор визуальных средств которые помогают разработчику выполнить эту процедуру на этапе разработки приложения.
Добавление объекта DataCommand к форме или компоненте можно выполнить следующим образом.
Добавьте объект Connection на форму (если данный объект уже создан то используйте существующее соединение).
Из вкладки Data окна Toolbox перетащите объект OleDbCommand или SqlCommand на вашу форму или компонент (рис. 3.1).
Примечание
Используйте объект SqlCoommand, если вы хотите выполнить команды в базе данных SQL Server версии 7.0 и выше; для остальных источников данных используйте объект OleDbCommand.
Рис. 50. Объект Sg/Command в окнеToolbox
Таблица 4
Свойства объекта Da taCommanc
Свойство |
Описание |
Name |
Имя, с помощью которого можно обратиться к команде в программном коде |
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, но программный код будет более ясным и понятным, если к параметрам обращаться с помощью имен.
Рис.51. Окно редактора коллекции параметров объекта DataCommand
Прежде, чем выполнять команду, необходимо установить значение для каждого параметра команды.
Для каждого параметра в коллекции Parameters задайте в свойстве Value то значение, которое нужно передать исполняемой команде. Следующий пример показывает, как установить значения параметров перед выполнением команды, которая вызывает хранимую процедуру. В данном примере предполагается, что вы уже сконфигурировали коллекцию Parameters (в коллекции содержится три параметра с менами au_id, аи_lname и au_fname). В данном примере такие свойства как CommandTex и CommandType задаются в программном коде, хотя они могут быть определены в окне Properties объекта DataCommand. Это сделано для большей наглядности и законченности приводимого в листинге программного кода.
Листинг
‘ Visual Basic
With OleDbCommand1
.CommandText="UpdateAuthor"
.CommandType=System.Data.CommandType.StoredProcedure
.Parameters("au_id").Value=listAuthorID.Text
.Parameters("au_lname").Value=txtAuthorLName.Text
.Parameters("au_fname").Value=txtAuthorFName.Text
End With
OleDbConnectionl.Open() OleDbCommandl.ExecuteNonQuery() OleDbConnectionl.Close()
// C#
OleDbCommandl.CommandText="UpdateAuthor";
OleDbCommandl.CommandType=System.Data.CommandType.StoredProcedure;
OleDbCommandl.Parameters["au_id"].-Value=listAuthorID.Text;
OleDbCommandl.Parameters["au_lname"].Value=txtAuthorLName.Text;
OleDbCommandl.Parameters["au_fname"].Value=txtAuthorFName.Text;
OleDbConnectionl.Open();
OleDbCommandl.ExecuteNonQuery();
OleDbConnectionl.Close ();
Получение возвращаемых значений
Хранимые процедуры часто возвращают значения назад к приложению, которое вызвало их на исполнение. Они могут передавать возвращаемые значения через параметр.
Получение значений, возвращенных процедурами через свойство value, происходит в несколько этапов.
Создайте параметр, свойству которого Direction присвойте значение output или inputoutput. Удостоверьтесь, что тип данных этого параметра соответствует типу возвращаемого значения.
После выполнения процедуры, прочитайте свойство value параметра, который возвращает значение.
Получите возвращаемое значение процедуры через свойство ReturnValue.
3. Создайте параметр, свойству Direction которого присвойте значение
ReturnVaiue.
Примечание
Параметр, который возвращает значение, должен быть первым в коллекции Parameters.
4. Удостоверьтесь, что тип данных этого параметра соответствует типу возвращаемого значения.
Примечание
Инструкции Update, insert и Delete в SQL-запросах возвращают целочисленное значение, указывающее количество записей, которые обработаны инструкцией. Вы можете получить число обработанных записей как возвращаемое значение метода ExecuteNonQuery.
Следующий пример (листинг) показывает, как получить значение, возвращаемое хранимой процедурой с именем CountAuthors. В этом случае предполагается, что первый параметр в коллекции Parameters называется retvalue и его свойство Direction имеет значение ReturnVaiue.
Листинг
' Visual Basic
Dim cntAffectedRecords As Integer
OleDbcommandl.CommandText="CountAuthors"
OleDbCommandl.CommandType=CommandType.StoredProcedure
OleDbConnectionl.Open()
OleDbCommandl.ExecuteNonQuery()
OleDbConnectionl.Close()
cntAffectedRecords=CType(OleDbCommandl.Parameters("retvalue").Value,Integer)
MessageBox.Show("Affected records=" & cntAffectedRecords.ToString)
// C#
int cntAffectedRecords;
oleDbcommandl.CommandText="CountAuthors";
OleDbCommandl.CommandType=CommandType.StoredProcedure;
OleDbConnectionl.Open();
OleDbCommandl.ExecuteNonQuery();
OleDbConnectionl.Close() ;
cntAffectedRecords=(int)(OleDbCommandl.Parameters["retvalue"].Value);
MessageBox.Show("Affected records=" + cntAffectedRecords.ToString());
Выполнение команд, которые возвращают наборы данных
Вы можете использовать объект DataCommand, чтобы выполнить процедуру выборки информации непосредственно из базы данных, которая будет доступна только для чтения. В этом случае выполняется SQL-запрос или хранимая процедура, которая содержит инструкцию select. Это аналогично тому, как заполняется набор данных через адаптер данных, за исключением того, что результирующий набор записей попадает в приложение, минуя "посредников".
Возвращенный набор записей помещается в объект DataReader (OleDbDataReader или SqlDataReader). В цикле, путем перебора, можно получить доступ к любой индивидуальной записи полученного набора. Поскольку DataReader обеспечивает доступ к данным в режиме forward-only, read-only, то это достаточно быстрый и эффективный способ получения набора записей из базы данных.
Выполнение команд, которые возвращают набор записей, происходит следующим образом.
Добавьте объект DataCommand к вашей форме или компоненте.
Определите в свойстве объекта CommandText текст SQL-запроса или имя хранимой процедуры, которые возвращают набор записей.
3. Установите в свойстве CommandType значение CommandType.Text (для SQL-запроса) или CommandType.StoredProcedure (для хранимой процедуры).
Если команда имеет параметры, то определите их.
Создайте объект DataReader как экземпляр класса OleDbDataReader или SqlDataReader, в зависимости от типа используемого соединения.
Откройте соединение, связанное с командой данных.
Вызовите метод ExecuteReader, адресуйте результаты работы команды объекту DataReader, созданному на шаге 5.
В цикле просмотрите полученные данные, используя метод Read.
Закройте объект DataReader.
Если больше не предполагается использовать метод ExecuteReader, то закройте соединение.
Следующий пример (листинг) показывает, как получить записи из таблицы Authors базы данных Pubs (SQL Server). Пример использует тип команды TableDirect и определяет имя таблицы Authors как текст команды. После выполнения команды (вызов метода ExecuteReader) организован цикл чтения записей в переменную s (создается строка с информацией об авторах, использующая в качестве разделителей пробел, символ табуляции и перевод строки), которая затем отображается в текстовом поле.
Листинг
' Visual Basic
Dim dreader As System.Data.OleDb.OleDbDataReader
OleDbCommandl.CommandText="authors"
OleDbCommandl.CommandType=CommandType.TabieDirect
OleDbConnectionl.Open()
dreader=0leDbCommandl.ExecuteReader(CommandBehavior.CioseConnection)
Dim s As String=""
While dreader.Read()
s &= dreader("au_id").ToString() _
& vbTab & dreader("au_fname").ToString()_
& " " & dreader("au_lname").ToString & ControlChars.CrLf
End While
TextBoxl.Text=s
dreader.Close()
// C#
System.Data.OleDb.OleDbDataReader dreader;
OleDbCommandl.CommandText="authors";
OleDbCommandl.CommandType=CommandType.TabieDirect;
OleDbConnectionl.Open();
dreader=01eDbCommand1.ExecuteReader(CommandBehavior.CioseConnection);
string s="";
while (dreader.Read())
{
s += dreader["au_id"].ToStringO + "\t"
+ dreader["au_fname"].ToStringO + " "
+ dreader["au_lname"].ToStringO + "\n";
}
TextBoxl.Text=s;
dreader.Close () ;
Следующий пример (листинг) показывает два способа использования объекта DataReader для получения данных. В первой части примера объект DataReader загружает данные в компонент ListBox на Windows-форме (только один столбец author_id таблицы authors). Во второй части примера рассматривается обработчик события SelectedlndexChanged объекта ListBox. Здесь в предложении SELECT SQL-запроса в качестве ключевого поля (параметра) для выбора единственной записи используется значение au_id. Этот параметр получает значение из списка авторов (объект ListBox1). Поскольку объект DataReader ожидает возвращения только одной записи, то информация из него считывается не в цикле (его метод Read вызывается только один раз). В примере проверяется, что имеется не менее одной записи, путем вызова метод Read в условном операторе If- End if.
Два обработчика событий используют различные команды данных: в первом случае не используются параметры, во втором случае команде передается один параметр для идентификации автора.
Листинг
' 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
OleDbCommandl.CommandText="authors"
OleDbCommandl.CommandType=CommandType.TableDirect
OleDbConnectionl.Open()
dreader=01eDbCommandl.ExecuteReader()
While dreader.Read()
ListBox1.Items.Add(dreader("au_id"))
End While
dreader.Close() OleDbConnectionl.Close()
End Sub
Private Sub ListBoxl_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ListBoxl.SelectedlndexChanged
Dim dreader As System.Data.OleDb.OleDbDataReader OleDbCommand2.CommandText = _
"SELECT au_id, au_lname, au_fname FROM authors WHERE au_id=?"
0leDbCommand2.CommandType=CommandType.Text
0leDbCommand2.Parameters("au_id").Value=ListBox1.Text
OleDbConnectionl.Open()
dreader=OleDbCommand2.ExecuteReader()
If dreader.Read() Then
txtAuthorlD.Text=dreader("au_id").ToString() txtAuthorLastName.Text=dreader("au_lname").ToString() txtAuthorFirstName.Text=dreader("au_fname").ToString()
End If
dreader.Close ()
OleDbConnectionl.Close ()
End Sub
// C#
private void btnLoadListBox_Click(object sender, System.EventArgs e)
{
System.Data.OleDb.OleDbDataReader dreader;
OleDbCommandl.CommandText="authors";
OleDbCommandl.CommandType=ComrnandType.TableDirect;
OleDbConnectionl.Open();
dreader=OleDbCommandl.ExecuteReader();
while( dreader.Read())
{
ListBox1.Items.Add(dreader["au_id"]);
}
dreader.Close(); OleDbConnectionl.Close();
Button6.Enabled=true;
}
private void ListBoxl_SelectedIndexChanged(object sender, System.EventArgs e)
{
System.Data.OleDto.OleDbDataReader dreader;
OleDbCommand2.CommandText =
"SELECT au_id, au_lname, au_fname FROM authors WHERE au_id=?";
OleDbCommand2.CommandType=ComnandType.Text;
OleDbCommand2.Parameters["au_id"].Value=ListBox1.Text;
OleDbConnectionl.Open();
dreader=OleDbCommand2.ExecuteReader() ;
if (dreader.Read())
{
txtAuthorlD.Text=dreader["au_id"].ToString(); txtAuthorLastName.Text=dreader["au_lname"].ToString(); txtAuthorFirstName.Text=dreader["au_fname"].ToString();
}
dreader.Close () ;
OleDbConnectionl.Close() ;
Выполнение обновления или модификации базы данных с использованием DataCommand
Некоторые типы команд данных (OleDbCommand или SqlCorranand) при выполнении каких-либо действий над элементами базы данных не возвращают никаких данных кроме признака, что команда выполнена успешно. К ним относятся:
команды модификации структуры базы данных, которые используются для создания таблиц, хранимых процедур и других элементов с использованием языка описания структур базы данных (DDL);
команды обновления данных (Update, Insert и Delete).
Если в приложении используется набор данных Dataset, то нет необходимости выполнять обновление базы данных через объект DataCommand, поскольку эти функции может выполнить адаптер данных. Оба типа приведенных выше команд возвращают целое число, указывающее успешность выполнения соответствующей операции. Возвращаемое значе ние различно — в зависимости от того, модифицируете ли вы записи таблицы, или модифицируете структуру базы данных с помощью DDL-команд:
если вы создаете новые элементы базы данных или изменяете ее структуру, то возвращаемое значение равно -1, если операция завершилась успешно;
если вы модифицируете записи, возвращаемое значение указывает количество записей, которые были обработаны соответствующей операцией.
В обоих случаях, если в процессе выполнения операции произошел сбой, то команда возвращает значение 0.
Чтобы выполнить команду модификации базы данных, нужно проделать ряд шагов.
Добавьте команду данных к вашей форме или компоненту и сконфигурируйте выполняемые ею действия (сформируйте SQL-запрос или сошлитесь на хранимую процедуру).
Если команда имеет параметры, то определите их.
Если в команде есть параметры, то добавьте программный код для установки их значений.
Добавьте программный код, чтобы открыть соединение, связанное с командой данных.
Вызовите метод команды ExecuteNonQuery, присвоив результат работы команды целочисленной переменной.
Примечание
Данный метод возвращает одно целочисленное значение. Однако хранимая процедура может возвращать набор значений, для которых нужно определить коллекцию параметров Parameters.
Закройте соединение.
В следующем примере (листинг) показано, как создать новую таблицу в базе данных. Пример предполагает, что вы уже добавили к форме команду данных, соединение и сконфигурировали их. Действия, выполняемые командой, записываются в ее свойство CommandText. В данном случае используется SQL-инструкция createtable, которая создает таблицу из двух столбцов, один из которых является первичным ключом. После выполнения команда вернет значение -1, если таблица была успешно создана.
Листинг
' 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 OleDbCormandl.CommandText=newtablecmd OleDbConnectionl.Open()
cmdresults=OleDbConimandl.ExecuteNonQuery() OleDbConnectionl.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, после чего соединение закрывается.
Листинг
' Visual Basic
Dim cmdresults As Integer
0leDbcommand2.CommandText="NewAuthor"
OleDbCommand2.CommandType=CommandType.StoredProcedure
0leDbCommand2.Parameters("au_id").Value=TextBox1.Text 0leDbCommand2.Parameters("au_lname").Value=TextBox2.Text 01eDbCommand2.Parameters("au_fname").Value=TextBox3.Text 0leDbCoramand2.Parameters("phone").Value=TextBox4.Text 01eDbCommand2.Parameters("address").Value=TextBox5.Text 0leDbCommand2 . Parameters ("city") . Value=TextBox6. Text 01eDbCommand2.Parameters("st").Value=TextBox7.Text 0leDbCommand2.Parameters("zip").Value=TextBox8.Text 01eDbCommand2.Parameters("contract").Value=CheckBoxl.Checked
01eDbConnection2.Open()
Try
cmdresults=O1eDbcommand2.ExecuteNonQuery()
Catch ex as Exception
MessageBox.Show("Failed to execute command, err=" & ex.Message)
End Try
01eDbConnection2.Close() MessageBox.Show("Number of records inserted=" & cmdresults.ToString)
// C#
int cmdresults=O;
01eDbCommand2.CommandText="NewAuthor";
01eDbCommand2.CommandType=CommandType.StoredProcedure;
01eDbCommand2.Parameters["au_id"].Value=TextBox1.Text; 01eDbCommand2.Parameters["au_lname"].Value=TextBox2.Text; 01eDbCommand2.Parameters["au__fname"].Value=TextBox3.Text; 01eDbCommand2.Parameters["phone"].Value=TextBox4.Text; 01eDbCommand2.Parameters["address"].Value=TextBox5.Text; 01eDbCommand2.Parameters["city"].Value=TextBox6.Text; 01eDbCommand2.Parameters["st"].Value=TextBox7.Text; 01eDbCommand2.Parameters["zip"].Value=TextBox8.Text; 01eDbCommand2.Parameters["contract"].Value=CheckBoxl.Checked;
01eDbConnection2.Open();
try
{
cmdresults=OleDbCommand2.ExecuteNonQuery();
{
catch (Exception ex) MessageBox.Show("Failed to execute command, err=" + ex.Message);
}
}
OleDbConnection2.Close() ;
MessageBox.Show("Number of records inserted=" + cmdresults.ToString());
Задание команды Data Command, возвращающей одно значение
Достаточно часто в приложениях требуется выполнение команд, которые возвращают единственное (скалярное) значение. Типичные примеры: SQL-запрос возвращает результат работы агрегирующей функции (sum, count и тому подобное), хранимая процедура, получающая пароль и возвращающая разрешение на доступ к базе данных, или процедура, которая получает код изделия, а возвращает его наименование и т. д.
Чтобы задать команду, которая возвращает скалярное значение, нужно выполнить несколько этапов.
Добавьте объект DataCommand к форме или компоненту.
В свойстве CommandText объекта DataCommand определите SQL-запрос или имя хранимой процедуры.
Свойству CommandType задайте значение CommandType.Text (для SQL- запроса) или CommandType. StoredProcedure (для хранимой процедуры).
Если команда имеет параметры, то определите их.
Откройте соединение с источником данных, которое ассоциировано с данной командой.
Вызовите метод команды ExecuteScaiar, присвоив результат его работы переменной соответствующего типа.
Закройте соединение с источником данных.
Следующий пример (листинг) показывает, как использовать команду данных, чтобы выполнить инструкцию SQL, которая возвращает скалярное значение. В SQL-запросе данной команды делается обращение к таблице Products (Изделия). В качестве критерия (параметра) поиска нужного изделия используется его идентификационный номер. Возвращается целочисленное значение, указывающее количество заготовок для заданного изделия (UnitsInStock).
Листинг
' Visual Basic
Dim scalarcmd As String
Dim qtyinstock As Integer
scalarcmd="SELECT UnitsInStock FROM Products WHERE (ProductID=?)"
OleDbCortmand3.CommandType=CommandType.Text
OleDbCommand3.CommandText=scalarcmd
OleDbCommand3.Parameters("productid").Value=txtProductID.Text
OleDbConnectionl.Open()
qtyinstock=CType(01eDbCommand3.ExecuteScaiar() , Integer)
OleDbConnectionl.Close()
MessageBox.Show("QtyinStock=" & qtyinstock.ToString)
// C#
string scalarcmd;
int qtyinstock;
scalarcmd="SELECT UnitsInStock FROM Products WHERE (ProductID=?)";
OleDbCommand3.CommandType=CommandType.Text;
OleDbCommand3.CommandText=scalarcmd;
OleDbCommand3.Parameters["productid"].Value=txtProductID.Text;
OleDbConnectionl.Open();
qtyinstock=(int)(01eDbCommand3.ExecuteScaiar());
OleDbConnectionl.Close();
MessageBox.Show("QtyinStock=" + qtyinstock.ToString ());
3. Доступ к бд через web-сервисы
3.1.Структура и назначение Web-сервисов
В ADO.NET используется отсоединенная модель доступа к данным. В этой модели открывается соединение с базой данных, делается выборка записей или выполняются другие операции с таблицами базы данных, после чего соединение сразу закрывается. В ADO.NET возможны две стратегии работы в рамках этой модели.
Первая стратегия предусматривает размещение данных в объекте DataSet. При этом данные размещаются в оперативной памяти компьютера в виде кэш-записей, с которыми можно работать в отрыве от источника данных. Чтобы использовать объект DataSet, создается экземпляр этого класса, который заполняется записями из источника данных через объект DataAdapter. Пользователь работает с записями через объект отображения информации (например, DataGrid), который связывается с набором данных DataSet.
Вторая стратегия заключается в том, чтобы выполнять операции непосредственно в базе данных, не передавая записи на компьютер клиента. В этой стратегии выполняются команды данных (объект DataCommand), содержащие SQL-запросы или ссылку на хранимые процедуры. При этом происходит соединение с базой данных, запуск команды, выполняющей те или иные действия с записями базы данных, и затем закрытие соединения. Если команда возвращает набор записей (содержит инструкцию select), то можно с помощью объекта DataReader получить эти записи и представить их пользователю через связанную с объектом DataReader компоненту визуального отображения данных. Это самый эффективный способ выборки информации, правда, она доступна только для чтения.
Каждая стратегия имеет определенные преимущества. Какую из них выбрать — зависит от характера задачи, решаемой конкретным приложением, и этот вопрос более детально рассматривается в следующих разделах.
3.2.Создание Web-сервисов
Обычно в Visual Studio .NET используется объект DataSet для доступа к данным. Этот подход имеет ряд преимуществ.
Работа с несколькими таблицами. Набор данных может содержать несколько таблиц. Можно работать как с каждой таблицей индивидуально, так и устанавливать между ними реляционные отношения.
Работа с данными из разных источников. Таблицы в наборе данных могут содержать данные из различных источников (например, из различных баз данных, XML-файлов, электронных таблиц и т. д.). Как только данные попадут в объект DataSet, с ними можно манипулировать, устанавливать связи между таблицами, сортировать, фильтровать и выполнять все те же действия, которые допускаются для данных, поступивших из одного источника.
Перемещение данных между элементами приложения. Данные из объекта DataSet могут легко передаваться другим элементами приложения — объектам отображения информации, на уровень бизнес-логики, в исходную базу данных.
Перемещение данных между приложениями. Объект DataSet позволяет реализовать простой и эффективный обмен данными между различными приложениями. Наборы данных включают поддержку преобразования содержимого таблиц в XML-формат, чтение данных из XML-формата, работу с XML схемами.
Связывание данных. Если вы работаете с формами, то связывание объектов DataSet с объектами визуального отображения информации выполняется гораздо проще, чем связывание набора записей, полученного после работы DataCommand.
Поддержка повторного использования данных. Набор данных позволяет вам многократно манипулировать полученными записями, без повторных обращений к исходному источнику данных (сортировка, фильтрация по различным признакам и критериям).
Простота программирования. Работая с DataSet, можно представить его структуру как набор объектов класса (например, к таблице customers в наборе данных можно обратиться как к объекту dataset. Customers). Это более легкий, ясный подход создания приложений, менее подверженный программным ошибкам. Кроме того, в Visual Studio реализовано достаточно много визуальных средств программирования с поддержкой IntelliSense и мастеров по конфигурации объектов работы с данными.
3.3.Доступ к Web-сервису из клиентского приложения
В качестве альтернативы можно напрямую взаимодействовать с базой данных (без использования объекта DataSet). В этой модели, используется объект DataCommand, который содержит SQL-запрос или ссылку на хранимую процедуру. При запуске команды на исполнение над таблицами базы данных выполняются определенные действия (выборка данных, добавление, удаление или обновление записей). Если команда возвращает набор записей (в SQL-запросе используется предложение select), то к ним можно получить доступ посредством объекта DataReader (в режиме только чтение).
Такая модель доступа к данным имеет следующие преимущества.
□ Высокая эффективность. Такие команды, как добавление, удаление записей выполняются непосредственно на уровне базы данных и не требуют передачи большого объема информации в приложение. Хранимые процедуры хранятся в базе данных в скомпилированном виде и не требуют ресурсов и времени для их компиляции и проверки синтаксиса.
□ Высокая степень контроля над данными. Используя команды, разработчик имеет прямой доступ к данным (без объектов посредников).
□ Меньшая потребность в оперативной памяти. Работая непосредственно с базой данных, нет необходимости загружать записи в оперативную память компьютера пользователя, соответственно для работы приложения требуется меньше ресурсов. Кроме того, меньше информации передается по каналам связи, что особенно важно для Интернет-приложений.
□ Уменьшение программного кода. При работе с объектом DataSet требуется программировать все процессы синхронизации таблиц набора данных в памяти компьютера с таблицами в базе данных. Например, после добавления записи в DataSet нужно выполнить эту операцию и в основном хранилище информации, кроме того, если в таблице есть поле типа "счетчик", то потребуется повторное считывание таблицы из основной базы данных в DataSet, чтобы передать приложению новое значение счетчика. При прямой работе с таблицами базы данных необходимость в программировании этих процессов отпадает.
Особенно эффективно использование модели прямого доступа к базе данных в Web-приложениях, когда требуется минимизировать объем информации, передаваемой по каналам связи.
3.4.Реализация бизнес-логики распределенных приложений на основе Web -сервисов
При создании Web-приложений для доступа к данным рекомендуется использовать объекты DataCommand и DataReader. Поскольку страница Web-формы и содержащиеся на ней компоненты обновляются при каждом обращении пользователя к серверу, то использовать объект DataSet не эффективно, особенно если не предусмотрено его кэширование. Однако использование набора данных целесообразно при следующих обстоятельствах:
необходима одновременная работа с несколькими таблицами, или работа с таблицами, получаемыми от различных источников данных;
требуется обмен данными с другим приложением или компонентом типа XML Web-сервис;
требуется длительная работа с записями, которые были получены от базы данных. Если в этом случае использовать DataCommand и DataReader, то это потребует длительной поддержки открытого соединения, что может негативно сказаться на эффективности работы приложения (особенно, если с ним потенциально могут работать большое количество пользователей);
если в приложении требуется обработка связанных таблиц;
если вы хотите использовать XML-формат для передачи или приема данных из другого приложения;
если во главу угла ставится простота программирования, а не эффективность работы приложения.
3.5.Доспуп к Web-сервисы из Web-приложений
В XML Web-сервисах необходимо использовать ту же модель доступа к данным, что была описана ранее. Здесь так же используются активные серверные страницы в виде Web-форм. Однако довольно часто XML Web-сервисы используются в трехуровневых приложениях для реализации бизнес-логики, что требует интенсивного обмена данными с другими частями приложения (база данных и приложение-клиент) через сеть.
В Web-сервисах рационально использовать DataSet:
если ваш XML Web-сервис посылает и получает данные. Например, посылает DataSet как возвращаемое значение метода и получает DataSet как параметр метода. Это фундаментальная основа XML Web-сервисов (собственно то, для чего они и создавались);
если существует какая-либо причина, описанная в предыдущем разделе для Web-форм.
Использование DataCommand и DataReader оправдано при следующих обстоятельствах:
если XML Web-сервис возвращает скалярную величину;
если XML Web-сервис выполняет не операцию запроса, а команду языка описания данных (DDL-команду), например, создает новую таблицу;
если XML Web-сервис вызывает хранимую процедуру, чтобы выполнить набор операций в пределах базы данных.
3.6. Доступ к Web-сервисам из - Windows -приложений
В Windows-формах предпочтительней использование набора данных. С помощью Windows-форм обычно реализуются приложения с достаточно сложной логикой обработки и представления данных. В отличие от Web-форм, Windows-формы не пересоздаются после каждой пользовательской операции над данными.
Здесь использование набора данных предпочтительно при следующих обстоятельствах:
□ если пользователь многократно выполняет различные операции с одним и тем же набором записей (редактирование, удаление, добавление, сортировка, фильтрация и т.п.);
□ если используются элементы визуального отображения данных Windows-форм, связанные с набором данных;
□ по любой из других причин, перечисленных выше в разделе "Web- формы".
Использование DataCommand И DataReader МОЖеТ быть разумным в следующих случаях:
если из базы данных возвращается скалярное значение;
если выполняется не операция запроса, а команда языка описания данных (DDL-команда), например, создание новой таблицы;
если возвращаемый набор данных требуется только отобразить в форме (в режиме только для чтения). Например, сформировать и представить пользователю отчет о работе некоторых подразделений фирмы за заданный период.
4.Отладка программного изделия
4.1.Кодирование программного изделия
После разработки внешних спецификаций модулей приступают к проектированию модуля и собственно программированию (кодированию) внутренней логики каждого модуля. Этот процесс должен быть тщательно спланирован и состоять из следующих шагов.
Выбор языка программирования. Выбор языка программирования часто предопределен имеющимися у заказчика вычислительными ресурсами, принятыми организационными стандартами или подготовкой программистов. Выбор языка программирования обычно осуществляется на более ранних стадиях разработки ПИ; однако если язык не определен, то программист выполняет выбор на этом шаге. Существенное влияние на выбор языка оказывают его возможности обеспечивать надежный процесс получения программ, наличие и специфические особенности компилятора и т.д. Выбранный язык программирования оказывает влияние и на разработку ПИ.
Проектирование внешних спецификаций модуля. Это процесс определения внешних характеристик каждого модуля, о котором шла речь в предыдущем разделе.
Проверка правильности внешних спецификаций модуля. Правильность спецификаций каждого модуля должна быть проверена сравнением их с информацией о взаимосвязях, полученной при проектировании структуры программы и в результате последующего обсуждения всеми программистами, разрабатывающими вызывающие модули.
Выбор алгоритма и структуры данных. К настоящему времени разработано значительное количество алгоритмов и соответствующих структур данных, которые позволяют удовлетворить потребности проектировщиков. Поэтому следует использовать опыт предыдущих разработок, отчеты, опубликованные материалы, выбрать из имеющихся эквивалентных алгоритмов и структур данных необходимые. Если же поиск не приводит к желаемому результату, то алгоритм и структуры данных необходимо разработать.
Оформление начала и конца будущего модуля. Предусматривается оформление модуля в соответствии с требованиями принятого языка программирования.
Объявление всех данных, используемых в качестве па- Урометров. Записываются соответствующие операторы объявления.
Объявление оставшихся данных. Записываются операторы объявления всех оставшихся данных, которые должны быть использованы в модуле. Поскольку трудно предсказать все переменные, которые понадобятся, этот шаг часто перекрывается следующим.
Детализация текста программы. В результате нескольких итераций осуществляется последовательная детализация логики модуля, начиная с достаточно высокого уровня абстракции и заканчивая готовым текстом программы. На этом шаге используются методы пошаговой детализации и структурного программирования.
Пошаговая детализация представляет собой процесс разложения функции модуля на подфункции. В конечном итоге подфункции превращаются в шаги требуемой программы. Пошаговая детализация применяется для декомпозиции функции каждого модуля в соответствии с внутренней логикой, необходимой для выполнения модулем этой функции.
В процессе пошаговой детализации используется псевдокод, состоящий из операторов языка программирования и текста предложений на естественном языке. При использовании псевдокода для пошаговой детализации на каждом новом проходе логика работы модуля описывается все точнее. Первоначальная версия может быть очень общей и близкой к исходным спецификациям, а более поздние версии могут оказаться намного ближе к реальной программе. Когда каждое предложение псевдокода непосредственно переводится в одно или два предложения языка программирования, можно считать, что процесс пошаговой детализации завершен.
Структурное программирование - это метод, предполагающий создание улучшенных программ. Он служит для организации проектирования и кодирования программ таким образом, чтобы предотвратить большинство логических ошибок и обнаружить те, которые допущены.
Отладка программы
В процесс отладки помимо тестирования входит: определение природы и места ошибки; устранение ошибки. Это чуть ли не единственный этап создания ПО, к которому большинство программистов испытывает неприязнь. Это можно объяснить следующим:
психологическая сложность;
из всех видов деятельности при разработке ПО отладка требует наибольших интеллектуальных затрат;
природа большинства языков программирования такова, что ошибка может быть в любом модуле;
процесс отладки настолько неприятен, что в литературе практически не отражен и не исследован.
Наиболее общими при отладке ПО являются малоэффективные методы "грубой силы". Методы "грубой силы " можно разделить на 3 группы:
1-я группа основана на распечатке памяти. Недостатки этого метода очевидны:
трудно установить соответствие между распечаткой памяти и переменной. Память предоставляет большой объем ненужной информации.
распечатка памяти - это статичный документ. А большинство ошибок надо ловить в динамике.
распечатка памяти и ошибки не совпадают по времени - локализация сложна.
2-я группа - отладка с расстановкой распечатки операторов по всей программе.
Лучше, чем первая, поскольку отображает динамику программы и легче идентифицировать переменные, но расстановка операторов печати заставляет программиста работать методом проб и ошибок. Распечаток данных может оказаться много. Этот метод требует изменения программы. Это плохо по следующим причинам:
введение операторов нарушает критические времена, что может скрыть ошибку;
можно внести новую ошибку Можно использовать не для всех программ.
3-я группа - отладка с использованием автоматических средств.
Подобна 2-ой группе, но отличается тем, что не вносятся изменения в программу.
Общая функция средств отладки - это вставка точек прерывания, вызывающих приостонов выполнения программы после выполнения определенного оператора или после получения определенного результата значения переменной. Недостаток - метод проб и ошибок.
Общий недостаток - все они игнорируют процесс обдумывания. Можно провести аналогии между нахождением ошибок и преступников.
Эксперименты показали, что средства отладки мало помогают процессу отладки, причем это касается и опытных, и малоопытных программистов. Программисты, обдумывающие тесты, быстрее находят ошибки, чем те, которые предпочитает многократно прогонять тесты. Т.е. применение грубой силы необходимо в том случае, когда другие методы не дают результатов. Рассмотрим методы, основанные на обдумывании
4.2.Метод индукции.
Считается, что большинство ошибок может быть выявлено при тщательном анализе, т.е. без выхода на машину. В процессе индукции осуществляется анализ от частного к целому, при этом, просматривая детали (симптомы ошибок, выявленные тестом) и взаимосвязи между ними, можно прийти к ошибке. Метод индукции разбивается на следующие этапы:
Определение данных, имеющих отношение к ошибке. Одна из самых распространенных ошибок при отладке - плохо организованные данные. Здесь необходимо разделить все данные на свидетельствующие о правильном выполнении и о неправильных действии программы
Организация данных. Индукция -это анализ от частного к общему. Необходимо структурировать данные, имеющие отношение к ошибке с целью выявления закономерностей. Особую важность представляют исследования на противоречивость. Структурирование данных удобно проводить и использованием следующей таблицы:
Вопрос |
Да |
Нет |
Что |
|
|
Где |
|
|
Когда |
|
|
Какова степень |
|
|
Строка "Что" образует общий список симптомов ошибок. "Где" -место, где эти симптомы обнаружены. "Когда" -время появления симптомов. "Какова степень" - определяет область распространения симптомов и степень их важности. Столбец "Да" описывает противоречивость ситуации, когда появляется ошибка, а когда - нет.
Необходимо изучить взаимосвязи и выдвинуть одну или несколько гипотез о причинах ошибки с учетом обнаруженных закономерностей. Если гипотезу не удастся выдвинуть, необходимы дополнительные данные, которые можно получить с помощью дополнительных тестов. Если гипотез несколько, то дальше рассматривается наиболее вероятная.
Доказательство гипотезы. Прежде чем взять гипотезу за основу, необходимо доказать ее приемлемость. Гипотеза должна полностью объяснить существование симптомов. Если доказать не удается, то либо гипотеза необоснованна, либо не полна, либо ошибок несколько. Если гипотеза доказана, то необходимо идти в то место и исправить ошибку.
4.3.Метод дедукции.
Этот метод позволяет на основании некоторых общих теорий и предположений с помощью операций исключения и уточнения прийти к определенному заключению, т.е. найти место ошибки. Процесс дедукции состоит в следующем:
Перечисление возможных причин или гипотез. Заключается в составлении списка всех возможных причин ошибки. Причем эти причины не должны обязательно объяснять ошибки. Это версия, с помощью которой можно структурировать и анализировать данные.
Для исключения возможных причин используется тщательный анализ данных. Особенно тщательно ищется противоречие. Если все причины исключаются, то необходимо выдвинуть новые версии. Если остается одна Гипотеза, то она наиболее вероятна.
Гипотеза может быть верна, но она не объясняет ошибки. Необходимы дополнительные данные, чтобы объяснить версию.
Доказательства: то же, что и в методе индукции.
5.Тестирование программного изделия
5.1.Определение и принципы тестирования
Тестирование является одним из этапов жизненного цикла ПИ, направленным на повышение качественных характеристик. При создании типичного ПИ около 40% общего времени и более 40% общей стоимости расходуется на проверку (тестирование) разрабатываемой программы.
Программы как объекты тестирования имеют ряд особенностей, которые отличают процесс их тестирования от общепринятого, применяемого при разработке аппаратуры и других технических изделий. Особенностями тестирования ПИ являются:
отсутствие эталона (программы), которому должна соответствовать тестируемая программа;
высокая сложность программ и принципиальная невозможность исчерпывающего тестирования;
практическая невозможность создания единой методики тестирования (формализации процесса тестирования) в силу большого разнообразия ПИ по их сложности, функциональному назначению, области использования и т.д.
Применительно к ПИ тестирование - это процесс многократного выполнения программы с целью обнаружения ошибок.
Общепринятое мнение, что тестирование - это процесс, демонстрирующий отсутствие ошибок в программе или доказывающий корректность выполняемых программой функций - является не просто ошибочным, но и крайне вредным, так как это нечто противоположное тому, что следует понимать под тестированием.
Программа тестируется для того, чтобы повысить уровень ее надежности, т.е. выявить максимальное число ошибок.
Цель тестирования - выявление как можно большего числа ошибок. При организации любого процесса очень важен правильный выбор цели, потому что для человеческого сознания характерна целевая направленность. Если поставить целью демонстрацию отсутствия ошибок, то мы подсознательно будем стремиться к этой цели, выбирая тестовые данные, на которых вероятность появления ошибки мала. И наоборот, задавшись целью обнаружить максимальное число ошибок, мы будем стремиться к достижению поставленной цели и проводить тестирование на тестовых наборах с большей вероятностью обнаружения ошибок.
Из правильного определения тестирования вытекает ряд принципов, которые интуитивно ясны, но именно поэтому на них не обращают должного внимания.
Принцип 1. Процесс тестирования более эффективен, если проводится не автором программы.
Из определения тестирования как процесса, направленного на выявление ошибок, ясно, что тестирование тем эффективней, чем больше ошибок выявлено. Тестовый прогон, в результате которого не выявлено ошибок, считается неудачным (неэффективным). Таким образом, тестирование - это процесс деструктивный (разрушительный). Именно этим и объясняется, почему многие считают его трудным. Особенно трудным и малоэффективным он является для самого автора программы, так как после выполнения конструктивной части при проектировании и написании программы ему трудно перестроиться на деструктивный образ мышления и, создав программу, тут же приступить к пристрастному выявлению в ней ошибок. Очевидно, что обнаружение недостатков в своей деятельности противоречит человеческой психологии.
Это не означает, что программист не может тестировать свою программу. Речь идет о повышении эффективности тестирования.
Все эти рассуждения не относятся к отладке, т.е. к исправлению уже известных ошибок. Она эффективнее выполняется самим автором программы.
Принцип 2. Описание предполагаемых значений результатов тестовых прогонов должно быть необходимой частью тестового набора данных.
Тестирование как процесс многократного выполнения программы проводится на многочисленных входных наборах данных (принципы выбора входных данных будут рассмотрены ниже). Чтобы определить правильность полученных в результате очередного тестового прогона данных, необходимо знать ожидаемый результат, иначе правдоподобные результаты тестового прогона могут быть признаны правильными.
Таким образом, тестовый набор данных должен включать два компонента: описание входных данных и описание точного и корректного результата, соответствующего набору входных данных.
Этот принцип довольно сложно, а в некоторых случаях даже невозможно реализовать на практике. Сложность его заключается в том, что при тестировании программы (модуля) необходимо для каждого входного набора данных рассчитать вручную ожидаемый результат или найти допустимый интервал изменения выходных данных. Процесс этот очень трудоемкий даже для небольших программ, так как он требует ручных расчетов, следуя логике алгоритма программы.
Из рассмотренного принципа, который трудно реализуем, но которого следует придерживаться логически, вытекает следующий.
Принцип 3. Необходимо досконально изучать результаты применения каждого теста.
Из практики видно, что значительная часть всех обнаруженных в конечном итоге ошибок, могла быть выявлена в результате самых первых тестовых прогонов, но они были пропущены вследствие недостаточно тщательного анализа результатов первых тестовых прогонов.
Принцип 4. Тесты для неправильных и непредусмотренных входных данных должны разрабатываться также тщательно, как для правильных, предусмотренных.
Согласно этому принципу при обработке данных, выходящих за область допустимых значений, в тестируемой программе должна быть предусмотрена диагностика в виде сообщений. Если сообщение о причине невозможности обработки по предложенному алгоритму отсутствует и программа завершается аварийно или ведет себя непредсказуемо, то такая программа не может считаться работоспособной и требует существенной доработки.
Тестовые наборы данных из области недопустимых входных значений обладают большей обнаруживающей способностью, чем тесты, соответствующие корректным входным данным.
Принцип 5. Необходимо проверять не только, делает ли программа то, для чего она предназначена, но и не делает ли она то, что не должна делать.
Это утверждение логически вытекает из предыдущего. Необходимо любую программу проверить на нежелательные побочные эффекты. Например, если программа обработки и печати какой-нибудь ведомости дублирует первую или последнюю строку, то она содержит ошибку.
Принцип 6. Вероятность наличия необнаруженных ошибок в части программы пропорциональна числу ошибок, уже обнаруженных в этой части.
Это свойство ошибок группироваться объясняется тем, что части программы, где при тестировании обнаружено большее число ошибок, либо были слабо проработаны идеологически, либо разрабатывались программистами более низкой квалификации. Например, в одной из версий ОС/370 47% ошибок, обнаруженных пользователями в процессе первых лет эксплуатации (после полного ее тестирования), приходились на 4% модулей.
Из этого принципа можно сделать практический вывод: если в какой-нибудь части программы обнаружено больше ошибок, чем в других, то ее необходимо тестировать более тщательно.
Итак, нужно помнить и знать, что:
тестирование - это процесс многократного выполнения программы с целью выявления ошибок;
тестовый прогон считается удачным, если он позволяет выявить ошибки, а тот тестовый набор эффективен, который имеет высокую вероятность обнаружения большего числа ошибок;
трудность тестирования в том, что это процесс творческий, плохо поддающийся формализации.
5.2. Методы тестирования программ
Тестирование программ является одной из составных частей более общего понятия - "отладка программ". Если тестирование - это процесс, направленный на выявление ошибок, то целью отладки являются локализация и исправление выявленных в процессе тестирования ошибок.
Под отладкой понимается процесс, позволяющий получить программу, функционирующую с требующимися характеристиками в заданной области изменения входных данных.
Процесс отладки включает:
действия, направленные на выявление ошибок (тестирование);
диагностику и локализацию ошибок (определение характера и местонахождения ошибок);
внесение исправлений в программу с целью устранения ошибок.
Из трех перечисленных видов работ самым трудоемким и дорогим является тестирование, затраты на которое для типичных ПИ приближаются к 40% общих затрат на разработку.
Процесс отладки начинается с разработки тестовых наборов данных по определенной методике, придерживаясь ряда правил, которые подробно будут рассмотрены в п.5.3.
Большая трудоемкость тестирования и ограниченные ресурсы приводят к необходимости систематизации процесса и методов тестирования. Рассмотрим подробнее последовательно применяемые методы тестирования: статический, детерминированный, стохастический и в реальном масштабе времени.
Статическое тестирование - наиболее формализованное, базируется на правилах структурного построения программ и обработки данных. Проверка степени выполнения этих правил проводится без изменения объектного кода программы путем формального анализа текста программы на языке программирования. Операторы и операнды текста программы анализируются в символьном виде, поэтому этот метод тестирования иногда называют символическим тестированием.
Наиболее трудоемким и детализированным является детерминированное тестирование, которое требует многократного выполнения программы на ЭВМ с использованием определенных, специальным образом подобранных тестовых наборов данных. При детерминированном тестировании контролируются каждая комбинация исходных данных и соответствующие результаты, а также каждое утверждение в спецификации тестируемой программы.
Детерминированное тестирование в силу трудоемкости возможно применять для отдельных модулей в процессе сборки программы или для небольших и несложных программных комплексов.
При тестировании ПИ невозможно перебрать все комбинации исходных данных и проконтролировать результаты функционирования на каждой из них, поэтому для комплексного тестирования ПИ применяется стохастическое тестирование.
Стохастическое тестирование предполагает использование в качестве исходных данных множества случайных величин с соответствующими распределениями, а для сравнения полученных результатов используются также распределения случайных величин.
Стохастическое тестирование применяется в основном для обнаружения ошибок, а для диагностики и локализации ошибок приходится переходить к детерминированному тестированию с использованием конкретных значений исходных данных из области изменения ранее использовавшихся случайных величин. Стохастическое тестирование наилучшим образом подвергается автоматизации путем использования датчиков случайных значений (генераторов случайных величин).
ПИ, предназначенные для работы в системах реального времени, должны проходить тестирование в реальном масштабе времени. В процессе такого тестирования проверяются результаты обработки исходных данных с учетом времени их поступления, длительности и приоритетности обработки, динамики использования памяти и взаимодействия с другими программами. При обнаружении отклонений результатов выполнения программ от ожидаемых для локализации ошибок приходится фиксировать время и переходить к детерминированному тестированию.
Каждый из рассмотренных методов тестирования не исключает последовательного применения другого метода, скорее наоборот, требование к повышению качества ПИ предполагает необходимость подвергать их различным методам тестирования (и их сочетаниям) в зависимости от сложности и области применения.
Каждый метод тестирования предполагает использование конкретных процедур для реализации. Статическое тестирование реализуется путем применения ручных методов тестирования программ.
Использование ручных методов тестирования достаточно эффективно. Для типичных программ, по данным фирмы IBM, можно находить от 30 до 80% ошибок логического проектирования и кодирования. Эти методы способствуют существенному увеличению производительности и повышению надежности программ, позволяют раньше обнаружить ошибки, а значит, уменьшить стоимость исправления. При ручных методах тестирования вероятность того, что при исправлении ошибок не вносятся новые ошибки, намного выше.
Основные методы ручного тестирования: инспекции исходного текста и сквозные просмотры.
Они имеют много общего:
предполагают некоторую подготовительную работу;
собирается собрание, состоящее из участников проверки, цель которого нахождение ошибок, но не их устранение (т.е. тестирование, а не отладка).
Рассмотрим каждую из предлагаемых процедур.
Инспекции исходного текста - набор правил и приемов обнаружения ошибок при изучении текста программы группой специалистов.
В инспектирующую группу входят обычно 4 человека: председатель (не автор, но знакомый с деталями программы); автор программы; проектировщик и специалист по тестированию.
В функции председателя входят: подготовка материалов для заседания инспектирующей группы; составление графика проведения инспекций; ведение заседания и регистрация всех найденных ошибок.
Общая процедура инспекции заключается в том, что председатель заранее (за несколько дней) раздает листинг программы и проектную спецификацию остальным членам группы для ознакомления. Инспекционное заседание начинается с доклада автора о логике своей программы, о методах и приемах, использованных при ее написании. Далее программа анализируется по списку вопросов для выявления общих ошибок программирования. Предлагаемый список содержит 67 вопросов, сгруппированных в 8 групп.
Председатель должен нести ответственность за результативность дискуссии, а участники должны сосредоточить свое внимание на поиске ошибок, а не на их корректировке. По окончании заседания автору программы передается список найденных ошибок. Если он очень велик и требует больших доработок, то может быть принято решение повторной инспекции. Оптимальная продолжительность заседания 90-120 мин. Скорость просмотра 150 операторов в час.
В качестве положительных моментов при инспекции исходного текста можно отметить, что результаты инспекции позволяют программисту увидеть сделанные им ошибки и способствуют его обучению, а также позволяют оценить стиль программирования.
Сквозные просмотры представляют собой ряд процедур и способов обнаружения ошибок, осуществляемых группой специалистов.
Процедура подготовки и проведения заседания при сквозном просмотре отличается тем, что на подготовительном этапе специалист по тестированию готовит небольшое число тестов, во время заседания каждый тест мысленно выполняется, и состояние программы отслеживается на бумаге или доске. Количество тестов должно быть небольшим, и они должны быть простыми. Фактически оба рассмотренных метода - это развитие всем хорошо знакомой процедуры "проверки за столом", когда программист просматривает свою программу перед началом тестирования. Однако они более эффективны, так как осуществляется один из основных принципов тестирования (тестирование не должен проводить автор программы), и намного дешевле машинного тестирования (не используется дорогостоящее машинное время).
Описанные методы рекомендуется использовать не только для тестирования новых программ, но и для модифицируемых программ, т.е. они эффективны как при разработке ПИ, так и на этапе эксплуатации при проведении работ по сопровождению.
5.3. Методы проектирования тестовых наборов данных
Как отмечалось выше, наиболее эффективным методом тестирования является детерминированное тестирование, при котором известны и контролируются каждая комбинация исходных данных и соответствующие ей результаты исполнения программы.
Детерминированное тестирование, или тестирование на определенных входных значениях, основывается на двух подходах: структурное тестирование (СТ) и функциональное тестирование (ФТ).
Структурное тестирование, или тестирование программ как "белого ящика" (стратегия тестирования, управляемого логикой программы), предполагает детальное изучение текста (логики) программы и построение (подбор) таких входных наборов данных, которые позволили бы при многократном выполнении программы на ЭВМ обеспечить выполнение максимально возможного количества маршрутов, логических ветвлений, циклов и т.д.
Функциональное тестирование, или тестирование программ как "черного ящика" (тестирование по "входу-выходу"), полностью абстрагируется от логики программы, предполагается, что программа - "черный ящик", а тестовые наборы выбираются на основании анализа входных функциональных спецификаций.
Таким образом, при функциональном тестировании исходной информацией для построения тестовых наборов данных являются функциональные спецификации программы.
Для успешного и качественного проведения детерминированного тестирования необходимо разработать эффективные тестовые наборы данных.
Понятие "эффективного" тестового набора данных связано с невозможностью "полного" тестирования программы.
В подтверждение этого высказывания рассмотрим фрагмент простейшего участка программы, который представлен графом передач управления (рис. 52). Каждая вершина графа - это линейный участок программы, заканчивающийся оператором ветвления. Дуги указывают на передачу управления. Граф описывает программу из 10-12 операторов, включая цикл, который выполняется не менее 20 раз.
Рис. 52. Граф передач управления
Если предположить, что выполнение каждой ветви этого участка исключает одновременное выполнение других ветвей, то, учитывая количество циклических повторений, число тестов для проверки этого участка будет равно 6 • 20 = 120.
Поскольку тестируемые программы состоят из множества подобных или более сложных участков, то исчерпывающее тестирование маршрутов не только невыполнимо, но и невозможно.
Целью отбора тестовых наборов данных является попытка уменьшить эту "неполноту". Если ввести ограничения на время, стоимость, машинное время и т.п., то основным вопросом детерминированного тестирования становится вопрос о том, какое подмножество всех возможных тестов имеет наивысшую вероятность обнаружения большинства ошибок.
Подмножество всех возможных тестов, которое обладает этим свойством, т.е. имеет наивысшую вероятность обнаружения большинства ошибок, называется эффективным.
Чтобы разработать эффективный тестовый набор, необходимо знать ряд методов его построения и придерживаться определенных правил и рекомендаций.
В соответствии с методом детерминированного тестирования при структурном тестировании ориентируются на построение тестовых наборов по принципу "белого ящика", а при функциональном тестировании - по принципу "черного ящика".
При построении тестовых наборов данных по принципу "белого ящика" руководствуются следующими критериями: покрытие операторов, покрытие узлов ветвления, покрытие условий, комбинаторное покрытие условий.
Рассмотрим подробнее каждый из перечисленных критериев.
Покрытие операторов. Этот критерий предполагает выбор такого тестового набора данных, который вызывает выполнение каждого оператора в программе хотя бы один раз. Критерий очень слабый, является не только необходимым, но и недостаточным условием тестирования.
Покрытие узлов ветвления (покрытие решений). Этот критерий предполагает разработку такого количества тестов, чтобы в каждом узле ветвления был обеспечен переход по веткам "истина" и "ложь" хотя бы один раз.
Покрытие решений обычно удовлетворяет критерию покрытия операторов, однако нельзя забывать о некоторых исключениях из этого правила. Например, если программа имеет несколько точек входа, то данный оператор выполняется только в том случае, если выполнение программы начинается с соответствующей точки входа. Другое исключение - операторы внутри ON-единиц; выполнение каждого направления перехода необязательно будет вызывать выполнение ON-единиц.
Покрытие условий. Если узел ветвления содержит более одного условия, тогда нужно разработать число тестов, достаточное для того, чтобы возможные результаты каждого условия в решении выполнялись, по крайней мере один раз; каждой точке входа в программу, а также ON-единицам должно быть передано управление при вызове, по крайней мере один раз. Этот критерий обычно называют покрытием условий.
Например: условие А>2&O=Д, тогда нужно предусмотреть тесты:
А > 2; А < 2 А = 3;с = 0;д = 0
с = д; с # д А = 2;с = 0;д=1
Однако рассмотренные критерии недостаточно чувствительны к ошибкам в логических выражениях.
Комбинаторное покрытие условий. Для выполнения таких ошибок используют комбинаторное покрытие условий. Этот критерий требует создания такого числа тестов, чтобы все возможные комбинации результатов условия в каждом решении и все точки входа и ON-единицы выполнялись, по крайней мере один раз. Для условия по этому критерию надо покрыть тестами следующие 4 комбинации:
Тесты:
А > 2; с = д; А = 3; с = 0; д = О
А > 2; с # д; А = 3, с = 0, д = 1
А<2; с = д; А = 2, с=1, д = 1
А < 2; с # д; А = 2, с = 1, д = 0
При построении тестов по стратегии "черного ящика" программа рассматривается как "черный ящик" (не известны текст программы и ее логика), а исходной информацией для тестовых наборов служат ее спецификации.
К стратегии "черного ящика" относятся методы:
эквивалентного разбиения;
анализ граничных значений;
функциональных диаграмм.
Метод эквивалентного разбиения. Построение тестов методов эквивалентного разбиения осуществляется в 2 этапа: 1) выделение классов эквивалентности; 2) построение тестов.
Классом эквивалентности называют множество входных значений, каждое из которых имеет одинаковую вероятность обнаружения конкретного типа ошибки.
Классы эквивалентности выделяются путем анализа входного условия и разбиением его на две или более групп. Для любого условия существуют правильный (представляющий правильные входные данные программы) и неправильный, т.е. ошибочные входные значения, классы эквивалентности (табл. 5).
Таблица 5
Входные условия и классы эквивалентности
Входные условия |
Правильные классы эквивалентности |
Неправильные классы эквивалентности |
При выделении классов эквивалентности целесообразно придерживаться следующих правил.
Если входное условие описывает область значений (например, идентификатор метки может содержать от одного до восьми символов), то определяются один правильный класс эквивалентности (1 < количество символов идентификатора метки <8) и два неправильных класса эквивалентности (ни одного и более 8).
Если входное условие описывает конечное число конкретных значений и есть основание полагать, что каждое значение программа трактует особо (например, способ передачи информации между городами допустим - почтовый, телеграфный, телетайпный), то определяются правильный класс эквивалентности для каждого значения и один неправильный класс эквивалентности (например, "курьерный").
Если входное условие описывает ситуацию "должно быть" (например, "первым символом идентификатора должна быть буква"), то определяются один правильный класс эквивалентности и один неправильный. На основе классов эквивалентности строятся тестовые наборы. Причем для правильных классов эквивалентности нужно стремиться к минимальному числу тестовых наборов, т.е. каждый тест должен покрывать по возможности большее число правильных классов эквивалентности.
Для каждого неправильного класса эквивалентности строится хотя бы один тестовый набор.
Анализ граничных значений. Этот метод предполагает исследование ситуаций, возникающих на границах и вблизи границ эквивалентных разбиений. Например, если правильная область значений есть -1,0 до +1,0, то нужно предусмотреть тесты -1.0, 1.0,-1.001 и 1.001.
Метод функциональных диаграмм. Метод заключается в преобразовании входной спецификации программы в функциональную диаграмму (диаграмму причинно-следственных связей) с помощью простейших булевских отношений, построения таблицы решений (методом обратной трассировки), которая является основой для написания эффективных тестовых наборов данных.
1. В спецификации программы выделяются причины и следст- вия. Причины - это отдельное входное условие, или класс экви- валентности входных условий. Следствие - выходное условие, или результат преобразования системы.
Каждой причине и следствию приписывается уникальный номер.
2. Анализируется семантическое содержание спецификации, которая преобразуется в булевский граф, связывающий причины и следствия. Каждая вершина графа может находиться в состоянии "истина" (1) или "ложь" (0).
Базовые символы для записи булевского графа:
|
тождество, устанавливает: |
если а = 1, то в = 1; если а = 0, то и в = 0
|
|
не, устанавливает
или, устанавливает:
и, устанавливает |
если а = 1, то в = 0; если а = 0, то и в = 1 если а = 1 или в=1, или с = 1, то d = 1, в противном случае d = 0
если а=1 и в = 1, и с = 1, то d=1, в противном случае d = 0 |
3. Диаграмма снабжается примечаниями, задающими ограничения и описывающими комбинации причин и(или) следствий, которые являются невозможными из-за синтаксических или внешних ограничений.
Используются следующие обозначения:
|
Ограничение Е (исключает) устанавливает, что а и в не могут принимать значение 1 одновременно
|
|
Ограничение I (включает) устанавливает, что по крайней мере одна из величин a, b и с не может принимать 0-е значение одновременно
|
|
Ограничение О (одно и только одно) устанавливает, что одна и только одна из величин а или Ь должна быть равна 1 |
|
Ограничение R(требует) устанавливает, что если а = 1, то и b = 1
|
|
Ограничение М (скрывает) является ограничением для следствий и устанавливает, что если следствие а имеет значение 1, то следствие Ь должно принять значение 0
|
4. По полученной функциональной диаграмме строится таблица решений. Для этого поочередно для каждого следствия, значение которого условно устанавливается в 1, прослеживается обратный путь (по диаграмме) ко всем причинам, связанным с этим следствием, и фиксируется их состояние. Каждый столбец таблицы решений соответствует тесту.
5. Столбцы решений преобразуются в тесты.
6.Проектирование интерфейсов прикладного программного обеспечения
6.1. Виды интерфейсов
Пользовательским интерфейсом называется набор приемов взаимодействия пользователя с приложением. Пользовательский интерфейс включает общение пользователя с приложением и язык общения.
Текстовые ОС
Линейные операционные системы реализуют интерфейс командной строки. Основным устройством управления в них является клавиатура. Команда набирается на клавиатуре и отображается на экране дисплея. Окончанием ввода команды служит нажатие клавиши Enter. Для работы с операционными системами, имеющими текстовый интерфейс, необходимо овладеть командным языком данной среды, т.е. совокупностью команд, структура которых определяется синтаксисом этого языка.
Первые настоящие операционные системы имели текстовый интерфейс. В настоящее время он также используется на серверах и компьютерах пользователей.
Графические ОС
Такие операционные системы реализуют интерфейс, основанный на взаимодействии активных и пассивных графических экранных элементов управления. Устройствами управления в данном случае являются клавиатура и мышь. Активным элементом управления является указатель мыши — графический объект, перемещение которого на экране синхронизировано с перемещением мыши. Пассивные элементы управления — это графические элементы управления приложений (экранные кнопки, значки, переключатели, флажки, раскрывающиеся списки, строки меню и т.д.).
Примером исключительно графических ОС являются операционные системы семейства Windows. Стартовый экран подобных ОС представляет собой системный объект, называемый рабочим столом. Рабочий стол — это графическая среда, на которой отображаются объекты (файлы и каталоги) и элементы управления.
В графических операционных системах большинство операций можно выполнять многими различными способами, например через строку меню, через панель инструментов, через систему окон и др. Поскольку операции выполняются над объектом, предварительно он должен быть выбран (выделен).
Основу графического интерфейса пользователя составляет организованная система окон и других графических объектов, при создании которой разработчики стремятся к максимальной стандартизации всех элементов и приемов работы.
Окно— это обрамленная прямоугольная область на экране монитора, в которой отображаются приложения, документ, сообщение. Окно является активным, если с ним в данный момент работает пользователь. Все операции, выполняемые в графических ОС, происходят либо на Рабочем столе, либо в каком-либо окне.
Речевые ОС
В случае SILK-интерфейса (от англ. speech – речь, image – образ, language – язык, knowledge – знание) – на экране по речевой команде происходит перемещение от одних поисковых образов к другим.
Предполагается, что при использовании общественного интерфейса не нужно будет разбираться в меню. Экранные образы однозначно укажут дальнейший путь перемещения от одних поисковых образов к другим по смысловым семантическим связям.
6.2. Области применения каждого вида
Текстовые редакторы
Программа имеет типовой интерфейс. В верхней строке располагается главное меню, строкой ниже - координатная линейка. В нижней части экрана имеется строка состояний и строка подсказки. Большую часть окна занимает рабочее поле. Кроме того на экране имеются горизонтальная и вертикальная линейки прокрутки.
Строка меню - содержит имена команд, объединенных по функциональному признаку. При выборе какой-либо команды меню на экране появляется соответствующее подменю, а при выборе определенных опций обеспечивается доступ к меню более низкого уровня.
Строка состояния содержит имя редактируемого документа и определяет положение курсора в документе. В строке выдается справочная информация.
Строка подсказки содержит информацию о возможных действиях пользователя в текущий момент.
Рабочее поле- часть экрана, предназначенная для создания документа. Максимальный размер его составляет 25 строк по 80 знаков каждая.
Координатная линейка определяет границы документа и позиции табуляции. Линейки бывают горизонтальные и вертикальные. По умолчанию линейка градуирована в сантиметрах.
Линейка прокрутки используется для перемещения текста документа в рабочем поле окна. Линейка, обеспечивающая вертикальное перемещение текста, называется вертикальной, а горизонтальное перемещение - горизонтальной линейкой прокрутки.
Команды вызываются одним из четырех способов:
посредством пиктографического меню,
из командного меню,
из динамического меню,
с помощью "горячих" клавиш
Для вызова команды используются как клавиатура, так и мышь. Все команды и опции логически упорядочены и объединены в меню в соответствии с их назначением. При работе с мышью для вызова команды обычно используется левая кнопка
Применение программы на практике
Теперь рассмотрим возможности, предоставляемые программой для оформления документов.
Деловая документация. В управленческой деятельности предприятий используются в основном текстовые документы, которые должны быть оформлены по определенным правилам. Эти документы называют еще управленческими. Программа предлагает различные шаблоны, используемые при создании документов. Благодаря им легко реализуются принципы стандартизации документов. Один раз оформленный шаблон используется в дальнейшем при подготовке документов подобного рода.
При оформлении документов следует соблюдать правила, обеспечивающие их юридическую силу, оперативный поиск и возможность обработки с помощью современных средств оргтехники. Большая часть документов оформляется на бланке предприятия, содержащем его реквизиты.
Реквизит документа- элемент официального документа. Совокупность расположенных на странице в установленной последовательности реквизитов называется формуляром.
Для оформления большинства документов используется два вида бланков: общий бланк предприятия для оформления документов всех видов и бланк для писем. При этом внешний вид бланков должен соответствовать ГОСТу "Управленческая документация. Единый формуляр-образец".
Оформление документов осуществляется с использованием стилей форматирования и шаблонов документа. Стиль форматирования определяет внешний вид отдельных абзацев и символов, а шаблон документа - вид документа в целом.
Основу шаблона составляют текст и графика. В нем устанавливаются поля страницы, колонтитулы, другие параметры, хранятся стили форматирования. Кроме того, каждый шаблон может содержать макрокоманды, элементы автотекста, установки, выполненные при адаптации команд, пиктографическое меню клавиатуры. Изменения шаблонов допустимы. Стандартная поставка программы имеет 37 шаблонов, позволяющих достаточно быстро создавать наиболее распространенные виды документов.
Деловая корреспонденция. В этом разделе можно выделить два вида писем: личные и служебные. Деловые направляют от имени одного предприятия другому. Они имеют сугубо официальный характер. Личные - посылаются работником одного предприятия работнику равного уровня другого. В них обсуждаются определенные проблемы.
Текст любого письма состоит из нескольких частей:
вступительной фразы
текста основной части, разбиваемой на смысловые абзацы,
заключительной фразы и подписи отправителя.
Редактор позволяет добиться безукоризненного оформления писем, оформляемых на специальных бланках для писем. Как мы говорили ранее эти бланки можно разработать с помощью этого же редактора самостоятельно. Оформить письмо можно при помощи шаблонов писем, имеющихся в программе.
Предлагаются три стандартных шаблона письма: изысканное письмо, современной письмо, стандартное письмо. Шаблоны письма имеют расширение .dot. Можно также воспользоваться мастером писем, создающим образец письма в соответствии с указаниями пользователя.
Программа значительно облегчает работу пользователя, предоставляя ему возможность применения копилки.
Копилка вместе с командой АВТОТЕКСТ- средство многократного вырезания и вставки нескольких документов. Пользователь может вырезать фрагменты из одного или нескольких документов, объединять их, а затем вставлять в другое место этого или иного документа. Фрагменты накапливаются в копилке в порядке их запоминания, отделяясь друг от друга маркерами абзацев.
Серийные письм- однотипные документы, рассылаемые различным адресатам. Для создания их предназначена команда СЛИЯНИЕ меню СЕРВИС. Она соединяет основной документ, содержащий неизменные данные с источником, содержащим переменные данные.
Команда СЛИЯНИЕ имеет диалоговое окно, элементы которого позволяют определить последовательность действий при создании типовых документов. В результате создается как минимум два документа: основной текстовой документ и источник данных.
Источник данных содержит информацию, которая различна в разных экземплярах серийного письма (адреса, имена адресатов и проч).
Основной документ содержит неизменную часть с указанием мест, в которые вставляется информация из документа данных. Результатом обработки документов получается готовое серийное письмо.
Процесс создания серийного письма состоит из трех этапов:
создание Основного документа,
создание Источника данных,
объединение документов.
Эта же команда позволяет оформить почтовые конверты, а также создавать почтовые наклейки и каталоги.
Таблицы. Программа предоставляет пользователям усовершенствованные средства обработки таблиц с использованием WYSIWYG-интерфейса. Ширина столбцов таблицы изменяется с помощью мыши, после ее создания. Высота строки приводится в соответствие с введенными данными самой программой. В данной версии реализован аппарат автоматического форматирования таблиц, позволяющий быстро и эффективно использовать эту операцию, используя набор шаблонов таблиц, предоставляемых программой.
В меню имеется пиктограмма для работы с таблицами. После создания таблицы, она может быть изменена с помощью мыши или команд меню.
Формулы и вычисления. В состав данной версии программы входит программа Редактор формул (Microsoft Equation 2.0). она позволяет вставлять в текст математические формулы и символы. редактор формул полезен при оформлении научных отчетов и статей. Редактор может запускаться как самостоятельная программа или непосредственно из текстового редактора.
Некоторые особенности обработки документов большого объема
В данной программе реализованы два способа форматирования текста - прямое форматирование отмеченных фрагментов и стилевое форматирование. Способы дополняют друг друга.
При стилевом форматировании можно использовать как стили символов, так и стили абзацев. При помощи стилей символов форматируется выделенный текст внутри абзаца (символ, слово, фраза, предложение).
При форматировании отмеченных фрагментов происходит обычная операция форматирования. для поддержания форматирования документов большинство стандартных стилей абзацев базируется на стандартном стиле Обычный, поэтому прежде, чем модифицировать его, следует хорошо подумать, так как эта операция приведет к значительному изменению форматирования всего документа.
Использование стилей позволяет значительно сэкономить время при оформлении больших документов. Чем однороднее документ, тем больше времени будет сэкономлено. Форматирование с помощь стилей заключается в назначении отдельным абзацам или символам текста стилей форматирования. Благодаря им, в случае необходимости, можно легко изменить вид документа. Использование стандартных стилей программы позволяет форматировать не только документ, но и колонтитулы, сноски, заголовки. При этом появляется возможность автоматического создания оглавления.
Все стили сохраняются вместе с документом и могут быть скопированы в другой документ, переименованы или изменены.
Кроме того встроенные мощные средства контроля правописания позволяют выявлять и исправлять ошибки в тексте. Программа определяет неверно написанные слова, словосочетания, повторы и ошибки при использовании прописных букв.
Очень полезными являются словари исключений и пользовательские словари. Они используются наряду с основным словарем и хранятся в виде текстовых документов.
В пользовательские словари включаются термины, отсутствующие в основном словаре, но являющиеся корректными. Обычно это термины специфической области деятельности пользователя.
Словари исключений содержат термины, которые должны подвергаться сомнению, даже если они написаны правильно.
Тезаурус применяется, если необходимо подобрать синонимы к слову. Это позволит избежать повторов слова в тексте, своевременно выполнив замену.
Графические редакторы
Общее понятие о графических редакторах
Графических редакторов или как их еще называют "рисовалок" существует достаточно много. Существуют мощные профессиональные программы такие как Corel Draw, AdobePhotoShop, Adobe Illustrator, Aldus PhotoStyler, 3D Studio и другие. Они, как правило, очень большие по объему и имеют массу вспомогательных программ. Есть программы менее сложные и более компактные - PhotoFinish, а есть и совсем простые, такие как Paintbrush и Paint (из стандартного состава Windows и Windows 95).
Графические редакторы делятся на два типа - растровые (или битмэповые) и векторные.
Битмэповые получили свое название от английского bitmap, то есть битовая карта. Они рисуют изображение по точкам, что означает, что для каждой точки картинки отдельно задан ее цвет. К такому типу относятся редакторы PhotoStyler, PhotoShop, PhotoFinish, Paintbrush.
Векторные редакторы рисую сразу целую линию - дугу, отрезок прямой. Кривые представляются как совокупность дуг и отрезков. К таким редакторам относятся Corel Draw,Adobe Illustrator и другие.
Эти два типа графических редакторов представляют собой два совершенно разных способа кодирования изображений. Перевод файлов из одной системы в другую операция достаточно сложная. Каждый из типов имеет свои достоинства и недостатки, а также свои области применения.
Векторные редакторы позволяют проделывать сложные трансформации формы рисунка, сжатия, растяжения, изменение размера, преобразования контуров. Он позволяют поворачивать любой элемент рисунка на любой угол без искажения формы, а также искажать любые форма (превратить квадрат в круг, цилиндр и тому подобное). В них удобно именно рисовать, сочетая картинки с различным текстом, размещенным произвольным образом (по дугам, по кривой). Однако такие редакторы непригодны для обработки фотоизображений. Чаще всего они используются непосредственно для создания картинки (товарный знак, эмблема).
Битмэповые (растровые) редакторы используются при обработке сканированных изображений - картинок, рисунков, фотографий, введенных в компьютер изображений, сделанных электронным фотоаппаратом. Присутствующее в названии таких редакторов слово "ФОТО" подчеркивает, что основной упор в этих программах делается на ретуширование сканированных изображений, преобразование цветов и оттенков, контраста, четкости, яркости, на игру со светотенью. Однако они почти не предназначены для работы с формой объектов и размер файлов программы существенно больше, чем у векторных.
Многие современные текстовые процессоры и практически все издательские системы поставляются в комплекте с несложными графическими редакторами, что позволяет немедленно поместить в текст нарисованную тут же картинку.
Мы остановимся несколько подробнее на графическом редакторе Paintbrush, входящем комплект оболочки Windows.
Графический редактор Adobe Photoshop
Компания Adobe Systems Incorporated известна своими передовыми разработками во многих сферах компьютерных технологий. Особенно существенные ее достижения в области создания настольных издательских систем (DTP - Desktop Publishing). Она является бесспорным лидером в этой области. Именно компания Adobe первой реализовала программный и аппаратный интерпретаторы языка описания страниц PostScript, который исаользуют все высококачественные устройства вывода изображений. Это прежде всего фотонаборные автоматы, составляющие технологическую основу современного цикла подготовки полиграфических оригинал-макетов. Программы Adobe Photoshop, AdobeIllustrator, Adobe FrameMaker, Adobe Separator, Adobe Acrobat, Adobe Streamline и другие составляют замечательный и мощный комплект программного обеспечения современного издательства. После слияния со своим главным конкурентом Aldus, что позволило включить ей в свой арсенал такие программы как Aldus PhotoStyler, Aldus PageMaker, компанияAdobe внесла в свой актив одну из лучших программ верстки - PageMaker. Этот шаг позволил ей еще сильнее упрочить свои позиции на рынке программного обеспечения.
Компания постоянно совершенствует свой пакет издательских программ, настраивая его в соответствии с современными требованиями и растущей мощностью настольных компьютеров. Другой стороной работы компании является развитие набора программ, улучшение их совместимости и переносимости документов между ними.
Программа обработки изображений компании Adobe - Photoshop является безусловным лидером (и по объему продаж в том числе) среди графических редакторов. Она достигла таких результатов за счет своих широчайших возможностей, высокой эффективности и скорости работы.
Программа предназначена для любых работ, связанных с созданием и обработкой точечной (растровой) графики - bitmapped imagies. К таким изображениям относятся книжные и журнальные иллюстрации, фотоснимки, слайды, видеокадры, мультипликационная графика и так далее. Программа предоставляет огромный выбор для множества творческих специалистов. Так например, художник-иллюстратор может дать своему воображению и рисовать на экране любые композиции, сохранять варианты, комбинировать их со сканированным изображением, использовать способы трансформации изображений.
Художник-дизайнер, возможно, не полностью удовлетворит свои потребности с помощью этой программы (необходима программа векторной графики), однако включение в процесс программы точечной графики существенно обогатит творческий диапазон и обеспечит переход от эскиза к конечному результату.
Программа удобна и для работников в области издательского дела и полиграфии, так как при наличии сканера или цифрового фотоаппарата она обеспечивает возможности по ретуши, коррекции, монтажу фотоизображений.
Что касается обычного пользователя, программа располагает как традиционными для художника средствами, так и совершенно новыми. Следует помнить, что привычные инструменты работают не совсем так, как их реальные прототипы.
Программа относится к классу профессиональных и ориентирована на достаточно высокий аппаратный уровень. Для среды Windows разработчики в качестве минимальных требований определяют:
компьютер с процессором не ниже 1386,
оперативная память не менее 16 Мбайт,
свободное дисковое пространство не менее 20 Мбайт для установки программы и 20 Мбайт для выполнения операций,
видеоадаптер не менее 256 цветов,
операционная система Windows 95.
Однако такой минимальный уровень ресурсов, позволяющий запустить программу, не дает возможности выполнять достаточно сложную и объемную работу. Поэтому, фирма рекомендует использовать компьютеры с процессором 1486, оперативной памятью 32 Мб, видеоадаптером более 256 цветов, со свободным дисковым пространством свыше 60 Мбайт. Кроме этого для качественной работы с программой требуется наличие дисковода для CD-ROM и цветного сканера.
Графический редактор Paintbrush.
Paintbrush - программа, находящаяся в пакете с оболочкой Windows. Она предназначена для создания и редактирования на экране изображений (картинок). Изображения сохраняются в графических файлах растрового формата и имеют расширения .ВМР или .РСХ. Каждое изображение представляет из себя мозаику из точек (пикселей), окрашенных в определенный цвет.
Редактор позволяет создавать довольно сложные и внешне привлекательные рисунки, схемы и чертежи. Изображения могут быть как в цвете, так и черно-белыми. В распоряжение пользователя программа предоставляет различные художественные средства, как то палитра цветов, кисть, аэрозольный баллончик, ластики для стирания, карандаши для рисования геометрических фигур (линий, многоугольников, эллипсов). С помощью различных шрифтов из комплекта Windows можно делать эффектные надписи к изображениям. С помощью "ножниц" можно вырезать фрагменты картинок, а затем перемещать отдельные части изображения, копировать их, уменьшать, увеличивать, разворачивать и так далее. Если готовый набор красок не удовлетворяет пользователя, программа предоставляет ему возможность использовать "палитру" для смешивания красок, создавая свои цвета.
Естественно, что для создания сложных картинок от пользователя потребуются и художественные способности. Однако любой может подготовить простые рисунки, схемы, а также использовать готовые изображения из других файлов.
Программа позволяет создавать рекламу, буклеты, объявления, приглашения, поздравления, иллюстрации к текстовым документам и прочее. Однако она не пригодна для серьезных графических работ, таких как техническое проектирование (деталей. машин домов) и редактирования фотоиллюстраций.
Paintbrush - простой однооконный графический редактор. Обычно ее значок лежит в окне Инструменты и представляет собой веселенькую, в пятнах краски, желтую палитру с кисточкой. После запуска программы на экране появляется окно без имени, что означает отсутствие имени у создаваемого рисунка или то, что данный рисунок не сохранялся на диск ранее.
Центральную часть окна занимает рабочее поле - часть экрана, на котором рисуют картинку. Ее размер может превышать размер рабочего поля, тогда на экране отображается только фрагмент изображения. Если размер картинки меньше рабочего поля, то она ограничивается рамкой в левой верхней части рабочего поля.
Вторая строка представляет собой меню программы стандартного вида. В ней размещен весь инструментарий - кисточки, кожницы, малярный валик, средства для рисования геометрических фигур разной формы. Для выбора инструмента, также как и в текстовом редакторе, следует подвести мышь к пиктограмме и нажать левую кнопку.
Внизу экрана расположена цветовая палитра, а левее ее - палитра толщин для линий, частиков, циркулей и прочих необходимых для рисования инструментов.
Все линии и фигуры рисуются тем светом, который выбран на цветовой палитре. Для выбора нужного цвета, подвести к нему курсор и щелкнуть кнопкой мыши.
Рассмотрим средства для рисования программы:
Кисточка рисует первым цветом, курсор при этом имеет форму квадратики, кружочка или черточки. Форма курсора выбирается в меню ПАРАМЕТРЫ (Options) командой Форма Кисточки (Brush Shape).
6.3.Проектирование интерфейсов
Обзор специализированного инструментария показал, что наибольшему числу требований удовлетворяют средства для разработки интерфейса, основанные на моделях. Поэтому предлагаемый в работе подход является развитием моделеориентированного подхода. Новый подход также, как и моделеориентированный, исходит из раздельной разработки и модифицирования интерфейса и прикладной программы, разделения интерфейса на компоненты, необходимости инструментальной поддержки их проектирования, раздельной модификации, повторного использования, а также автоматической генерации кода интерфейса по модели.
Новым является определение модели пользовательского интерфейса, которая содержит лишь ту информацию, которая может подвергнуться изменению в его жизненном цикле. Проектирование интерфейса связано с четырьмя основными классами систем понятий:
- системой понятий пользователя, в терминах которой он осуществляет свое взаимодействие с прикладной программой;
- одной из систем понятий, в терминах которой определяются различные типы диалога;
- системой понятий для определения сценарий диалога;
-системой понятий, в терминах которой осуществляется связь между прикладной программой и пользовательским интерфейсом.
Таким образом, модель интерфейса содержит четыре компоненты, каждая из которых определяется в терминах одной из этих систем понятий. В терминах этих же систем понятий обеспечивается интеллектуальная поддержка разработчика с использованием структурных и графических редакторов, а также определяются связи между компонентами.
Для обеспечения поддержки проектирования и реализации различных типов диалога разработчику интерфейса предлагаются три системы понятий, каждая из которых поддерживает проектирование одного из типов диалога – система понятий графического пользовательского интерфейса, поддерживающего разработку интерфейсов, основанных на формах или WIMP-интерфейсов (windows, icons, menus, pointing devices), система понятий графических статических сцен, и система понятий для формирования текстов (в дальнейшем количество систем таких понятий предполагается увеличить).
Для обеспечения «открытости» инструментария предлагаются следующие решения:
- явное представление систем понятий в форме моделей онтологий1;
- предоставление разработчику структурных и графических редакторов для формирования разных компонент модели интерфейса, управляемых моделями онтологий;
- предоставление специалистам, осуществляющим сопровождение инструментария, редакторов моделей онтологий и модели генерации кода, которая описывает соответствия между компонентами модели интерфейса и инструкциями целевого языка программирования.
Изменение моделей онтологий не приводит к модификации кода редакторов, которыми эти модели управляют, поскольку редакторы реализуются как интерпретаторы моделей онтологий. Если изменение онтологий требует изменений генератора кода интерфейса, то они осуществляются внесением изменений в модель генерации кода.
Для обеспечения открытости средств оценивания проекта интерфейса, эти средства модели должны управляться базой знаний о дефектах. База знаний формируется и модифицируется с помощью редактора базы знаний о дефектах, управляемого моделью онтологии дефектов интерфейса, и, соответственно, является расширяемой (модифицируемой).
Повторная используемость компонент интерфейса обеспечивается многоуровневыми библиотеками повторно используемых компонентов.
Таким образом, модель интерфейса проектируется на основе универсальных моделей онтологий для формирования каждого компонента модели интерфейса. В интерфейсе можно выделить следующие универсальные модели онтологий: D – модель онтологии пользователя; G – модель онтологии представления, которая состоит из трех моделей онтологий, определяющих один из типов диалога (G1, G2, G3); S – модель онтологии сценария диалога, L – модель онтологии связи с прикладной программой. Каждая из моделей онтологий имеет вид: <Name, OS>, где Name – множество имен, Name ={<n, {sn}>}, n- имя термина, sn- характеристика (атрибут) этого термина. OS – множество онтологических соотношений. Формирование компонента модели интерфейса сводится к заданию значений понятий соответствующей универсальной модели онтологии. Соответственно, модель интерфейса есть {D, G, L, S}.
Модель онтологии пользователя определяет четыре класса терминов: группы, понятия, характеристики и области возможных значений (ОВЗ). Группа – это традиционное в предметной области объединение концептуально связанных групп и/или понятий. Понятия делятся на простые, не имеющие внутренней структуры, и составные. Составные понятия обладают набором характеристик. Характеристика также может быть простой или составной; в последнем случае она обладает набором характеристик. Каждая простая характеристика или простое понятие описываются ОВЗ либо качественных, перечисляемых в описании ОВЗ, либо числовых (в этом случае ОВЗ задается диапазоном значений). Качественные значения могут быть «взаимоисключающими» или «совместными».
Модель онтологии представления. Данная модель онтологии состоит из трех моделей онтологий - модели онтологии графического пользовательского интерфейса, модели онтологии графических статических сцен на плоскости, модели онтологии для формирования текстов. Каждая из моделей онтологий позволяет реализовать один из типов диалога.
Рис. 53 Модель системы понятий пользователя
Модель онтологии графического пользовательского интерфейса (ГПИ) предназначена для формирования компонента представления информации на основе экранных форм. Она определяет две основные группы элементов – окна и оконные элементы управления, а также три дополнительные группы – панели управления, оконные меню и вспомогательные средства.
Модель онтологии графических статических сцен на плоскости определяет базовое графическое изображение, наполнения и примитивы. Базовое графическое изображение - это произвольный графический рисунок, схема, эскиз и т. п., являющееся основой для нанесения на него различных изображений. Базовое графическое изображение определяются своим именем, изображением, типом и соответствующим типу описанием его составляющих. Наполнение задает возможные варианты цветового и рельефного изображения базы. Для каждого базового изображения может быть задано множество возможных наполнений, которые определяются именем наполнения, его цветом и текстурой. Примитив задает возможные варианты изображений, наносимых на базовое изображение. Для каждой базы может быть задано множество возможных примитивов. Каждый примитив определяется именем, типом и соответствующим типу описанием. Тип примитива может быть либо предопределенным, либо строящимся, либо сложным. У предопределенных примитивов изображение определено заранее. Для строящегося примитива необходимо задать имя, форму примитива, цвет линии и фона. Сложный примитив – это совокупность строящихся примитивов, соединенных между собой линиями заданного цвета и типа.
Модель онтологии для формирования текстов определяет конструкции для описания структуры и способа порождения текста на основе результатов (выходных данных прикладной программы).
Конструкции для описания структуры и способа порождения текста состоят из последовательности элементов описания, каждый из которых определяет зависимость порождаемого текста от выходных данных прикладной программы. Конструкциями онтологии для формального описания структуры и способа порождения текста являются: альтернатива, цикл, выводимое множество и строка. Цикл и альтернатива, в свою очередь, также содержат элементы описания текста в качестве компонент.
На рис. 2 представлены экранные формы, соответствующие трем типам диалога для фрагмента модели системы понятий пользователя, представленной на рис.1. Экранные формы проектируются с помощью описанных выше моделей онтологий. Так, рис. 54А соответствует типу диалога, основанному на экранных формах, рис. 54Б - типу диалога, основанному на графических сценах. В этом случае заполнение результатов осмотра больного включает формы с изображением схемы полей зрения и множеством условных обозначений, которые наносятся на эти формы и служат результатами осмотра. На рис. 54В приведен фрагмент текста, описывающий те же данные и сформированный на основе модели онтологии для формирования текстов.
|
|
|
А Б В
Рис.54 Представление информации из раздела медицины «офтальмология» в различных формах:
А – интерфейс, основанный на формах; Б- интерфейс, основанный на графических сценах; В – интерфейс в виде текста.
Модель онтологии сценария диалога определяет абстрактные термины для описания реакций на события (наборы действий, выполняемых при возникновении событий, источники событий, вид режимов переходов между окнами, способы выбора экземпляров окна и др.). Вершины графа данной модели онтологии соответствуют оконным классам модели онтологии графического пользовательского интерфейса, дуги графа – переходам между вершинами. Каждая вершина описывается именем класса модели онтологии графического пользовательского интерфейса, именем окна, множественностью, а также реакцией окна на события. Различается три типа множественности: единичная, конечная и произвольная. Реакция окна на события - это набор действий, выполняемых при возникновении различных событий. Каждая реакция описывается тройкой: источником событий (экземпляр оконного класса, прикладная программа, оконный элемент управления), именем события, принадлежащего источнику и реакцией на событие. Каждая дуга описывает режим перехода между окнами, способ выбора нового окна, а также событие, которое инициирует переход и вызов функций прикладной программы. Любой из трех типов диалогов использует оконные классы модели онтологии ГПИ, что позволяет описать сценарий диалога, соответствующий различным типам диалога.
Модель онтологии связи с прикладной программой определяет множество программных интерфейсов, предоставляемых прикладной программой. Каждый программный интерфейс описывает модель взаимодействия с программой, которая может быть локальной и распределенной, а также список функций, предоставляемых данным интерфейсом. Каждая функция характеризуется типом возвращаемого значения и множеством параметров, также определяемых типом.
Управление процессом проектирования и генерацией программного кода на основе онтологий.
Управление проектированием пользовательского интерфейса осуществляется разработчиком пользовательского интерфейса, а модели онтологий, которые управляют структурными и графическими редакторами, регламентируют набор правил для задания понятий, их характеристик и значений, определяющих специфику каждого компонента пользовательского интерфейса. На рис. 54 изображена базовая архитектура инструментального комплекса.
Рис. 54 Базовая архитектура инструментального комплекса для разработки пользовательского интерфейса.
Генератор кода каждому компоненту модели онтологии сопоставляет набор исходных кодов на некотором языке программирования и связывает их вместе. Кроме того, генератор вносит в программный код дополнительные конструкции, предоставляющие возможность редактирования полученного кода в одном из существующих средств разработки для данного языка программирования, а также коды программных интерфейсов, структур данных и организации взаимодействия (набора инструкций связывания интерфейса и прикладной программы). В настоящее время разработан прототип инструментального средства, который поддерживает генерацию кода на языках C# и Java.
Для поддержки проектирования и реализации различных типов диалога предлагаются три модели онтологии – модель онтологии графического пользовательского интерфейса, графических статических сцен на плоскости, модель онтологии для формирования текстов. В результате, одной модели системы понятий пользователя и модели связи с прикладной программой может соответствовать несколько типов диалога, основанных на экранных формах, графических сценах, текстах. Для расширения типов реализуемых диалогов в настоящее время разработана модель онтологии графических динамических сцен на плоскости, разрабатывается редактор таких сцен, модель и методы автоматической генерации диалогов, основанных на динамических сценах.
Модель интерфейса состоит из следующих компонентов: модели системы понятий пользователя, модели представления, модели сценария диалога и модели связи с прикладной программой. Инструментальная поддержка проектирования обеспечивается набором редакторов для проектирования. Сформированная с их помощью модель затем автоматически преобразуется в исполнимый код на некоторый целевой язык программирования.
Инструментальный комплекс поддерживает раздельную разработку и модификацию интерфейса и прикладной программы, а также связывание кода отдельно разработанных компонентов.
Интеллектуальная поддержка разработчика осуществляется на основе проблемно-независимых моделей онтологий, отражающих специфику каждого компонента модели, а также структурных и графических редакторов, управляемых этими моделями онтологий и освобождающих, таким образом, разработчиков от изучения различных языков для формирования компонентов модели.
Для обеспечения «открытости» инструментария графические и структурные редакторы реализованы как интерпретаторы моделей онтологий. Для их модификации предлагаются редакторы моделей онтологий, это позволяет изменять онтологии без изменения кода; если модифицирование инструментария требует изменения кода интерфейса, разработчик вносит их в модель генерации кода, которая описывает соответствия между компонентами модели интерфейса и инструкциями целевого языка программирования.
Список использованной и рекомендуемой литературы
Гарнаев А. Visual Studio.NET 2003. – СПБ.: «БХВ Петербург», 2009. – 660 с.
Бучек Г. ASP.NET. Учебный курс. Пер с англ. – М.; СПБ.: «Питер», 2008. – 505 с.
Пейн К. ASP.NET за 21 день. Пер. с англ. - К.; М.; СПб.: Издательский дом «Вильямс», 2008. - 824 с.
Постолит А. Visual Studio.NET работка приложений баз данных. –СПБ.: «БХВ Петербург», 2009. – 538 с.
Смирнова Г.Н., Сорокин А.А., Тельнов Ю.Ф. Проектирование экономических информационных систем. Учебник. –М.:Финансы и статистика, 2009. -505 с.
Оньон Ф. Основы ASP.NET с примерами на C#. Пер. с англ. - К.; М.; СПб.: Издательский дом «Вильямс», 2008. - 294 с.
Кузнецов С.Д. Проектирование и разработки корпоративных информационных систем: Курс лекций.- \\www.citforum.ru
Дейт К.Дж. Введение в системы баз данных, 6-е издание: Пер. с англ. - К.; М.; СПб.: Издательский дом «Вильямс», 2009. - 848 с.
Джеффри Д.Ульман, Дженнифер Уидом. Введение в системы баз данных. Пер. с англ. - М.: Издательство «Лори», 2009. - 374 с.
Карпова Т.С. Базы данных: модели, разработка, реализация. –СПб.: Питер, 2008. – 304 с
Коннолли Т., Бегг К., Страчан А. Базы данных: проектирование, реализация и сопровождение. Теория и практика, 2-е изд.:пер. с англ.: Уч.пос. – М.: Изд.дом «Вильямс», 2008– 1120 с.
Список электронных источников информации
Григорьев В.Ю., Павлов Р.В., Устинов А.В. Информационная система образовательного портала "Юридическая Россия"2010 http://www.edu.ru/db/portal/e-library/00000092/22statya.pdf
Бурков А.В. Проектирование информационных систем: Учебный курс Марийский государственный университет 2009 http://window.edu.ru/window_catalog/files/r61403/burkov-lectures.pdf http://window.edu.ru/window_catalog/files/r61403/burkov-quest.pdf
1 Онтология – явное описание концептуализации. Она может иметь различные формы, но обязательно включает словарь терминов, спецификацию их смысла, а также описание связей между терминами