This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Введение в разработку распределенных информационных систем. Курс лекций. Оглавление 1. Введение в информационные системы ..............................................................................2 1.1 Общее представление об информационных системах................................................2 1.2 Жизненный цикл информационных систем ................................................................3 1.3 Основные понятия теории реляционных систем баз данных ....................................5 1.4 Архитектура информационных систем ........................................................................8 2. Язык SQL...............................................................................................................................9 2.1 История и стандарты языка SQL...................................................................................9 2.2 Структура языка SQL.....................................................................................................9 2.3 Типы данных SQL и выражения .................................................................................10 2.4.1 Оператор SELECT .....................................................................................................11 2.4.2 Оператор UNION .......................................................................................................15 2.4.3 Оператор INSERT......................................................................................................15 2.4.4 Оператор UPDATE ....................................................................................................16 2.4.5 Оператор DELETE.....................................................................................................17 2.5.1 Оператор CREATE TABLE ......................................................................................17 2.5.2 Оператор ALTER TABLE .........................................................................................22 2.5.3 Оператор DROP TABLE ...........................................................................................23 2.6.1 Оператор GRANT ......................................................................................................23 2.6.2 Оператор REVOKE....................................................................................................24 3. Объекты баз данных...........................................................................................................25 3.1 Представления ..............................................................................................................25 3.2 Хранимые процедуры ..................................................................................................26 3.3 Триггеры........................................................................................................................27 3.4 Транзакции и блокировки............................................................................................29 3.5 Индексы .........................................................................................................................34 4. Языки HTML И DHTML....................................................................................................36 4.1 История и стандарты языка html.................................................................................36 4.2 Структура страницы на языке html.............................................................................37 4.3 Каскадные таблицы стилей .........................................................................................38 4.4 Сценарии JavaScript......................................................................................................42 5. Язык C#................................................................................................................................48 5.1 Платформа .NET ...........................................................................................................48 5.2 Основы языка C# ..........................................................................................................51 5.3 Объектно-ориентированное программирование .......................................................57 5.4 Обработка исключительных ситуаций .......................................................................61 5.5 Интерфейсы...................................................................................................................63 5.6 Делегаты и события......................................................................................................64 5.7 Доступ к данным ..........................................................................................................66 5.8 Разработка web-приложений .......................................................................................77
1. Введение в информационные системы 1.1 Общее представление об информационных системах Информационные системы (ИС) относятся к классу программных продуктов, автоматизирующих работу каких-либо организаций, компаний и учреждений. Можно выделить по крайней мере два свойства, которые являются общими для всех информационных систем: • любая информационная система предназначена для сбора, хранения и
обработки
информации.
Поэтому
в
основе
любой
информационной системы лежит среда хранения и доступа к данным, которая должна обеспечивать уровень надежности хранения и эффективности доступа, соответствующий области применения информационной системы. В большинстве случаев наиболее надежным способом хранения информации является использование базы данных. • любая информационная система предназначена для пользователя, являющего специалистом в той предметной области, на которую ориентирована информационная система, но в большинстве случаев не являющегося специалистом в области информационных технологий. Вследствие этого информационные системы обязаны поддерживать дружественный по отношению к пользователю интерфейс. В зависимости от месторасположения компонент информационные системы делятся на локальные и распределенные. Все компоненты локальной информационной системы размещаются на одном компьютере. Информационная система, компоненты которой распределяются между несколькими компьютерами, называется распределенной.
1.2 Жизненный цикл информационных систем В
основе
деятельности
по
созданию
и
использованию
информационных систем лежит понятие жизненного цикла. Жизненный цикл отражает различные состояния информационной системы, начиная с момента принятия решения о создании системы и заканчивая моментом прекращения
ее
функционирования.
Модели
жизненного
цикла
информационных систем: 1. каскадная модель (модель водопада, последовательная модель) предполагает переход на следующий этап цикла только после полного окончания работ на предыдущем этапе. Основной недостаток данный модели состоит в том, что работающая система, которая может быть продемонстрирована конечному пользователю, появляется только на поздних этапах жизненного цикла и в случае возникновения изменения в требованиях стоимость их учета весьма велика. Каскадная модель в основном использовалась в 70-80 годы прошлого века. 2. спиральная модель (итерационная модель) предполагает создание прототипа информационной системы на самых ранних стадиях проектирования. Каждый виток спирали соответствует созданию новой версии прототипа программного продукта. При таком подходе
к
разработке
удается
предоставить
конечному
пользователю прототип системы для ознакомления и тестирования тогда, когда в системе еще не реализована большая часть функций и внести изменения в проект еще достаточно просто. Каскадная модель стала широко использоваться в конце 80-х годов прошлого века. Традиционный жизненный цикл включает следующие основные этапы: a. анализ требований. На этом этапе необходимо выявить все актуальные
и
потенциальные
потребности
заказчика
информационной
системы,
понять,
какие
потоки
данных
существуют внутри организации заказчика, оценить объемы информации, описать бизнес-процессы и т.д. Анализ требования может носить как неформальный, так и формальный характер. Среди формальных подходов к анализу требований в последнее время все более популярным становиться язык UML (Unified Modeling
Language).
используются
use
Для
case
описания диаграммы
требований (диаграммы
в
UML
вариантов
использования системы). b. проектирование. На этом этапе необходимо дать ответ на вопрос, как система будет реализовывать те требования, которые к ней предъявлены на этапе анализа требований. Проектирование включает в себя выработку архитектуры системы, разбиение системы на подсистемы и распределение функций между ними, проектирование
базы
данных,
определение
требований
к
аппаратным и программным компонентам системы. c. программирование. На этом этапе происходит непосредственное кодирование программных модулей информационной системы. d. тестирование и отладка. На этом этапе происходит тестирование созданных программных модулей и исправление найденных ошибок. В настоящее время принято различать три вида тестов: тесты
модулей,
интеграционные
или
компонентные
тесты,
системные тесты. Тесты модулей включают в себя тестирование отдельных классов, подпрограмм, модулей. Интеграционные тесты предназначены
для
тестирования
взаимодействия
различных
программных модулей системы между собой. Системные тесты тестируют всю систему в целом так, как ее видит конечный пользователь.
e. внедрение и сопровождение. На этом этапе происходит внедрение информационной
системы
у
заказчика
и
последующее
сопровождение работы пользователей с системой.
1.3 Основные понятия теории реляционных систем баз данных База данных - совокупность связанных данных, организованных по определенным правилам, предусматривающим общие принципы описания, хранения и манипулирования, независимая от прикладных программ. Реляционная база данных - это база данных, в которой информация представлена в виде двумерных таблиц, сохраняемых в файлах. Таблица состоит из строк, называемых записями, записи состоят из столбцов, называемых полями. Система управления базами данных (СУБД) - это совокупность языковых и программных средств, предназначенных для создания, ведения и совместного использования БД многими пользователями. Пользователей СУБД можно разделить на три большие группы: 1. разработчики базы данных отвечают за написание прикладных программ, использующих базу данных; 2. конечные пользователи работают с базой данных либо через некоторую информационную систему, либо пользовательский интерфейс системы управления базами данных; 3. администраторы
базы
данных
обеспечивают
поддержание
работоспособности базы данных, сохранность и безопасность данных, настройку работы базы данных. Базовой архитектурой СУБД является трехуровневая модель, в рамках
которой
СУБД
представляется
состоящей
из
внешнего,
концептуального и внутреннего уровня. На внешнем уровне содержимое СУБД представляется так, как его видит отдельный пользователь. На концептуальном уровне данные СУБД описываются в обобщенной модели
предметной области, для которой создается информационная система. Внутренний уровень - это собственно данные, расположенные в файлах. В ведении СУБД также находится словарь данных, содержащий сведения обо всем, что хранится в базе данных (имена всех таблиц и представлений, хранимых процедур и триггеров, учетные записи пользователей СУБД и т.п.). Сведения такого рода принято называть метаданными. Реляционная модель данных основывается на математических принципах теории множеств и математической логике. Эти принципы были впервые использованы для моделирования данных в 60-х годах прошлого века Коддом. Реляционная модель определяет, каким образом данные могут быть представлены (структура данных), каким образом данные могут быть защищены от некорректных изменений (целостность данных) и какие операции могут быть выполнены с данными (операции с данными). Основные понятия реляционной модели: • все данные концептуально представляются как упорядоченное набор строк и столбцов, называемых отношением; • все данные являются скалярными; • строка
данных
называется
кортежем,
количество
кортежей
называется кардинальным числом; • каждый столбец в кортеже называется атрибутом, количество атрибутов называется степенью отношения; • отсутствие информации описывается значением NULL; • потенциальный ключ K для отношения R - это подмножество множества
атрибутов
R,
всегда
обладающее
свойством
уникальности (т.е. нет двух кортежей в отношении R с одинаковым значение K) и свойством не избыточности (т.е. никакое из подмножеств
K
не
обладает
свойством
уникальности).
Потенциальный ключ, состоящий из более чем одного атрибута, называется составным, а из одного - простым. Первичный ключ -
это потенциальный ключ, по которому физически упорядочены кортежи в отношении. • внешний ключ определяется следующим образом. Пусть R2 некоторое отношение. Тогда внешний ключ FK в отношении R2 это такое подмножество множества атрибутов R2, что существует отношение R1 с потенциальным ключом K и значение FK в любом кортеже R2 всегда совпадает со значением K некоторого кортежа в R1. Ограничение, по которому значения внешнего ключа должны быть адекватны значениям соответствующего потенциального ключа, называют ссылочным ограничением. Соответственно, под ссылочной целостностью понимают требование того, чтобы в базе данных не было нарушений ссылочных ограничений. Следующие операции допустимыми над данными в реляционной модели: • выборка
заданного отношения после исключения из него некоторых атрибутов; • произведение
возвращает
отношение,
содержащие
кортежи,
которые являются всеми возможными сочетаниями кортежей, принадлежащих двум исходным отношениям; • объединение возвращает отношение, содержащие все кортежи, принадлежащие двум исходным отношениям; • соединение возвращает отношение, кортежи которого являются соединением
двух
кортежей,
принадлежащих
исходным
отношениям и имеющим общее значение для одного или более атрибутов исходных отношений; при этом общее значение атрибутов встречается в результирующем кортеже только один раз.
1.4 Архитектура информационных систем Файл-серверная архитектура: • сервер - хранит файлы и обеспечивает совместный доступ к ним со стороны пользователей; • клиент - предоставляет пользовательский интерфейс, обеспечивает работу бизнес-логики и системы управления базами данных. Двухуровневая клиент-серверная архитектура: • сервер - обеспечивает работу системы управления базами данных и реализует часть функций бизнес-логики; • клиент - предоставляет пользовательский интерфейс и реализует часть функций бизнес-логики. Многоуровневая клиент-серверная архитектура: • сервер базы данных - обеспечивает работу системы управления базами данных; • сервер приложений - реализует функции бизнес-логики; • клиент - предоставляет пользовательский интерфейс. Одним из наиболее популярных в настоящее время вариантов реализации
многоуровневой
архитектуры
является
построение
Internet/Intranet приложений. В качестве клиента в таких приложениях выступает браузер. За генерацию пользовательского интерфейса отвечает приложение,
выполняющееся
на
web-сервере
взаимодействие клиента с сервером приложений.
и
обеспечивающее
2. Язык SQL 2.1 История и стандарты языка SQL SQL (Structured Query Langauge - структурированный язык запросов) является стандартным языком, используемым для работы с реляционными базами данных. Он позволяет исключить большую работу, необходимость которой возникает при попытке использовать языка программирования общего назначения для разработки функций работы с базой данных. Язык SQL был разработан в конце 70-х годов в компании IBM и был впервые реализован в реляционной СУБД IBM System R. В дальнейшем, благодаря своей элегантности, независимости от специфики компьютера и поддержке лидерами в области технологии реляционных баз данных, SQL стал и в обозримом будущем останется стандартом "дефакто" для всех реляционных систем обработки данных. Первый международный стандарт языка SQL был принят в 1989 году ANSI. Этот стандарт называют SQL/89. Подавляющее большинство СУБД поддерживают этот стандарт полностью. В связи с развитием информационных
технологий
через
некоторое
время
возникла
необходимость расширения стандарта. В 1992 году был принят новый стандарт SQL/92. Затем в 1999 году был принят стандарт SQL/99 и, наконец, самый последний стандарт языка SQL был принят в 2003 году и носит название SQL/2003. Стоит, правда, сказать о том, что не все СУБД ограничиваются полной поддержкой стандарта и часто добавляют в язык SQL
какие-то
специфичные
конкурентоспособности СУБД.
2.2 Структура языка SQL
возможности
с
целью
повышения
В структуре языка SQL выделяют три подмножества операторов языка: 1. язык определения данных (DDL, Data Definition Language) подмножество операторов языка SQL, которое обеспечивает определение данных, хранящихся в базе данных; 2. язык
манипулирования
данными
(DML,
Data
Manipulation
Language) - подмножество операторов языка SQL, используемых для выборки, добавления и удаления данных для объектов, определенных с помощью DDL; 3. язык управления данными (DCL, Data Control Language) подмножество
операторов
языка
SQL,
используемых
для
управления правами доступа к объектам базы данных.
2.3 Типы данных SQL и выражения Тип данных - это атрибут, определяющий тип информации, которую может содержать объект. У всех полей, переменных, хранимых процедур есть определенные типы данных. Основные типы данных перечислены ниже (Microsoft SQL Server 2000): • char(n) - символьные строки постоянной длины в n символов; • varchar(n) - символьные строки переменной длины, максимальная длина n символов; • datetime, smalldatetime - дата и время; • float, real - числа с плавающей запятой; • int, smallint - целые числа. Выражение - это комбинация идентификаторов, значений и операторов, которые сервер СУБД может обработать, чтобы получить результат. Основные виды операторов представлены ниже:
• сравнение - сравнивает значение с другим значением или выражением (>, >=, <, <=, =, <>); • логический - проверяют истинность условия AND, OR, NOT, LIKE, ANY, ALL или IN; • арифметический - выполняют сложение (+), вычитание (-), умножение (*), деление (/) и остаток от деления (%); • конкатенация строк - объединение двух строк в одну (+); • присваивание - присваивают значение переменной (set) или ассоциируют столбец результирующего набора с псевдонимом (as).
2.4.1 Оператор SELECT Оператор SELECT позволяет получать существующие данные из базы данных. Большинство операторов SELECT описывают четыре главных свойства результирующего набора: 1. столбцы, которые должны войти в результирующий набор; 2. таблицу или таблицы, из которых извлекаются данные для формирования результирующего набора; 3. условия, которым должны соответствовать строки исходной таблицы или таблиц, чтобы попасть в результирующий набор; 4. последовательность упорядочения строк в результирующем наборе. Оператор SELECT имеет следующий синтаксис (необязательные элементы заключены в квадратные скобки): SELECT [DISTINCT][TOP n] {список полей} FROM {список таблиц} [WHERE {условия выборки или соединения}] [GROUP BY {список полей, по которым выполняется группировка}] [HAVING {условия включения в группу}] [ORDER BY {список полей для сортировки}]
Оператор DISTINCT используется для исключения дублирующих записей из результирующего набора. Оператор TOP n предназначен для отображения первых n записей из результирующего набора. Для задания условий выборки используется оператор WHERE. В этом операторе определяется некоторое условие, которое может быть либо истинным, либо ложным для каждой записи той таблицы или таблиц, из которых происходит извлечение данных. При этом в результирующий набор попадают лишь те записи, для которых условие оказывается истинным. При формировании условий отбора можно использовать операторы отношений (>, <, >=, <=, =, <>), булевы операторы AND, OR, NOT, а также специфичные операторы сравнения SQL: • BETWEEN A AND B - истинен, когда сравниваемое значение попадает в заданный диапазон (включая границы); • IN
(множество)
-
истинен,
когда
сравниваемое
значение
сравниваемое
значение
принадлежит указанному множеству; • LIKE
'шаблон'
-
истинен,
когда
соответствует шаблону. При написании запроса используются символы "%", означающий любое количество любых символов, и "_", означающий один любой символ; • IS NULL - истинен, когда сравниваемое значение есть пустое значение (NULL); IS NOT NULL - истинен, когда сравниваемое значение не пустое значение. Оператор WHERE также часто используется для выборки данных из двух и более связанных между собой таблиц. По другому такой запрос называют соединением таблиц. Для соединения двух связанных между собой таблиц в операторе WHERE следует последовательно приравнять между собой значения полей, с помощью которых таблицы соединены между собой таблицы, и соединить равенства логической операцией AND. Наряду с использованием оператора WHERE для соединения таблиц также
используются операторы INNER JOIN и OUTER JOIN. Конструкция INNER JOIN (внутренней соединение) имеет следующий синтаксис: FROM Таблица1 INNER JOIN Таблица2 ON Таблица1.Поле1=Таблица2.Поле1 AND Таблица1.Поле2=Таблица2.Поле2 AND ... Оператор LEFT OUTER JOIN (левое внешнее соединение) используется для получения результирующего набора данных, в который входят все записи таблицы, расположенные слева от конструкции LEFT OUTER JOIN, и только те записи из таблицы, расположенной справа от конструкции LEFT OUTER JOIN, которые соответствуют условию соединения. Конструкция LEFT OUTER JOIN (внутренней соединение) имеет следующий синтаксис: FROM Таблица1 LEFT OUTER JOIN Таблица2 ON Таблица1.Поле1=Таблица2.Поле1 AND Таблица1.Поле2=Таблица2.Поле2 AND ... Сортировка
результирующего
набора
данных
производится
использованием оператора ORDER BY, после которого указывается поле или поля, по которым производится сортировка, а также направление сортировки (ASC - в возрастающем порядке , DESC - в убывающем, по умолчанию используется ASC). Для сортировки можно указывать несколько полей. В этом случае вначале сортировка производится по первому полю, затем по второму полю и т.д. Конструкция GROUP BY используется для получения сводной информации по группам записей. Вместе с GROUP BY следует использовать одну из групповых (агрегатных) функций, с помощью которых указывается, какие именно сводные данные должны быть получены: • SUM(поле) - сумма значений;
• COUNT(поле) - количество значений (без учета значений NULL). Для подсчета количеств записей с учетом значений NULL используется COUNT(*); • AVG(поле) - среднее значение; • MIN(поле) - минимальное значение; • MAX(поле) - максимальное значение. Все групповые функции игнорируют значения NULL (кроме вызова COUNT(*)), при этом если поле содержит только значения NULL, то результатом применения групповой функции также будет NULL. При применении групповых функции без конструкции GROUP BY агрегатные функции возвращают лишь одно значение, при этом в запросе SELECT можно указать для выборки лишь агрегатные функции. После ключевого слова
GROUP
группирующими.
BY
следует
Конструкция
список
полей,
GROUP
BY
которые
называются
ограничивает
записи
результирующего набора таким образом, что для каждого конкретного значения группирующего поля или полей возможна только одна запись в результирующем наборе. В каждой записи результирующего набора содержатся
сводные
данные,
связанные
с
некоторым
значением
группирующего поля или полей. В запросе SELECT для выборки можно кроме групповых функций также указать имена группирующих полей. Записи сгруппированного результирующего набора фильтруются средствами конструкции HAVING. В этом операторе определяется некоторое условие, которое может быть либо истинным, либо ложным для каждой группы записей той таблицы или таблиц, из которых происходит извлечение данных. При этом в результирующий набор попадают лишь те группы записей, для которых условие оказывается истинным. При формировании условий отбора можно использовать операторы отношений (>, <, >=, <=, =, <>), булевы операторы AND, OR, NOT, а также специфичные операторы сравнения SQL (IN, BETWEEN, LIKE).
2.4.2 Оператор UNION С помощью оператора UNION можно объединить результирующие наборы двух или более запросов SELECT в один результирующий набор. Синтаксис оператора UNION выглядит следующим образом: SELECT {список полей} FROM {список таблиц} ... UNION SELECT {список полей} FROM {список таблиц} ... Для успешного выполнения запроса на объединение количество и тип данных полей, входящих в состав объединяемых запросов, должны совпадать.
2.4.3 Оператор INSERT Оператор INSERT добавляет в таблицу одну или несколько записей. В простейшем случае оператор INSERT имеет следующий вид: INSERT INTO {таблица} [(список полей)] VALUES (список значений) Значения полей в списке значений должны быть указаны в той же последовательности, что и в списке полей. Число значений должно быть равно числу полей, а тип данных и точность целой и дробной части каждого значения должны совпадать с таковыми для соответствующего поля. Если список полей не задан, то значения полей должны быть указаны в той же последовательности, что и поля таблицы. Если в списке полей заданы лишь часть списка полей таблицы, то все поля, не указанные в списке полей, получат пустое значение NULL или значение по умолчанию
(если таковое было определено при создании таблицы). При этом необходимо обратить внимание на то, что все поля, для которых в операторе INSERT не указано явное значение, должны допускать пустые значения или содержать значения по умолчанию. Оператор INSERT не позволяет указывать значения для полей, для которых установлено автоинкрементальное увеличение. В операторе INSERT вместо списка значений может использоваться подзапрос SELECT: INSERT INTO {таблица} [(список полей)] SELECT ... Подзапрос SELECT в операторе INSERT позволяет добавить в таблицу данные из одной или нескольких других таблиц, причем несколько записей одновременно. Подзапрос SELECT в операторе INSERT применяется для добавления к таблице существующих данных, тогда как конструкция VALUES в операторе INSERT используется для добавления к таблице новых данных.
2.4.4 Оператор UPDATE Оператор UPDATE способен изменять данные в одной записи, группе записей или во всех записях таблицы. Синтаксис оператора UPDATE выглядит следующим образом: UPDATE {таблица} SET поле1=значение1[, поле2=значение2] [WHERE {условие}] SET задает поля, которые следует изменить, и их новые значения. Во всех записях, которые соответствуют условию поиска, заданному конструкцией
WHERE,
значения
заданных
полей
обновляются
значениями, заданными в конструкции SET. Если конструкция WHERE не задана, обновляются все записи.
2.4.5 Оператор DELETE Оператор DELETE удаляет из таблицы одну или несколько записей. Синтаксис оператора DELETE выглядит так: DELETE {таблица} [FROM {список таблиц}] [WHERE {условия}] Обязательным элементов оператора DELETE является только указание имени таблицы, из которой необходимо удалить записи. При указании условия в конструкции WHERE из таблицы будут удалены только те записи, которые удовлетворяют указанным после WHERE условиям. Если конструкция WHERE не задана, то удаляются все записи таблицы. Конструкция FROM задает дополнительные таблицы, которые можно использовать при написании условий в конструкции WHERE. Стоит обратить внимание на то, что любая таблица, из которой с помощью оператора DELETE удалены все записи, все равно остается в базе данных. Сами таблицы удаляются из базы данных с помощью оператора DROP TABLE (см. дальше). Для
быстрого
удаления
всех
использовать запрос TRUNCATE TABLE: TRUNCATE TABLE {таблица}
2.5.1 Оператор CREATE TABLE
данных
из
таблицы
можно
Оператор CREATE TABLE создает таблицу в базе данных. Синтаксис оператора CREATE TABLE выглядит так: CREATE TABLE {таблица} ( {поле1} {тип данных} [IDENTITY] [NOT NULL] [DEFAULT {значение по умолчанию}] [{ограничение поля}], {поле2} {тип данных} [NOT NULL] [DEFAULT {значение по умолчанию}] [{ограничение поля}], ... CONSTRAINT {ограничения таблицы} ) Параметр IDENTITY указывает, что поле будет содержать сгенерированные
системой
последовательные
значения,
уникально
идентифицирующие каждую запись таблицы. Конструкция
NOT
NULL
используется
для
запрещения
возможности ввода в поле пустых значений. Следует отличать пустое значение NULL, ноль, пробел и символьную строку нулевой длины. Пустое значение NULL показывает, что в поле не были введены какиелибо данные. Обычно пустое значение свидетельствует о том, что значение неизвестно или не определено. В целом, следует избегать возможности хранения пустых значений, так как они усложняют обработку запросов и обновлений. Если для поля разрешены пустые значения, то пустое значение может оказаться в поле в трех случаях: если при добавлении записи не указано значение для этого поля или значению поля присвоено значение NULL при выполнении запроса UPDATE или значению поля присвоено значение NULL при вводе данных. Если для поля пустые значения запрещены, то при добавлении данных в таблицу для поля должно быть указано какое-либо значение, в противном случае запись не будет добавлена в таблицу.
Иногда требуется добавить в таблицу запись, значения поля в которой пока не известно либо практически всегда одно и тоже. Для решения этой задачи рекомендуется определить для поля значение по умолчанию используя конструкцию DEFAULT. При добавлении в таблицу новой записи, если пользователь для поля не укажет никакого значения и при этом для поля запрещены пустые значения, в поле будет автоматически добавлено значение по умолчанию. Стоит обратить внимание на то, что значение по умолчанию должно быть совместимо с типом данные поля, к которому относится определение DEFAULT. Для указания поля или полей, являющихся первичным ключом таблицы, используется ограничение PRIMARY KEY. В таблице может быть лишь одно ограничение PRIMARY KEY, причем поля, входящие в первичный ключ, не допускают ввода пустых значений. Существует два способа создания ограничения PRIMARY KEY - как ограничения одного поля (если первичный ключ простой) или как ограничения таблицы (если первичный ключ простой или составной). Синтаксис применения ограничения PRIMARY KEY, как ограничения одного поля, выглядит так: {поле} {тип данных} PRIMARY KEY, ... Синтаксис
применения
ограничения
PRIMARY
KEY,
как
ограничения таблицы, выглядит так: CONSTRAINT {имя ключа} PRIMARY KEY ({поле1}, {поле2}, ...) Ограничение UNIQUE позволяет запретить ввод повторяющихся значений в поле или поля, не участвующие в формировании первичного ключа. Основное отличие ограничения UNIQUE от PRIMARY KEY состоит в том, что для одной таблицы допускается более одного ограничения UNIQUE, в то время как ограничение PRIMARY KEY может
быть лишь одно. Существует два способа создания ограничения UNIQUE как ограничения одного поля или как ограничения таблицы. Синтаксис применения ограничения UNIQUE, как ограничения одного поля, выглядит так: {поле} {тип данных} UNIQUE, ... Синтаксис применения ограничения UNIQUE, как ограничения таблицы, выглядит так: CONSTRAINT {имя ключа} UNIQUE ({поле1}, {поле2}, ...) Для указания поля или полей, используемых для создания связи между двумя таблицами, используется ограничения FOREIGN KEY. Это поле или поля должны содержать значения или первичного ключа из второй таблицы, или поля (полей) с ограничением UNIQUE. В таблице может быть несколько ограничений FOREIGN KEY. Поля с ограничением FOREIGN KEY могут содержать пустые значения. Внешний ключ может также ссылаться на поля этой же таблицы. Существует два способа создания ограничения FOREIGN KEY - как ограничения одного поля или как ограничения таблицы. Синтаксис применения ограничения FOREIGN KEY, как ограничения одного поля, выглядит так: {поле} {тип данных} FOREIGN KEY REFERENCES {вторая таблица} ({поле во второй таблице}) ON DELETE {опция внешнего ключа}, ... Синтаксис
применения
ограничения
ограничения таблицы, выглядит так:
FOREIGN
KEY,
как
CONSTRAINT {имя ключа} FOREIGN KEY ({поле1}, {поле2}, ...) REFERENCES {вторая таблица} ({поле1 во второй таблице}, ...) ON DELETE {опция внешнего ключа} Возможные опции внешнего ключа, определяющие, что происходит при удалении записи, имеющей связанные записи: • NO ACTION - удаление завершается ошибкой. • CASCADE - связанные записи также удаляются. • SET NULL - в связанных записях поля внешнего ключа получают значение NULL. • SET DEFAULT - в связанных записях поля внешнего ключа получают значение по умолчанию. Ограничение CHECK используется для ограничения значений, которые разрешено ввести в поле. Этим оно похоже на ограничение FOREIGN KEY. Отличие заключается в способе определения допустимых значений. Ограничение FOREIGN KEY получает список допустимых значений из другой таблицы, а ограничение CHECK определяет их на основе логического выражения. К одному полю разрешается применить несколько ограничений CHECK, которые проверяются в порядке их создания. Можно также создать ограничение CHECK для нескольких полей, если определить его на уровне таблицы. Синтаксис применения ограничения CHECK, как ограничения одного поля, выглядит так: {поле} {тип данных} CHECK ({условие}), ... Синтаксис применения ограничения CHECK, как ограничения таблицы, выглядит так: CONSTRAINT {имя ограничения} CHECK ({условие})
2.5.2 Оператор ALTER TABLE Оператор ALTER TABLE изменяет существующую таблицу в базе данных. С помощью этого оператора можно добавить или удалить поле в таблице, добавить или удалить ограничение. Для добавления в таблице поля или полей используется следующий синтаксис оператора ALTER TABLE: ALTER TABLE {таблица} ADD {поле1} {тип данных} [NOT NULL] [DEFAULT {значение по умолчанию}] [{ограничение поля}], {поле2} {тип данных} [NOT NULL] [DEFAULT {значение по умолчанию}] [{ограничение поля}], ... При добавлении нового поля нельзя указать ограничение NOT NULL без указания значения по умолчанию. Для удаления в таблице поля или полей используется следующий синтаксис оператора ALTER TABLE: ALTER TABLE {таблица} DROP COLUMN {поле1}, {поле2}, ... Для добавления в таблице ограничения используется следующий синтаксис оператора ALTER TABLE: ALTER TABLE {таблица} ADD CONSTRAINT {ограничение поля или таблицы}, Для удаления в таблице ограничения используется следующий синтаксис оператора ALTER TABLE:
ALTER TABLE {таблица} DROP CONSTRAINT {ограничение}
2.5.3 Оператор DROP TABLE Оператор DROP TABLE удаляет существующую таблицу из базы данных. Синтаксис оператора DROP TABLE выглядит так: DROP TABLE {таблица}
2.6.1 Оператор GRANT Оператор GRANT используется для назначения разрешений на выполнения пользователю
операций или
с
группе
объектом
базы
пользователей.
данных Несколько
определенному упрощенный
синтаксис этого оператора выглядит следующим образом: GRANT {разрешения} [ON {таблица}] TO {пользователь} В качестве разрешения можно указывать как операторы языка определения данных, так и языка манипулирования данными. Если нужно предоставить все допустимые разрешения, следует воспользоваться разрешением ALL. Можно определить разрешения как для всей таблицы, так и для ее отдельных полей (только разрешения SELECT и UPDATE). Для указания разрешений для отдельных полей используется следующий синтаксис: GRANT SELECT({поле1}, {поле2},...), UPDATE({поле1}, {поле2},...) ON {таблица}
TO {пользователь} Управление
разрешениями
значительно
упрощается
с
использованием ролей. Преимущества использования ролей заключается в следующем: • упрощается работа по предоставлению разрешений; • упрощается механизм изменения разрешений; • повышается производительность системы за счет сокращения количества проверок отдельных разрешений. Рекомендуется на этапе формирования политики безопасности распределить всех пользователей по группам с одинаковыми правами доступа к данным и для каждой группы определить свою роль.
2.6.2 Оператор REVOKE Оператор REVOKE используется для снятия разрешений на выполнения пользователю
операций или
с
группе
объектом
базы
пользователей.
данных Несколько
синтаксис этого оператора выглядит следующим образом: REVOKE {разрешения} [ON {таблица}] FROM {пользователь}
определенному упрощенный
3. Объекты баз данных 3.1 Представления Представление (view) - временная таблица, сформированная из результирующего
набора
оператора
SELECT.
Запрос
SELECT,
определяющий представление, может ссылаться на одну или несколько таблиц и представлений из базы данных. В других операторах SQL допустимо ссылаться на представление, как на обычную таблицу. Представление хранит только текст запроса SELECT, но не сами данные. Всякий раз при обращении к представлению выполняется запрос SELECT и его результирующий набор становится содержанием представления. Оператор CREATE VIEW создает представление в базе данных. Синтаксис оператора CREATE VIEW выглядит так: CREATE VIEW {имя представления} AS {запрос SELECT} Оператор DROP VIEW удаляет представление из базы данных. Синтаксис оператора DROP VIEW выглядит так: DROP VIEW {имя представления} Основные функции представлений: • ограничение доступной пользователю области таблицы определенными полями или записями; • объединение данных из нескольких таблиц и представление их в виде одной временной таблицы; • замена детальных данных, расположенных в таблицах, сводными данными;
• упрощение структуры запросов к базе данных за счет замены одного сложного запроса SELECT на несколько простых запросов SELECT, сохраненных в виде представлений. К созданному представлению можно не только обращаться за получением данных с помощью запроса SELECT, но также возможно с некоторыми
ограничениями
выполнять
обновление
данных
в
представлении с помощью запросов INSERT, UPDATE и DELETE. Чтобы можно было обновлять данные в представлении представление должно удовлетворять следующим ограничениям: •
основываться только на одной таблице;
•
содержать первичный ключ таблицы;
•
не содержать в своем определении групповые функции;
•
не использовать конструкцию GROUP BY.
3.2 Хранимые процедуры Хранимая процедура представляет собой подпрограмму на языке SQL. Хранимые процедуры позволяют повысить производительность, расширяют возможности программирования и поддерживают функции безопасности, недоступные при использовании команд SQL, отсылаемых для обработки на сервер. Повышается производительность - за счет локального (по отношению к базе данных) хранения и прекомпиляции исходного
текста
процедуры.
Возможности
программирования
расширяются благодаря применению таких распространенных средств программирования, как использование входных и выходных параметров, а также поддержке многократного использования уже созданных хранимых процедур. Функции безопасности реализуются через разрешения на использование процедуры только определенными пользователями. В результате
пользователи
получают
лишь
ограниченный
доступ
к
внутренней структуре базы данных, а для выполнения манипуляции с данными обращаются к хранимым процедурам. Оператор CREATE PROCEDURE создает хранимую процедуру в базе данных. Синтаксис оператора CREATE PROCEDURE выглядит так: CREATE PROCEDURE {имя хранимой процедуры} [ {@параметр1} {тип данных} [OUTPUT], {@параметр2} {тип данных} [OUTPUT], ... ] AS {текст хранимой процедуры} Оператор DROP PROCEDURE удаляет хранимую процедуру из базы данных. Синтаксис оператора DROP PROCEDURE выглядит так: DROP PROCEDURE {имя хранимой процедуры} Оператор
3.3 Триггеры Обеспечение целостности данных имеет решающее значение для поддержания точности и согласованности базы данных. Триггеры представляют собой особый вид хранимых процедур, привязанных в таблицам и представлениям и автоматически срабатывающих при добавлении, удалении или изменении данных. Прежде чем реализовывать триггер, следует выяснить, нельзя ли получить аналогичные результаты с
использованием ограничений. Триггеры применяются в следующих случаях: 1. если требуется реализовать сложные ограничения на данные; 2. если необходимо каскадное изменение через связанные таблицы в базе данных; 3. если
база
данных
денормализована
и
требуется
способ
автоматизированного обновления избыточных (дублирующих) данных в нескольких таблицах; 4. если
требуется
вывод
пользовательских
сообщений,
журналирование проводимых пользователем операций с данными или сложная обработка ошибок. Для создания триггера используется конструкция следующего вида: CREATE TRIGGER {имя триггера} ON {имя таблицы} FOR {тип события для обработки} AS {текст триггера} При создании триггера следует задать тип события, вызывающего его срабатывание. Типов события три: INSERT, UPDATE, DELETE. Один и тот же триггер может срабатывать на одно, два или все три события. Конструкция AS и следующие за ней команды языка SQL определяют задачу, которую будет выполнять триггер. При срабатывании триггера на события INSERT, UPDATE или DELETE создается одна или две псевдотаблицы (также известных как логические таблицы). Существует два типа логических таблиц: INSERTED и DELETED. INSERTED создается в результате события добавления или обновления данных. В ней находится набор добавленных или измененных записей. DELETED создается в результате удаления или обновления данных. В случае удаления данных в ней находятся удаленные записи, а в случае обновления данных в ней находятся обновленные записи в том
состоянии, в каком они были до операции обновления. Для определения того, значение какого поля записей было изменено при обновлении данных,
используется
конструкция
IF
UPDATE({имя
поля}).
UPDATE({имя поля}) возвращает TRUE, если поле было изменено, и FALSE в противном случае. Необходимо обратить внимание на тот факт, что при выполнении триггера таблица, для которой был создан триггер, уже содержит добавленные и измененные записи и не содержит удаленные записи. Для отмены добавления, удаления или изменения данных в триггере необходимо вызвать оператор отката транзакции ROLLBACK TRAN.
3.4 Транзакции и блокировки Типы
управления
одновременным
доступом
нескольких
пользователей к данным: • пессимистическое - в одно и тоже время просматривать и изменять данные может только один пользователь. • оптимистическое - в одно и тоже время просматривать данные могут несколько пользователей, но изменять данные может только один пользователь. Оба
типа
управления
одновременным
доступом
к
данным
используют в своей работе блокировки данных. Блокировка - это объект, с помощью которого показывается зависимость пользователя от какого-либо ресурса.
Система
управления
блокировками
запрещает
другим
пользователям выполнять над ресурсами операции, негативно влияющие на зависимость пользователя, владеющего блокировкой, от этого ресурса. Блокировка создает временное ограничение на выполнение некоторых операций обработки тех данных, от которых зависит пользователь. Основные типы блокировок:
• разделяемая (shared, S) - накладывается при выполнении операций чтения данных (например, SELECT). Никакая другая транзакция не сможет изменить или удалить данные, если на них установлена разделяемая
блокировка.
Разделяемая
блокировка
обычно
освобождается после завершения чтения данных, но если только уровень изоляции транзакции установлен в REPEATABLE READ или выше, то разделяемая блокировка сохраняется до завершения транзакции. • монопольная (exclusive, X) - накладывается при выполнении операций изменения данных (например, UPDATE). Никакая другая транзакция не сможет ни изменить, ни даже прочитать данные, если на них установления монопольная блокировка. Исключение: прочитать данные с установленной монопольной блокировкой возможно, если только уровень изоляции транзакции установлен в READ UNCOMMITTED. Монопольная блокировка освобождается после завершения транзакции. Для просмотра установленных блокировок в Microsoft SQL Server используется системная хранимая процедура sp_lock. Транзакция - последовательность операций, выполняемая как целостная логическая единица работы. Свойства транзакции: • атомарность - в транзакции выполняются или все входящие в нее операции, или ни одна. • согласованность - после завершении транзакции все данные должны находится в согласованном состоянии. • изоляция - модификации, выполняемые транзакцией, должны быть изолированы от модификаций, параллельно выполняемых другими транзакциями. • устойчивость - по завершении транзакции ее результат должен сохраниться в системе в любом случае.
Оператор BEGIN TRAN используется для начала транзакции. Для завершения транзакции используется либо оператор COMMIT TRAN (используется в том случае, если транзакция завершается успешно и все действия, выполнении в рамках транзакции должны быть сохранены в базе данных), либо оператор ROLLBACK TRAN (используется в том случае, если транзакция завершается с ошибками и все действия, выполнении в рамках транзакции должны быть отменены). Синтаксис транзакции выглядит так: BEGIN TRAN {операторы SQL} {если ошибок не было} COMMIT TRAN {иначе, если возникли ошибки} ROLLBACK TRAN Управление транзакциями осуществляется на уровне соединения, а не пользователя. После начала транзакции в соединении и до ее успешного или неуспешного завершения все выполненные в этом соединении операторы SQL становятся частью транзакции. При одновременном выполнении двух транзакций, обращающихся к одним и тем же данным, могут возникать следующие проблемные ситуации: o потерянные обновления - появляются при выборе одной записи двумя или более транзакциями, которые затем обновляют эту запись на основе ее первоначального значения. Ни у одной из транзакций нет сведений о действиях, выполненных другими транзакциями, поэтому последнее обновление записывается поверх обновлений, сделанных другими транзакциями, что приводит к потере данных.
o грязное чтение - возникает в том случае, когда первая транзакция читает данные, которые обновила, но еще не зафиксировала вторая транзакция. Таким образом, первая транзакция читает еще не зафиксированные
данные,
изменения
которых
могут
быть
отменены во второй транзакции. o неповторяемое чтение - возникает, когда первая транзакция несколько раз обращается к одним и тем же данным, однако данные меняются вследствие того, что между обращениями вторая транзакция обновляет данные и фиксирует. o чтение фантомов - появляется в том случае, когда записи из диапазона записей, читаемого в первой транзакции, добавляются или удаляются второй транзакцией. Для управления взаимодействия транзакций между собой и, соответственно, управлением блокировками данных, возникающими при выполнении
транзакций,
используется
установка
уровня
изоляции
транзакции. Уровень изоляции транзакции определяет, какие блокировки накладываются на данные, обрабатываемые в рамках транзакций. Оператор SET TRANSACTION ISOLATION LEVEL используется для изменения уровня изоляции транзакции. Синтаксис оператора SET TRANSACTION ISOLATION LEVEL выглядит так: SET TRANSACTION ISOLATION LEVEL {уровень изоляции} В языке SQL допустимы следующие уровни изоляции транзакции: 1. READ UNCOMMITTED (неподтвержденное чтение) - транзакция с этим уровнем изоляции может читать записи, которые были изменены, но еще не зафиксированы другой транзакцией. 2. READ COMMITTED (подтвержденное чтение) - транзакция с этим уровнем изоляции может читать только те записи, которые были изменены и уже зафиксированы другой транзакцией.
3. REPEATABLE READ (повторяемое чтение) - транзакция с этим уровнем изоляции может читать только те записи, которые были изменены и уже зафиксированы другой транзакцией, и никакая другая транзакция не может изменить записи, которые были прочитаны в рамках этой транзакции. 4. SERIALIZABLE (упорядочение) - транзакция с этим уровнем изоляции может читать только те записи, которые были изменены и уже
зафиксированы
другой
транзакцией;
никакая
другая
транзакция не может изменить записи, которые были прочитаны в рамках этой транзакции и никакая другая транзакция не может добавить или удалить записи из диапазона записей, прочитанного в рамках этой транзакции.
Взаимоблокировка - возникает тогда, когда две или более транзакции, конкурирующих за ресурс, становятся взаимозависимыми. Для того, чтобы избежать появления взаимоблокировок, следует не изменять порядок обращения к ресурсам в рамках транзакций.
3.5 Индексы Индексы используются для быстрого поиска нужных записей в таблицах базы данных. Существует два типа индексов: кластерные и некластерные. Структура обоих типов индексов - B-дерево (Balanced tree, сбалансированное дерево). На листовом уровне B-дерева кластерный индекс содержит записи таблицы, а некластерный - указатели на записи. У таблицы может быть только один кластерный индекс, т.к. ключ кластерного индекса физически упорядочивает таблицу. Этот тип индексов особенно эффективен при выполнении запросов, поскольку записи хранятся на листовом уровне B-дерева. Порядком сортировки и местом хранения кластерный индекс напоминает словарь с его алфавитным порядком сортировки слов и наличием определений после каждого слова. Если кластерный индекс у таблицы всегда один, то некластерных индексов для таблицы может быть создано несколько. Некластерный индекс напоминает предметный указатель, где у каждого элемента проставлена соответствующая ему страница. Помимо типа (кластерный или некластерный), индекс имеет ряд других свойств: • уникальный - в нем не допускается дублирования ключей; • составной - ключ такого индекса состоит из нескольких полей. Если результат запроса можно получить из индекса, без обращения к лежащей в его основе таблицы, то такой запрос считается покрытым, а индекс - покрывающим. При создании индекс упорядочивается по возрастанию. Это касается как кластерных, так и некластерных индексов. Кластерный индекс определяет порядок сортировки таблицы. Оператор CREATE INDEX используется для создания индекса. Синтаксис оператора CREATE INDEX выглядит так:
CREATE [UNIQUE] [CLUSTERED|NONCLUSTERED] INDEX {индекс} ON {таблица} (список полей) Оператор DROP INDEX используется для удаления индекса. Синтаксис оператора DROP INDEX выглядит так: DROP INDEX {индекс}
4. Языки HTML И DHTML 4.1 История и стандарты языка HTML HTML (HyperText Markup Language - язык разметки гипертекста) является стандартным языком, используемым для разметки и оформления гипертекстовых документов. Под разметкой документа понимается описание его структуры. С помощью гипертекстовых ссылок описывается взаимосвязь между различными документами. Язык HTML также содержит достаточное количество возможностей по определению того, как гипертекстовый документ должен выводится на то или иное устройство вывода информации. Возможность
применения
гипертекста
была
предсказана
Ванневаром Бушем в 1945 году, а термин "гипертекст" впервые был введен Тедом Нельсоном в 60-х годах прошлого века. Предшественником языка HTML был язык SGML (Standard Generalized Markup Language стандартный обобщенный язык разметки), прошедший стандартизацию в 1986 году. Стандарт языка SGML определяет синтаксис записи элементов разметки (тегов) и их атрибутов, а также правила определения новых тегов и указания структурных отношений между ними. На его основе в 1991 году
Тим
Бернерс-Ли
разработал
язык
разметки
гипертекстовых
документов HTML, который предназначался для передачи гипертекстовой информации через Internet посредством протокола HTTP (HyperText Trasport Protocol – протокол передачи гипертекста). Первый стандарт языка HTML был принят в 1995 году консорциумом World Wide Web Consortium (W3C). Этот стандарт называется HTML 2.0. В 1997 году был принят новый стандарт HTML 3.2. В этом стандарте для форматирования гипертекста предлагалось использовать каскадные таблицы стилей
(Cascading Style Sheets, CSS). Последний стандарт языка HTML был принят в 1999 году и называется HTML 4.0.
4.2 Структура страницы на языке HTML Теги записываются с использованием угловых скобок и бывают одиночные (например, ) и парные (например, ...). Каждый тег состоит из имени (обязательный элемент), набора атрибутов (свойств), описывающих отображение и поведение тега и текстовой информации (только для парных тегов). Одиночные тег записывается следующим образом: <имя атрибут=значение атрибут=значение> Парные тег записывается следующим образом: <имя атрибут=значение атрибут=значение> текстовая информация имя> Для вставки комментариев на странице HTML используется следующая запись: . Структура страницы на языке HTML: Название страницы Содержимое страницы
Парный тег используется для определения заголовка страницы, описывающего страницу в целом с помощью специальных тегов. В заголовке практически всегда используется парный тег для указания названия страницы, отображаемого в заголовке окна браузера. В заголовке страницы часто используется одиночный тег <meta> для описания различных атрибутов страницы, например: a. кодировка
символов,
использованная
при
подготовке
документа; <meta http-equiv="content-type" content="text/html; charset=кодировка символов"> b. список ключевых слов, по которым эту страница будут находить поисковые системы Интернет; <meta name="keywords" lang="обозначение языка ключевых слов" content="ключевые слова"> c. сведения об авторах; <meta name="author" content="автор(ы)"> d. название программы, при помощи которой была создана страница (добавляется автоматически); e. отмена кэширования страницы. <meta http-equiv="expires" content="Дата устаревания страницы"> Парный тег используется для определения тела страницы, отображаемое во внутренней области окна браузера.
4.3 Каскадные таблицы стилей Каскадные таблицы стилей (Cascading Style Sheets, CSS) - способ оформления страниц HTML, позволяющий с помощью параметров стиля определить отображение содержимого тега. Основные параметры стилей:
• border - рамка вокруг содержимого тега. Возможные значения: ширина границы в стандартных единицах (обычно пикселях: 1px), стиль границы (сплошная solid, точечная dotted, штриховая dashed, отсутствующая none), цвет границы (название цвета или RGB-код цвета). • color - цвет текста. Возможные значения: название цвета (black, red, green, yellow) или RGB-код цвета (#00fac3). • display - показ содержимого тега. Возможные значения: inline (содержимое тега отображается); none (содержимое тега не отображается и место на экране не резервируется). • font-family - шрифт текста. Возможные значения: название шрифта (Arial, Times New Roman) или название семейства шрифтов (Times, Courier). • font-size - размер шрифта. Возможные значения: размер шрифта в стандартных единицах (пунктах: 12pt, миллиметрах: 12mm, пикселях: 12px), в абсолютных единицах (small, medium, large), в относительных единицах (smaller, larger). • font-weight
-
полужирное
начертание
шрифта.
Возможные
значения: normal или bold. • font-style - курсивное начертание шрифта. Возможные значения: normal или italic. • left - отступ слева содержимого тега. Возможные значения: отступ в стандартных единицах (пунктах: 12pt, миллиметрах: 12mm, пикселях: 12px). • margin - граница вокруг содержимого тега. Возможные значения: ширина
границы
в
стандартных
единицах
(пунктах:
12pt,
миллиметрах: 12mm, пикселях: 12px). • padding - отступ между содержимым тега и рамкой вокруг содержимого тега. Возможные значения: отступ в стандартных единицах (пунктах: 12pt, миллиметрах: 12mm, пикселях: 12px).
• position - тип позиционирования содержимого тега. Возможные значения: absolute (абсолютное позиционирование на экране с использованием
параметров
стиля
top
и
left),
relative
(относительное позиционирование согласно обычным правилам HTML),
static
(какое-либо
специальное
позиционирование
отсутствует и содержимое тега размещается согласно обычным правилам HTML). • text-align - выравнивание абзаца текста. Возможные значения: left (по левому краю), right (по правому краю), center (по центру), justify (по ширине). • top - отступ сверху содержимого тега. Возможные значения: отступ в стандартных единицах (пунктах: 12pt, миллиметрах: 12mm, пикселях: 12px). Предусмотрено три различных способа определения стилей: внешние таблицы стилей для нескольких страниц - определение стилей размещается в отдельном текстовом файле с расширением css. Применяется для стилей, используемых на нескольких страницах. Структура файла с таблицей стилей: <style type="text/css"> определение стилей Определить стиль можно следующим образом: 1.
указав параметры стиля для требуемого тега;
тег {параметр: значение; параметр: значение;} 2. указав параметры стиля для стилевого класса; .класс {параметр: значение; параметр: значение;} 3. указав параметры стиля для идентификатора стиля; #идентификатор {параметр: значение; параметр: значение;} Для использования в странице HTML внешнего файла таблицы стилей необходимо применить в заголовке страницы тег :
Применение стиля на странице HTML зависит от того, каким образом стиль был определен: • если параметры стиля были указаны для определенного тега, то никаких изменений на странице HTML делать не нужно; • если параметры стиля были указаны для стилевого класса, то для применения стиля к требуемому тегу на странице необходимо присвоить атрибуту class значение, равное имени стилевого класса; <тег class=класс> • если параметры стиля были указаны для идентификатора стиля, то для применения стиля к требуемому тегу на странице необходимо присвоить атрибуту id значение, равное имени идентификатора стиля (идентификатор стиля рекомендуется использовать на странице только в одном теге); <тег id=идентификатор> встраивание таблиц стилей в страницу HTML - определение стилей прописывается в заголовке страницы в парном теге <style>. Применяется для стилей, используемых только на данной странице. <style type="text/css"> определение стилей Определение и применение стилей аналогично использованию внешних таблиц стилей. встраивание
стилей
в
теги
HTML
-
определение
стиля
прописывается в атрибуте style какого-либо тега. Применяется для стилей, используемых только для данного тега на странице.
Встраивание стилей в теги HTML записывается следующим образом: <тег style="параметр: значение; параметр: значение;">
4.4 Сценарии JavaScript Динамический HTML (DHTML) представляет собой комбинацию таких web-технологий, как CSS (форматирует объекты на web-странице), JavaScript (изменяет объекты на web-странице), DOM (находит объекты на web-странице), предназначенных для увеличения интерактивности webстраниц. Каскадные таблицы стилей (CSS) определяют свойства элементов на странице. Объектная модель документа (Document Object Model, DOM) определяет иерархию всех объектов в окне браузера. С помощью JavaScript создаются простые программные коды, которые выполняются браузером на стороне клиента без обращения к web-серверу (клиентские скрипты) и управляют функционированием объектов на странице. Программный код на языке JavaScript оформляется в виде функций. Синтаксис определения функции показан ниже: <script language="JavaScript"> function [имя функции]([список параметров]){ [строки тела функции]; return [значение]; } В сценариях JavaScript можно использовать переменные, ссылаясь на них по имени. Переменные бывают глобальные (определенные вне какой-либо функции), так и локальные (определенные внутри функции).
Для объявление переменной используется следующий синтаксис: var [имя переменной]; Тип переменной
переменной определяется
при из
ее объявлении того
значения,
не указывается. которое
Тип
переменной
присваивается. Присвоить значение переменной можно при помощи оператора присваивания (=). В JavaScript различают следующие типы: • число, например 12 или 34.79; • строка, например "функция"; • логический, могут принимать только два значения - true или false; Операторы языка JavaScript повторяют общеизвестные операторы языка С. Унарные операторы: "-" - изменение знака на противоположный; "++" - увеличения значения переменной на 1; "--" - уменьшение значения переменой на 1. Бинарные операторы: "+" - сложение; "-" - вычитание; "*" - умножение; "/" - деление; "%" - вычисление остатка от деления. Операторы отношения: ">" - больше; ">=" - больше или равно; "<" меньше; "<=" - меньше или равно; "==" - равно; "!=" - не равно. Логические операторы: "||" - логическое ИЛИ; "&&" - логическое И; "!" - логическое отрицание. Кроме обычного оператора присваивания "=", в языке JavaScript, так же как и в С, можно использовать операторы присваивания со сложением "+=", с вычитанием "-=", с умножением "*=", с делением "/=", с вычислением остатка от деления "%=". Условный оператор языка JavaScript повторяет условный оператор языка С. Общий вид условного оператора следующий: if ([условие]){ [операторы] } else{ [операторы] }
Операторы цикла языка JavaScript также повторяют аналогичные операторы языка С. Общий вид цикла со счетчиком следующий: for ([инициализация счетчика]; [условие]; [обновление счетчика]){ [операторы] } Общий вид цикла с условием следующий: while ([условие]){ [операторы] } Модель DOM позволяет находить адрес для различных элементов на странице. Затем, зная адрес элемента, с помощью JavaScript можно изменить те или иные свойства объекта или определить его реакцию на то или иное событие. Для идентификации объекта на странице (определения его идентификатора) используется атрибут тега ID, значение которого должно быть уникально в пределах страницы. Также в модели DOM определены два важных объекта - document и window. Объект document представляет собой страницу в окне браузера и используется для доступа к объектам на странице, их изменению, добавлению и удалению. Объект window представляет собой окно браузера и предоставляет возможность доступа к странице, загруженной в браузер, информации о браузере и событиях в окне браузера. Событиями называются какие-либо действия в окне браузера, инициатором которых обычно является пользователь. Перечень событий, которые используются чаще всего: • onload - происходит после загрузки объекта; • onunload - происходит при выгрузки объекта;
• onfocus - происходит при получении элементом фокуса ввода; • onblur - происходит при потере элементом фокуса ввода; • onmouseover - происходит при попадании указателя мыши в область, занимаемой элементом; • onmouseout - происходит при выходе указателя мыши из области, занимаемой элементом; • onclick - происходит при щелчке мышью на области, занимаемой элементом; • onmousedown - происходит при нажатии кнопки мыши на области, занимаемой элементом; • onmouseup - происходит при отпускании кнопки мыши на области, занимаемой элементом; • onmousemove - происходит при перемещении мыши над областью, занимаемой элементом; • onkeydown - происходит при нажатии клавиши на клавиатуре; • onkeyup - происходит при отпускании клавиши на клавиатуре; • onkeypress - происходит при нажатии и отпускании клавиши на клавиатуре. Обработчик события (event handler) позволяет определить действия, связанные с каким-либо событием. Для создания обработчика события необходимо указать в качестве атрибута тега имя события и либо функцию JavaScript, вызываемую при наступлении события, либо код на языке JavaScript. Синтаксис обработчика события следующий: <тег событие="функция JavaScript()"> или <тег событие="код на JavaScript"> Для получения доступа к объекту на странице необходимо либо сослаться
на
его
идентификатор,
либо
воспользоваться
методом
getElementByID объекта document, в качестве параметра которого указывается идентификатор объекта, заключенный в кавычки. Для изменения атрибута объекта необходимо присвоить ему требуемое значение. ID.атрибут=значение; или var obj=document.getElementByID("ID"); obj.атрибут=значение; Для изменения параметра стиля объекта необходимо использовать атрибут style, после которого указывается имя параметра стиля. ID.style.параметр=значение; или var obj=document.getElementByID("ID"); obj.style.параметр=значение; Для
передачи
информации
о
событии
функции
JavaScript,
вызываемой при обработке событий, необходимо указать параметр функции с именем event. Используя объект event можно определить объект, для которого произошло событие, состоянии клавиш клавиатуры в момент события, положении курсора мыши и состоянии клавиш мыши. <тег событие="функция JavaScript(event)"> Для вывода сообщений на экран можно воспользоваться функцией языка JavaScript alert: alert("текст сообщения"); В браузере Internet Explorer можно также вывести сообщение в статусную строку окна, используя свойство status объекта window:
window.status="текст сообщения"; Для определения размеров объекта на странице, его положения, видимости,
перекрывания
с
другими
объектами,
необходимо
воспользоваться моделью DOM. Для изменения ширины и высоты объекта используются свойства style.width и style.height. Для изменения положения верхнего левого угла объекта используются свойства style.top и style.left. Для изменения трехмерного положения объекта используется свойство style.zIndex. Для управления видимостью объекта используются свойство style.visibility со значениями visible или hidden или свойство style.display со значениями none, inline или block. Модель DOM позволяет динамически изменить стилевой класс объектов на странице. Для этой цели используется свойство className объекта. Для определения и изменения содержимого объекта на странице необходимо использовать свойства innerHTML и innerText объекта. Разница между этими свойствами заключается в том, что свойство innerText предоставляет доступ только к текстовому содержимому объекта, в то время как свойство innerHTML позволяет изменять содержимое объекта на языке HTML.
5. Язык C# 5.1 Платформа .NET Предшественником платформы .NET была модель компонентных объектов COM (Component Object Model), появившаяся в 1992 году. Технология COM предназначена для упрощения создания сложных приложений и основывается на создании компонентов, которые могут быть написаны на разных языках программирования, помещены в динамические загружаемые библиотеки (DLL) и затем использованы в других приложениях. Недостатки COM: • отсутствие полной совместимости компонентов, разработанных на разных языках программирования; • требование совместимости на двоичном уровне ограничивает использование
технологии
COM
операционными
системами
Windows; • сложности в установке приложений и конфликты между старыми и новыми версиями компонентов; • отсутствие контроля корректного освобождения оперативной памяти при выполнении приложения ("утечка памяти"); • невозможность в полной мере использовать несколько языков программирования при разработке сложных приложений. Преимущества .NET: • полные возможности взаимодействия с существующим кодом; • полноценное использование несколько языков программирования при разработке сложных приложений; • общая среда выполнения для всех приложений вне зависимости от языка программирования, на котором разработано приложение;
• библиотека базовых классов, которая обеспечивает сокрытие всех сложностей, связанных
с непосредственным
использованием
вызовов большинства прикладных API; • упрощение установки приложений методом копирования файлов и отсутствие конфликтов между старыми и новыми версиями компонентов. Первая версия .NET Framework 1.0 появилась в 2001 году. В 2003 году вышла следующая версия .NET Framework 2.0. В конце 2006 года появилась версия .NET Framework 3.0, являющейся неотъемлемой частью операционной системы Windows Vista. Модули DLL или EXE, скомпилированные для платформы .NET, называются сборками (assembly). Внутри сборок находится программный код на языке IL (Microsoft Intermediate Language). Программный код на языке IL является не зависящим от аппаратно-программной платформы, что позволяет создавать кросс-платформенные приложения. Кроме того, компиляция исходных текстов приложений, написанных на любом языке программирования,
в
код
IL
является
основой
совместимости
компонентов, написанных на разных языках программирования. Помимо инструкций IL, сборки содержат также метаданные, которые подробно описывают типы, определенные в сборке, и саму сборку (эта часть метаданных называется манифестом). В манифесте содержится информация о текущей версии сборки, об использованных ограничениях по безопасности, о поддерживаемом естественном языке (английском, русском и т. д.), а также список всех внешних сборок, которые потребуются для нормального выполнения. Поскольку в сборках содержится платформенно-независимый код на языке IL, а выполняются в конечном итоге платформенно-зависимые инструкции, необходимо использование компиляции времени выполнения (just-in-time compiler, JIT). Откомпилированные из IL платформенно-
зависимые инструкции JIT помещает в кэш-память, что ускоряет работу приложения. .NET Framework состоит из двух частей - среды выполнения CLR (Common Language Runtime) и библиотеки базовых классов BCL (Base Class Library). Ядро среды выполнения реализовано в виде библиотеки "C:\Windows\system32\mscoree.dll". При обращении к приложению .NET mscoree.dll автоматически загружается в память, и, в свою очередь, эта библиотека управляет процессом загрузки в память сборки данного приложения. Ядро среды выполнения ответственно за множество задач. Оно
занимается
поиском
физического
местонахождения
сборки,
обнаружением внутри сборки запрошенного типа (класса, интерфейса, структуры и т. п.) на основе информации метаданных, компилирует IL в платформенно-зависимые инструкции, выполняет проверки, связанные с обеспечением безопасности и т.д. Библиотека базовых классов разбита на множество отдельных сборок,
однако
главная
сборка
представлена
файлом
"C:\Windows\Microsoft.NET\Framework\версия\mscorlib.dll". В библиотеке базовых классов содержится огромное количество типов для решения распространенных задач при создании приложения. Приложение .NET будет
обязательно
использовать
сборку
mscorlib.dll
и
по
мере
необходимости — другие сборки. Стандартная система типов (Common Type System, CTS) — это формальная спецификация, которая определяет, как какой-либо тип (класс, структура, интерфейс, встроенный тип данных и т. п.) должен быть определен для его правильного восприятия средой выполнения .NET. CTS определяет синтаксические конструкции, которые могут поддерживаться, а могут и не поддерживаться конкретным языком программирования .NET. Если необходимо создавать сборки, которые смогут использоваться всеми языками программирования .NET, следует при создании типов следовать общеязыковым
правилам
(Common
Language
Specification,
CLS).
Необходимо понимать, что CLS - это лишь часть тех возможностей, которые
определены
в
CTS,
и
поддерживаемая
всеми
языками
программирования на платформе .NET.
5.2 Основы языка C# Структура простейшей программы на языке С#: using System; class класс { public static int Main(string[] args) { программный код return 0; } или public static void Main() { программный код } } Класс — это определяемый пользователем тип данных. Класс можно представить себе как чертеж, по которому организуются его члены. В отличие от класса объектом называется конкретный экземпляр определенного класса, с помощью которого обычно и производятся определенные действия в программе. Для создания нового объекта в С# используется ключевое слово new. Синтаксис оператора new выглядит так: класс переменная=new класс(); или класс переменная; переменная=new класс();
Ключевое слово new означает, что среде выполнения следует выделить необходимое количество оперативной памяти под создаваемый объект. Выделение памяти производится из "управляемой кучи" (managed heap). В С# переменная любого класса — это ссылка на объект в памяти, но не сам объект. При создании переменной любого класса используется конструктор класса. Конструктор класса представляет собой метод с именем, совпадающим с именем класса, и не возвращающий никакого значения. В классе могут быть определены несколько конструкторов, принимающие разное количество параметров. Если в классе явно не определен конструктор, то компилятор автоматически создает конструктор по умолчанию без параметров, в котором данные класса получают значения по умолчанию. Конструктор по умолчанию без параметров может быть также явно определен в классе (см. ниже). Для ввода-вывода информации на консоль используется класс Console. Для ввода информации используются статические методы int Read() (считывает один символ с клавиатуры) и string ReadLine() (считывает строку с клавиатуры до нажатия клавиши Enter). Для вывода информации используются статические методы void Write(string value) (выводит строку на экран) и void WriteLine(string format, params object[] args) (выводит строку на экран и переводит курсор на новую строку). Для форматирования строк используется статический метод string Format(string
format,
params
object[]
args)
класса
String.
Также
форматирование строк применяется при выводе информации на консоль (см. выше). В строке формата применяются подстановочные знаки (записываются с помощью фигурных скобок, в которых указывается порядковый номер подставляемого значения) и, если необходимо, после символа двоеточия параметры форматирования (eN - вывод числа в экспоненциальном формате с N знаками в мантиссе; fN - вывод числа с фиксированной точность с N знаками после запятой; x - вывод целого числа в шестнадцатеричном формате; c - вывод числа в денежном
формате; p - вывод числа в процентном формате с умножением числа на 100; n - вывод числа с разделителями между разрядами). Все типы в С# разделяются на две основные разновидности: структурные типы (value-based) и ссылочные типы (reference-based). К структурным типам относятся все числовые типы данных (int, float и пр.), а также перечисления (enum) и структуры (struct). Память для структурных типов выделяется из стека. При присвоении переменной одного структурного типа другой переменной происходит побитовое копирование значения первой переменной во вторую переменную. Для создания переменных структурного типа оператор new не используется (за исключением вызова конструктора с параметрами для структур). К ссылочным типам относятся классы (class) и интерфейсы (interface). Память для ссылочных типов выделяется из "управляемой кучи". При присвоении переменной одного ссылочного типа другой переменной создается еще одна ссылка, которая указывает на ту же область памяти, что и первая переменная. Для создания переменных ссылочного типа используется оператор new. В С# все типы данных (как структурные, так и ссылочные) являются производными от класса Object. Класс Object определяет общее полиморфическое поведение для всех типов данных. Определение класса Object: public class Object{ public Object(); public virtual Boolean Equals (Object obj); public virtual Int32 GetHashCode(); public Type GetType(); public virtual String ToString(); protected virtual void Finalize(); protected Object MemberwiseClone(); public static bool ReferenceEquals(Object objA, Object objB); }
Метод Equals выполняет проверку того, что сравниваемые объекты указывают на одну и ту же область памяти. Метод GetHashCode возвращает целое число, идентифицирующее конкретный объект данного типа. Метод GetType возвращает описание типа того объекта, для которого он был вызван. Метод ToString возвращает строковое представление объекта. Метод Finalize вызывается перед удалением объекта (см. ниже). Метод MemberwiseClone используется для создания еще одной ссылки на область памяти, занимаемую данным объектом. Метод ReferenceEquals выполняет проверку того, что сравниваемые объекты указывают на одну и ту же область памяти. Перечень встроенных типов языка C# и соответствующих им системных типов .NET: byte (Byte) - целое в диапазоне от 0 до 255; short (Int16) - целое в диапазоне от -32768 до 32767; int (Int32) - целое в диапазоне от -2 147 483 648 до 2 147 483 647; long (Int64) - целое в диапазоне от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807; char (Char) - один 16-битовый символ Unicode; string (String) - строка неограниченного размера символов Unicode; float (Single) - число с плавающей точкой от 10(-45) до 10(38); double (Double) - число с плавающей точкой от 10(-324) до 10(308); bool (Boolean) - логическое значение true или false; object (Object) - все, что угодно. Для объявления константы используется ключевое слово const. Цикл со счетчиком определяется следующим образом: for(инициализация счетчика; условие; изменение счетчика) тело цикла
Цикл со счетчиком прекращается в том случае, когда условие становится ложным. Цикл с предусловием записывается следующим образом: while(условие) тело цикла Цикл с предусловием прекращается в том случае, когда условие становится ложным. Цикл с постусловием записывается следующим образом: do тело цикла while(условие); Цикл с постусловием прекращается в том случае, когда условие становится ложным. Цикл с массивом записывается следующим образом: foreach(элемент массива in массив) тело цикла Цикл с массивом прекращается в том случае, когда будет закончен перебор всех элементов массива. Во всех циклах можно применять операторы break и continue. Для проверки условия используется следующая конструкция: if (условие) условие истинно else условие ложно Для множественной проверки значения переменной используется следующая конструкция:
switch(переменная){ case значение 1: код для значения 1 break; case значение 2: код для значения 2 break; default: код для значения по умолчанию } Массив — это набор элементов одного типа, доступ к которым производится с помощью числового индекса. В С# массивы могут быть простыми или многомерными. Массивы объявляются путем помещения квадратных скобок после указания типа данных для элементов этого массива. Синтаксис объявления массива: тип[] массив=new тип[количество элементов]; или тип[] массив; массив=new тип[количество элементов]; Элементы массива могут быть инициализированы при объявлении: тип[] массив={значение, значение, ...}; Для доступа к элементу массива после его имени в квадратных скобках указывается индекс элемента. Индексация элементов массива всегда начинается с 0. Необходимо обратить внимание на то, что любой массив является производным классом от класса Array. В следствие этого любой массив в C# наследует большое количество полезных методов обработки элементов массива. Для сортировки массива используется статический метод void Sort(Array array) класса Array (для выполнения сортировки необходимо, чтобы для типа элементов массива был реализован интерфейс IComparable). Для поиска элемента массива
используется статический метод int BinarySearch(Array array, object value) класса Array (для выполнения поиска необходимо, чтобы для типа элементов массива был реализован интерфейс IComparable). Для улучшения структурирования программного кода в C# используется пространства имен. Для объявления пространства имен используется следующая конструкция: namespace имя{ определения типов } В
последующем
для
обращения
к
типу,
объявленному
в
пространстве имен, используется конструкция имя.тип. Пространства имен могут быть вложенными. Для подключения классов из какого-либо пространства имен используется конструкция using имя. Если подключено пространство имен, то можно ссылаться на тип и без указания пространства имен.
5.3 Объектно-ориентированное программирование Определение класса на языке С#: class класс { тип переменная; тип метод(аргументы) { программный код } } Определение
класса
состоит
из
определения
поля
класса
(информация, описывающая объекты данного класса) и методов класса
(действия, которые либо могут выполнять объекты данного класса, либо можно выполнять над объектами данного класса). Объектно-ориентированных подход в программирования опирается на следующие принципы: • инкапсуляция; • наследование; • полиморфизм. Инкапсуляция - способность прятать детали реализации объектов от пользователей этих объектов. Инкапсуляция, с одной стороны, позволяет скрывать от пользователя объекта детали его внутренней реализации (принцип "черного ящика"), а, с другой стороны, используется для предотвращения неконтролируемого доступа к внутренним данным объекта. Наследование - возможность создавать новые определения классов на
основе
существующих,
функциональность.
расширяя
Наследование
и
переопределяя
используется
для
их
повторного
использования кода. Наследование бывает двух видов: отношение типа "быть" (классическое наследование) и отношение типа "иметь" (включение или делегирование). Полиморфизм - поддержка выполнения нужного действия в зависимости от типа передаваемого объекта. Полиморфизм применяется для
универсальной
обработки
схожих
объектов
разных
типов.
Полиморфизм бывает двух видов: основанный на "раннем связывании" (использует механизм виртуальных методов в классах, связанных классическим наследованием) и "позднем связывании" (используется для объектов, не связанных наследованием). Для
реализации
инкапсуляции
в
языке
C#
используются
модификаторы доступа и свойства. Язык С# поддерживает следующие модификаторы доступа (модификаторы видимости): • public - поля, свойства и методы являются общедоступными.
• private - поля, свойства и методы будут доступны только в классе, в котором они определены. • protected - поля, свойства и методы будут доступны как в классе, в котором они определены, так и в любом производном класса. • internal - поля, свойства и методы будут доступны во всех классах внутри сборки, в которой определен класс. Для контроля доступа к полям класса в языке C# можно использовать свойства. Внутри класса свойство определяется в виде пары методов для присвоения значения свойств и для чтения значения свойства. Для пользователей объектов класса свойство представляется как поле класса. Синтаксис определения свойства класса: тип свойство { get { return значение; } set { поле=value; } } Метод get используется для получения значения свойства. Метод set используется для изменения значения свойства. Внутри метода set новое значение свойства передается в виде переменной value. С помощью свойств можно проверить новое значение поля, прежде, чем изменить поле; выполнить дополнительные действия при изменении или чтении поля, представить для пользователя в виде поля информацию, которая на самом деле не является полем класса. Для
реализации
классического
используется следующий синтаксис: class потомок: родитель {
наследования
в
языке
C#
} Язык C# не поддерживает множественное наследование. Для вызова в конструкторе класса-потомка конструктора класса-родителя используется ключевое слово base: class потомок: родитель { потомок(аргументы):base(аргументы){ } } Также ключевое слово base используется для вызовов методов класса-родителя из переопределенных методов в классе-потомке. Язык C# также поддерживает наследование включением. Для реализации полиморфизма, основанного на виртуальных методах, в языке C# используются ключевые слова virtual и override: class родитель { virtual метод(аргументы){ } } class потомок: родитель { override метод(аргументы){ } } Кроме того, язык C# поддерживает объявление абстрактных методов с помощью ключевого слова abstract. Абстрактные методы не содержат реализации и должны быть переопределены с помощью ключевого слова override в классах-потомках. Класс, в котором объявлен хотя бы один абстрактный метод, является абстрактным и должен быть объявлен в помощью ключевого слова abstract. Объекты абстрактного класса не могут быть созданы.
5.4 Обработка исключительных ситуаций Исключения - объекты класса Exception или его потомков, в которых передается информация об ошибках. Для
обработки
исключительных
ситуаций
используется
конструкция try/catсh, имеющая следующий синтаксис: try { программный код, при выполнении которого возможны ошибки } catch(тип переменная) { программный код для обработки ошибки указанного типа } Можно перехватывать не одно, а несколько типов исключений, если использовать несколько блоков catch. В этом случае более специфичные исключения
должны
предшествовать
более
общим
исключениям,
поскольку среда выполнения просматривает обработчики исключений по порядку. Перехватив исключение, можно получить более детальную информацию об ошибке. Свойство Message содержит краткое описание ошибки; свойство TargetSite представляет объект, в котором возникла ошибка (используя этот объект, можно получить имя метода, имя класса и имя сборки, в которой возникла ошибка); свойство InnerException возвращает следующий объект в цепочке исключений. В том случае, когда в программном коде обработки ошибки нет необходимости в получении детальной информации о произошедшей ошибке, применяется упрощенная конструкция try/catсh: try { программный код, при выполнении которого возможны ошибки }
catch { программный код для обработки ошибки указанного типа } Также можно использовать конструкцию try/catсh/finally, имеющую следующий синтаксис: try { программный код, при выполнении которого возможны ошибки } catch(тип переменная) { программный код для обработки ошибки указанного типа } finally { программный код, выполняемый вне зависимости от ошибки } В качестве типа перехватываемого исключения необходимо использовать класс Exception или его потомков. Для выбрасывания (возбуждения) исключения используется оператор throw, имеющий следующий синтаксис: throw исключение; В простейшем случае для выбрасывания общего исключения используется следующий синтаксис: throw new Exception("сообщение об ошибке"); Если необходимо повторно возбудить исключение, перехваченное в блоке catch, следует воспользоваться оператором throw без параметров.
5.5 Интерфейсы Интерфейс - это тип, определяющий набор методов и свойств без реализации, и используемый для определения классов со сходной функциональностью. Интерфейс определяется с помощью ключевого слова interface. Синтаксис определения интерфейса: interface интерфейс { тип метод(аргументы); тип свойство { get; set;} } Особенности использования интерфейсов: • все методы интерфейса по определению являются открытыми, при этом
запрещено
использовать
в
определении
методов
модификаторы доступа. • тип интерфейса можно использовать в объявлении параметров методов и переменных, но создавать объекты типа интерфейс нельзя. • вместо
изменения
уже
используемого
интерфейса
следует
воспользоваться наследованием интерфейса. Интерфейсы реализуются с помощью классов. Под реализацией классом интерфейса понимается написание в классе программного кода для каждого из объявленных в интерфейсе методов и свойств. Для реализации интерфейса необходимо: • после имени класса, реализующего интерфейс, поставьте двоеточие и напишите имя интерфейса (если в классе необходимо реализовать несколько интерфейсов, следует разделить их имена запятыми); • включите в класс все методы и свойства, определенные в интерфейсе;
• для
каждого
реализованного
метода
и
свойства
укажите
модификатор доступа public. Возможность реализации одним классов нескольких интерфейсов заменяет отсутствие множественного наследования. Для получения доступа к интерфейсу объекта применяются следующие способы: • явное приведение типа - (интерфейс)объект; • с помощью ключевого слова as - объект as интерфейс; • с помощью ключевого слова is - if (объект is интерфейс). Для реализации наследования интерфейсов в языке C# используется следующий синтаксис: interface потомок: родитель { }
5.6 Делегаты и события Делегат - класс, в котором хранится функция. В определение делегата входит прототип функций, которые могут быть представлены этим делегатом. При объявлении переменной типа делегата указывается функция, тип которой совместим с типом делегата. После этого делегат можно использовать для вызова указанной функции. Обычно делегаты используются для реализации обратных вызовов. Обратный вызов - вызов из функции A функции B, переданной в качестве параметра функции A. Обратные вызовы часто применяются для передачи из функции информации о производимых ее действиях. Объявление делегата может располагаться внутри или вне какоголибо класса и похоже на объявление функции, но с добавлением в начале ключевого
слова
delegate.
следующий синтаксис:
Для
объявления
делегата
используется
delegate тип делегат(аргументы); Возможность объявления делегата вне какого-либо класса связана с тем, что на основе строки объявления делегата компилятор фактические генерирует объявление класса, производного от MulticastDelegate. Для создания делегата необходимо объявить переменную типа делегата и с помощью ключевого слова new вызвать конструктор делегата, передав ему в качестве параметра имя функции, которая будет храниться в делегате. делегат переменная=new делегат(объект.метод); Для вызова делегата указывается имя переменной типа делегата, а затем в круглых скобках через запятую перечисляются параметры, которые надо передать функции, вызываемой через объект делегата. В основе механизма обработки событий лежат делегаты, поэтому прежде, чем объявить событие, необходимо объявить делегат. Объявление события похоже на объявление переменной типа делегата, но с добавлением в начале ключевого слова event. Для объявления события используется следующий синтаксис: event делегат событие; Чтобы сгенерировать (возбудить) событие, указывается имя события, а затем в круглых скобках через запятую перечисляются параметры события. Прежде чем возбуждать событие, рекомендуется проверить, не равна ли null переменная, описывающая событие. Для подписки на событие для какого-либо объекта используется оператор +=, после которого с помощью ключевого слова new вызывается
конструктор делегата, в качестве параметра которого указывается имя метода, представляющего из себя обработчик события. объект.событие+=new делегат(метод);
5.7 Доступ к данным Для доступа к данным на платформе .NET используется библиотека классов ADO.NET. Основу этой библиотеки составляют класс DataSet и классы, реализующие следующие основные интерфейсы: IDbConnection, IDbCommand, IDataReader, IDataAdapter. Используя ADO.NET возможно реализовать как классические клиент-серверные приложения, в которых клиентское приложение напрямую обращается к базе данных с помощью SQL-запросов, так и многоуровневые рассоединенные приложения, в которых важно иметь возможность работать с не имеющими постоянного подключения к серверу баз данных копиями данных. Главную роль в создании рассоединенных приложений играет класс Dataset, позволяющий создавать локальный набор взаимосвязанных таблиц. Также необходимо отметить, что с помощью ADO.NET можно обращаться к самым различным источникам данных. Работы с различными источниками данных реализована с помощью управляемых провайдеров (managed provider). Управляемый провайдер - набор классов, реализующих интерфейсы IDbConnection, IDbCommand, IDataReader, IDbDataAdapter и предназначенный для работы с определенным источником данных. Для работы с Microsoft SQL Server и Oracle используются провайдеры SQL и Oracle, оптимизированные для работы именно с этими СУБД. Кроме того, в состав ADO.NET включен провайдер OLEDb, позволяющий работать с любыми источниками данных, поддерживающих протокол OLE DB. Интерфейс IDbConnection (реализован в классе SqlConnection провайдера SQL) - предназначен для создания соединения (connection) с
источником данных. Для указания источника данных для создания соединения используется строка соединения (connection string). Строка соединения содержит пары "параметр=значение", разделенных символом точка с запятой. Информация, которая должна быть указана в строке соединения, зависит от источника данных. При создании соединения с Microsoft SQL Server необходимо указать значения для следующих параметров: server - имя компьютера (или его IP адрес), на котором установлен Microsoft SQL Server; uid - учетная запись пользователя Microsoft SQL Server, от имени которого создается соединение; pwd пароль учетной записи пользователя Microsoft SQL Server, от имени которого создается соединение; database - имя базы данных, с которой необходимо создать соединение. Строка соединения может быть указана при вызове конструктора объекта класса SqlConnection, либо через присвоение значения свойству ConnectionString интерфейса IDbConnection. Для открытия соединения с базой данных используется метод void Open() интерфейса IDbConnection. Для закрытия соединения с базой данных используется метод void Close() интерфейса IDbConnection. Шаблон работы с соединением: SqlConnection con = new SqlConnection("server=...;uid=...;pwd=...;database=.. ."); con.Open(); try{ ... } finally{ con.Close(); } На практике используются два варианта работы с соединением с базой данных. Если количество пользователей невелико и клиентское приложение при этом часто обращается к базе данных рекомендуется
создать один объект соединения с базой данных для всего приложения и держать
соединение открытым в течение
всего
времени работы
приложения. Если количество пользователей велико и клиентское приложение не часто обращается к базе данных, рекомендуется открывать соединение только на время выполнения запросов и использовать организацию пула соединений (connection pooling). Открытие соединения с базой данных обычно требует определенного времени и ресурсов. Пул соединений содержит коллекцию открытых соединений с базой данных. При вызове метода Open пул соединений проверяет наличие свободного соединения в пуле и возвращает его клиентскому приложению. При вызове метода Close соединение фактически не закрывается, а возвращается обратно в пул соединений. Соединения объединяются в пул соединений по признаку совпадения строки соединения. Если открывается соединение, в котором строка соединения отличается от строки, использованной в предыдущих соединениях, создается новый пул соединений. Использование пула соединений
позволяет
приложений
с
существенно
большим
повысить
количеством
производительность
одновременно
работающих
пользователей. Использование пула соединений включено по умолчанию при работе с ADO.NET. Рекомендуется выносить информацию о строке соединения во внешний файл или хранить ее в реестре. Такой подход позволяет гибко, безопасно и централизованно настраивать подключение к источнику данных. Для доступа к реестру используется класс RegistryKey. Для указания требуемой корневой ветки реестра используются статические поля
CurrentUser
и
LocalMachine
класса
Registry.
Данные
поля
применяются для инициализации переменных типа RegistryKey. Для открытия
нужной
ветки
реестра
используется
метод
RegistryKey
CreateSubKey(string subkey), который открывает существующую ветку реестра или создает новую. Для чтения значения из реестра применяется
метод object GetValue(string name). Для записи значения в реестр применяется метод void SetValue(string name,object value). Шаблон чтение значения из реестра: RegistryKey key=Registry.CurrentUser; key=key.CreateSubKey("ветка реестра"); try { value=(string)key.GetValue("параметр"); if (value == null) throw new Exception(); } catch { key.SetValue("параметр", "значение"); } Интерфейс
IDbCommand
(реализован
в
классе
SqlCommand
провайдера SQL) - предназначен для выполнения произвольных SQL запросов к базе данных. Текст SQL запроса обычно указывается при вызове конструктора объекта класса SqlCommand. Также при вызове конструктора следует указать объект соединения с базой данных. При формировании строки SQL запроса можно использовать форматирование строк с помощью статического метода Format класса String. Для выполнения SQL запроса к базе данных, который не возвращает в качестве результата набора записей, используется метод int ExecuteNonQuery()
интерфейса
IDbCommand.
При
возвращает количество записей, задействованных
вызове
метод
при выполнении
запроса. Данный метод применяется при выполнении таких запросов, как, например, INSERT, UPDATE, DELETE или выполнении содержащих их хранимых процедур, а также запросов языка манипулирования данными и языка управления данными. Шаблон выполнения метода ExecuteNonQuery: SqlConnection con; ...
SqlCommand com = new SqlCommand("текст запроса SQL",con); try{ com.ExecuteNonQuery(); } catch(Exception ex){ } Так как при выполнении запроса SQL могут возникнуть различные ошибки, рекомендуется помещать вызов метода ExecuteNonQuery в блок try-catch. Для выполнения SQL запроса к базе данных, который возвращает в качестве результата набор записей, используется метод IDataReader ExecuteReader(CommandBehavior behavior) интерфейса IDbCommand. В классе SqlCommand также определен упрощенный метод SqlDataReader ExecuteReader(). Метод ExecuteReader применяется для получения данных из базы данных, которые в клиентском приложении доступны только для чтения (read-only) и могут быть просмотрены только по порядку (forwardonly). Использование ExecuteReader особенно эффективно для получения большого
количества
данных,
поскольку
полученные
данные
не
кэшируются в оперативной памяти. Для чтение следующей записи из объекта, поддерживающего интерфейс IDataReader, используется метод bool Read() интерфейса IDataReader,
возвращающий
значение
true,
если
запись
успешно
прочитана, и false в противном случае. Необходимо обратить внимание на тот факт, что метод Read должен быть вызван до первого обращения к полям записи. Для чтения значений в полях очередной записи можно использовать метод object GetSqlValue (int i) класса SqlDataReader, в качестве параметра которого указывается номер поля (нумерация полей начинается с нуля). Также для доступа к значениям полей можно использовать индексатор по номеру или по имени поля. Шаблон выполнения метода ExecuteReader:
SqlConnection con; ... SqlCommand com = new SqlCommand("текст запроса SQL",con); try{ SqlDataReader rd = cmd.ExecuteReader(); while (rd.Read()){ for (int i = 0; i < rd.FieldCount; i++) object value=rd.GetSqlValue(i); или object value=rd[i]; } } catch(Exception ex){ } finally{ rd.Close(); } Если имена полей известны, то шаблон выполнения метода ExecuteReader может выглядеть следующим образом: SqlConnection con; ... SqlCommand com = new SqlCommand("текст запроса SQL",con); try{ SqlDataReader rd = cmd.ExecuteReader(); while (rd.Read()){ object value=rd["имя поля"]; } } catch(Exception ex){ } finally{ rd.Close(); } Рекомендуется
выносить
тексты
запросов
SQL,
которые
используются при работе с интерфейсом IDbCommand, во внешний файл или в таблицу в базе данных. Подобное решение позволяет существенно
упросить разработку и сопровождение программы. Внешний файл, хранящий тексты запросов SQL, может иметь формат XML. Для доступа к файлам в формате XML используется класс XmlDocument. Для открытия требуемого файла используется метод void Load(string filename) класса XmlDocument. Для нахождения в документе XML требуемого узла по его имени используется
метод
XmlNode
SelectSingleNode(string
xpath)
класса
XmlDocument. В качестве параметра методу SelectSingleNode передается запрос XPath, в котором указывается информация о требуемом узле. На практике часто используются следующие шаблоны запросов XPath: "//узел" - выбор узла по его имени; "//узел[@атрибут='значение']" - выбор узла по его имени и значению атрибута. Для доступа к содержимому узла применяется класс XmlNode. Информация в узле может находится в форме текстового значения узла или в форме атрибутов узла. Для доступа к текстовому значению узла используются свойства string Value{ get; set; } и string InnerText{ get; set; } класса XmlNode. Шаблон получения текстового значения узла по его имени: XmlDocument doc=new XmlDocument(); try{ doc.Load("имя файла"); XmlNode node=doc.SelectSingleNode("//имя узла"); string value=node.Value; } catch(Exception ex){ } Для
доступа
к
атрибутам
узла
используется
свойство
XmlAttributeCollection Attributes{ get; } класса XmlNode, возвращающее коллекцию объектов класса XmlAttribute. Доступ к элементам коллекции
атрибутов может производится по индексу или по имени. Для доступа к текстовому значению атрибута используется свойство string Value{ get; set; } класса XmlAttribute. Шаблон получения атрибута узла по его имени: XmlDocument doc=new XmlDocument(); try{ doc.Load("имя файла"); XmlNode node=doc.SelectSingleNode("//имя узла"); string value=node.Attributes["имя атрибута"].Value; } catch(Exception ex){ } Для XmlNodeList
доступа
к
подчиненным
ChildNodes{
get;
}
узлам используется
класса
XmlNode,
свойство
возвращающее
коллекцию объектов класса XmlNode. Шаблон перебора подчиненных узлов заданного по имени узла: XmlDocument doc=new XmlDocument(); try{ doc.Load("имя файла"); XmlNode node=doc.SelectSingleNode("//имя узла"); foreach(XmlNode child in node.ChildNodes){ string value=child.Value; } } catch(Exception ex){ } Для хранения текстов запросов SQL можно использовать файл XML со следующей структурой: <sql> текст запроса
Шаблон выполнения запроса SQL, текст которого сохранен в файле XML с приведенной выше структурой: string query; XmlDocument doc=new XmlDocument(); try{ doc.Load("имя файла"); XmlNode node=doc.SelectSingleNode("//query[@name='имя запроса']"); query=node.Value; } catch(Exception ex){ } SqlConnection con= new SqlConnection("server=...;uid=...;pwd=...;database=.. ."); con.Open(); SqlCommand com = new SqlCommand(query,con); try{ com.ExecuteNonQuery(); } catch(Exception ex){ } Интерфейс IDataAdapter (реализован в классе SqlDataAdapter провайдера SQL) - предназначен для заполнения данными из источника данных объекта DataSet и последующего обновления источника данных в соответствии со сделанными в объекте DataSet изменениями. Текст SQL запроса
для
конструктора
получения объекта
данных класса
обычно
указывается
SqlDataAdapter.
Также
при
вызове
при
вызове
конструктора следует указать объект соединения с базой данных. При формировании строки SQL запроса можно использовать форматирование строк с помощью статического метода Format класса String. Для заполнения объекта DataSet данными используется метод int Fill(DataSet
dataSet)
интерфейса
IDataAdapter.
При
вызове
метод
возвращает количество записей, переданных в объект DataSet. Шаблон выполнения метода Fill: SqlConnection con; ... DataSet data; SqlDataAdapter ad = new SqlDataAdapter("текст запроса SQL",con); try{ ad.Fill(data); } catch(Exception ex){ } Для доступа к таблице в объекте DataSet используется свойство DataTableCollection
Tables{
get;
}
класса
DataSet,
возвращающее
коллекцию объектов класса DataTable. Доступ к элементам коллекции таблиц может производится по индексу или по имени. Для доступа к требуемой записи таблицы используется свойство DataRowCollection Rows { get; } класса DataTable, возвращающее коллекцию объектов класса DataRow. Доступ к элементам коллекции записей производится по индексу. Для доступа к требуемому полю записи таблицы используется индексатор по номеру или по имени поля класса DataRow. Шаблон чтения данных объекта DataSet: DataSet data; ... for(int i=0; i < data.Tables[0].Rows.Count; i++){ for(int j=0; j < data.Tables[0].Columns.Count; j++){ object value=data.Tables[0].Rows[i][j]; } } Для изменения значений в полях таблицы в объекте DataSet необходимо присвоить новое значение полю требуемой записи.
DataSet data; ... data.Tables[0].Rows[номер записи][номер поля]=значение; data.Tables[0].Rows[номер записи]["название поля"]=значение; Для добавления новой записи в таблицу в объекте DataSet необходимо создать новую запись, вызвав метод DataRow NewRow() класса DataTable, присвоить значения полям созданной запис и добавить запись в коллекцию записей таблицы, вызвав метод void Add(DataRow row) свойства Rows класса DataTable. DataSet data; ... DataRow row=data.Tables[0].NewRow(); row["название поля"]=значение; ... data.Tables[0].Rows.Add(row); Для удаления записи из таблицы в объекте DataSet необходимо вызвать метод void Delete() класса DataRow, а затем вызвать метод void AcceptChanges() класса DataTable. DataSet data; ... data.Tables[0].Rows[номер записи].Delete(); data.Tables[0].AcceptChanges(); Для сохранения всех сделанных в объекте DataSet изменений в источник данных необходимо вызвать метод int Update(DataSet dataSet) интерфейса IDataAdapter. При вызове метод возвращает количество записей, измененных в источнике данных. DataSet data;
5.8 Разработка web-приложений Для разработки web-приложений на платформе .NET используется библиотека классов ASP.NET. Наиболее важными классами в данной библиотеке
являются
классы
HttpApplication,
HttpApplicationState,
HttpRequest, HttpResponse и Page. Web-приложение представляет собой набор взаимосвязанных файлов, расположенных в виртуальном каталоге (virtual directory) на web-сервере. Класс HttpApplication - предназначен для обработки событий, общих для всего web-приложения. Объект класса, являющего потомком HttpApplication, создается динамически во время выполнения приложения. Для обработки событий уровня приложения в проект следует добавить файл global.aspx. В файле global.aspx могут быть определены обработчики событий
запуска
и
завершения
приложения,
а
также
обработки
возникающих ошибок. Класс
HttpApplicationState
-
предназначен
для
хранения
в
оперативной памяти данных, общих для всех сеансов web-приложения. Объект класса HttpApplicationState создается динамически при первом обращении пользователя к любому ресурсу web-приложения. Доступ к объекту состояния приложения HttpApplicationState можно получить через свойство Application класса Page. Для сохранения значения в состоянии приложения используется следующий синтаксис: Application["имя значения"]=значение;
Для чтения значения из состояния приложения используется следующий синтаксис: object переменная=Application["имя значения"]; Класс HttpRequest - предназначен для чтения параметров запроса HTTP, отправленного пользователем. С помощью объекта HttpRequest можно получить информацию о переданных в запросе переменных, о возможностях браузера, используемого пользователем, об IP-адресе компьютера пользователя, о клиентских cookie и т.д. Доступ к объекту запроса HttpRequest можно получить через свойство Request класса Page. Для чтения значения, переданного в запросе HTTP методом GET или POST, используется следующий синтаксис: string переменная=Request["имя значения"]; Таким же образом можно получить доступ к значениям клиентских cookie. Класс HttpResponse - предназначен для формирования кода страницы на языке HTML (или XML), которая должна быть возвращена браузеру пользователя. Доступ к объекту запроса HttpResponse можно получить через свойство Response класса Page. Для формирования содержимого страницы используется метод void Write(string s) класса HttpResponse. Класс Page - является базовым классом для всех web-страниц приложения. При добавлении в проект новой web-страницы создается два файла с расширением *.aspx и *.aspx.cs. Файл с расширением *.aspx содержит код на языке HTML и может быть изменен либо с помощью редактора HTML, либо с помощью визуального редактора, входящего в состав Visual Studio. В заголовке файла *.aspx находятся следующая строка:
<%@ Page Language="язык" AutoEventWireup="true" CodeFile="*.aspx.cs" Inherits="класс" %> В параметре Language указывается язык, на котором будут написаны серверные обработчики событий страницы, в параметре CodeFile указывается имя файла, в котором будут написаны серверные обработчики событий страницы (расширение cs указывает на то, что программный код будет написан на языке C#), в параметре Inherits указывается имя класса, потомка класса Page, в котором будут определены серверные обработчики событий страницы. В библиотеке ASP.NET определено много различных серверных элементов управления, которые могут быть размещены на web-странице (Web server controls). Серверные элементы управления обрабатываются на сервере перед тем, как пользователь получит в браузере запрашиваемую web-страницу. При формировании кода возвращаемой web-страницы каждый серверный элемент управления преобразуется в один или несколько тегов HTML. В дополнение к стандартным серверным элементам управления можно разработать пользовательские элементы управления.