--PAGE_BREAK--1.2 Платформа Microsoft.NETFramework
Платформа Microsoft .NET Framework, предназначенная для работы приложений Microsoft .NET, дает большие преимущества разработчикам программ. В частности, она способна преодолеть барьеры языковой несовместимости, допуская создание отдельных компонентов создаваемой системы на различных языках программирования.
Среди других преимуществ Microsoft .NET Framework заслуживает упоминания наличие обширной библиотеки классов, существенно облегчающей решение задач, наиболее часто возникающих при создании автономных программ и Web-приложений.
Эта библиотека, насчитывающая десятки тысяч классов, готовых к употреблению, которые позволят использовать в своих разработках готовые и отлаженные модули.
Платформа Microsoft .NET Framework обеспечивает возможность использования модулей, разработанных программистом ранее, а также возможность обращения к новым компонентам из разработанного ранее программного кода. В результате после относительно небольших переделок старые программы смогут приобрести новую функциональность.
Приложения Microsoft .NET работают в среде Microsoft .NET Framework в рамках системы исполнения программ Common Language Runtime (CLR). Примененная в Microsoft .NET Framework концепция управляемого кода обеспечит надежное и безопасное выполнение программ, а также значительно уменьшит вероятность допущения ошибок в процессе программирования. Этому же способствует система обработки исключений и система автоматического освобождения неиспользуемой оперативной памяти, называемой системой сборки мусора (garbage collection).
Встроенные в язык С# и рассчитанные на среду Microsoft .NET Framework средства документирования, такие, как атрибуты и операторы комментариев специального вида, позволят существенно упростить создание конструкторской документации на программный код. Это особенно ценно при разработке больших проектов, когда из-за сложности и объемности задачи сопровождение разработки превращается в непосильную задачу и становится настоящим кошмаром для менеджера проекта.
В сочетании с мощным средством ускоренной разработки приложений Microsoft Visual Studio .NET набор языков платформы Microsoft .NET послужит отличным подспорьем при создании программ самого разного типа, как автономных, так и рассчитанных на использование в Интернете.
Глава 2. Приложения с базами данных и методы доступа к СУБД 2.1 Программные интерфейсы доступа к СУБД
2.1.1 Прямой вызов программного интерфейса СУБД
Как правило, СУБД любого типа, предназначенная для работы на платформе Microsoft Windows, предоставляет в распоряжение программиста интерфейс API, с помощью которого программа может выполнять все необходимые операции с базами данных. Физически этот интерфейс обычно реализован с помощью библиотек динамической компоновки DLL, экспортирующих функции доступа к СУБД.
В частности, Microsoft SQL Server предоставляет разработчикам приложений программный интерфейс DB Library —естественный интерфейс данной СУБД, реализованный как набор функций.
Следует заметить, что прямая работа приложений с программным интерфейсом СУБД может привести к проблемам при появлении новых версий этих СУБД. Компания Microsoft, например, не рекомендует использовать в новых приложениях упомянутый выше интерфейс DB Library, оставленный только для совместимости с разработанными ранее приложениями.
Кроме того, технология прямого вызова программного интерфейса СУБД недоступна для разработчиков Web-приложений, использующих так называемые серверные сценарии JavaScript и VB Script.
2.1.2 Использование программного интерфейса ODBC
Программный интерфейс ODBC, как и только что упомянутые интерфейсы прямого вызова СУБД также выполнен в виде набора функций. Это ограничивает его применение в Web-приложениях.
Однако интерфейс ODBC, созданный специально для доступа к реляционным базам данных, универсален. Это единый интерфейс, позволяющий приложениям работать с СУБД всех типов, для которых имеется так называемый драйвер ODBC.
Используя ODBC, программист может не заботиться о деталях внутреннего устройства и особенностях естественного интерфейса различных СУБД, т.к. драйвер ODBC полностью скрывает от него эти детали. В результате программы, обращающиеся к базам данных, становятся менее зависимыми от этих баз данных. К сожалению, отличия в реализации драйверов ODBC различных СУБД не всегда позволяют добиться полной независимости программ от типа СУБД.
2.2 Объектные интерфейсы СУБД
По мере развития ОС Microsoft Windows и СУБД, на смену программным интерфейсам пришли объектные интерфейсы, основанные на использовании модели компонентных объектов Component Object Model (COM).
Объекты COM можно представить себе как набор интерфейсов, через которые можно получить доступ к свойствам и методам объекта. Если Вы знакомы с классами, интерфейсами и свойствами языка C#, то эти понятия Вам тоже знакомы. Хотя с появлением платформы .NET технология COM становится устаревшей (или, как говорят, унаследованной), до сих пор она интенсивно применяется как в самой ОС Microsoft Windows, так и в приложениях, создаваемых для этой ОС.
продолжение
--PAGE_BREAK--2.2.1 Интерфейс OLE DB
Объектный интерфейс OLE DB представляет собой открытый стандарт, предназначенный для универсального доступа приложений к базам данных. В отличие от интерфейса ODBC и RDO, интерфейс OLE DB позволяет приложениям обращаться не только к реляционным БД, но и к нереляционным, таким, например, как серверы почты, базы данных для мэйнфреймов с методами доступа IMS, VSAM и т. д.
Интерфейс OLE DB состоит из трех компонентов: провайдера (provider), потребителя (consumer) и служебного компонента, выполняющего обработку и передачу данных.
В роли потребителя могут выступать приложения. Задача провайдера OLE DB — реализация интерфейса OLE DB. В составе OLE DB поставляются провайдеры для интерфейсов ODBC, для текстовых файлов и некоторые другие. Пользуясь провайдером ODBC, потребители интерфейса OLE DB могут получить доступ к базам данных через драйвер ODBC.
2.2.2 Интерфейс ActiveX Data Objects
Упомянутый выше объектный интерфейс OLE DB не реализует механизм автоматизации, в результате чего этот метод не подходит для создания Web-приложений, основанных на серверных сценариях JavaScript и VB Script.
Объектный интерфейс ActiveX Data Objects (ADO) построен на основе интерфейса OLE DB. При этом интерфейс OLE DB обеспечивает универсальный доступ к данным с помощью провайдеров, таких как Microsoft OLE DB Provider для ODBC (MSDASQL) или Microsoft OLE DB Provider для SQL Server (SQLOLEDB).
Благодаря тому, что объекты ADO реализуют средства автоматизации, интерфейс ADO доступен из приложений, составленных с применением целого спектра инструментальных средств, таких, как серверный сценарии ASP, C++, Visual Basic, Visual Basic for Applications, Java и т. д.
Ключевыми элементами программной модели ADO является набор объектов, с помощью которых выполняется соединение с базами данных, выполнение команд с параметрами, получение результата выполнения этих команд в виде переменных или наборов записей, обработка событий и ошибок.
Вот типичный сценарий работы приложения с базой данных посредством интерфейса ADO:
· установка соединения;
· подготовка команды и параметров;
· выполнение команды;
· обработка результатов выполнения команды;
· закрытие соединения;
· обработка ошибок
Прежде чем обращаться к базе данных, приложение должно установить соединение с сервером базы данных. При этом требуется указать имя источника данных Data Source Name (DSN) или информацию об источнике данных, такую как имя драйвера, имя сервера, пароль и т.д.
После установки соединения приложение должно подготовить объект-команду, записав в его свойства команды, необходимые для доступа к данным (например, строки языка SQL). Приложение может передать вместе с командой параметры. Входные параметры позволяют передавать информацию в хранимые процедуры СУБД Microsoft SQL Server, а выходные — принимать информацию из хранимой процедуры.
Когда программа инициирует выполнение команды, она получает результат в виде набора записей (Recordset) или через выходные параметры хранимой процедуры (если команда запускает такую процедуру). Приложение может просмотреть все записи из полученного набора, сохранить их в памяти или использовать каким-либо другим способом. В частности, можно обновить полученный набор записей с целью обновления источника данных (если это необходимо).
После того как команда выполнена, а результаты ее выполнения обработаны, приложение должно закрыть соединение. Большое количество незакрытых соединений может привести к чрезмерному расходованию ресурсов сервера СУБД.
В процессе подготовки параметров команды и ее выполнения могут возникать ошибки. Приложение должно быть готово их обработать.
2.3 Метод доступа ADO .NET
Рассмотренные выше методы доступа с программными и объектными интерфейсами больше всего подходят для создания так называемых клиент-серверных приложений. Такие приложения обычно открывают соединение с базой данных в начале своей работы, а закрывают — при ее завершении. Если пользователей много, то каждый из них будет во время своей работы держать как минимум одно соединение с сервером СУБД (даже во время обеденного перерыва, если клиентская программа запускается на целый день). Это отнимает немало ресурсов сервера и приводит к необходимости приобретения большого количества серверных лицензий.
2.3.1 Многоуровневые системы
С появлением Web-приложений, интегрированных с базами данных, получили развитие так называемые многоуровневые системы. В этих системах клиент (в роли которого выступает обычный браузер, такой, например, как Microsoft Internet Explorer) обращается к СУБД не напрямую, а через Web-сервер.
Такое обращение начинается с того, что бразуер направляет запрос к Web-серверу (например, для выборки данных из базы данных или обновления базы данных). Далее Web-сервер действует следующим образом:
· открывает соединение с СУБД;
· выполняет запрос, обращаясь к базе данных;
· закрывает соединение с базой данных;
· отправляет результат запроса в браузер
Браузер получает результат обработки запроса в виде текстового документа HTML и отображает его в своем окне.
Так как соединение с базой данных устанавливается только на время обработки запроса, это позволяет экономить ресурсы сервера СУБД, а также приобретать небольшое количество клиентских лицензий. Фактически клиентом СУБД в этом случае выступает Web-сервер, и только для него нужны клиентские лицензии.
продолжение
--PAGE_BREAK--2.3.2 Рассоединенные системы
Метод доступа ADO .NET, доступный приложениям на платформе Microsoft .NET, позволяет создавать разновидность многоуровневых систем — так называемые рассоединенные (disconnected) системы.
Рассоединенные системы позволяют получить локально данные, извлеченные из базы данных, выполнить их локальную обработку, а затем обновить базу данных на сервере по результатам этой обработки.
Данные, извлеченные из сервера СУБД методом ADO .NET, сохраняются в объекте класса DataSet. Этот объект может хранить в себе одновременно несколько таблиц данных, в том числе связанных между собой (related tables), а также ограничения (constraints). В частности, можно переписать в созданный локально объект DataSet содержимое всей базы данных, расположенной на сервере, если в этом возникнет необходимость.
Вот возможная схема взаимодействия клиента с сервером в рассоединенной системе, реализованной с использованием метода доступа ADO .NET:
· открытие соединения с сервером СУБД;
· отправка запроса к базе данных;
· закрытие соединения;
· обработка данных, полученных в виде объекта класса DataSet;
· открытие соединения с сервером СУБД;
· обновление базы данных с использованием содержимого объекта класса DataSet;
· закрытие соединения
2.3.3 Распределенная обработка данных и XML
Если нужно создать информационную систему с распределенной обработкой данных, встает вопрос организации взаимодействия между серверами и клиентами такой системы. Метод доступа ADO позволяет организовать такую обработку средствами COM, однако этот способ имеет определенные недостатки. Эти недостатки проявляются в тех случаях, когда нужно объединить узлы системы при помощи каналов Интернета.
Дело в том, что корпоративные интрасети, подключенные к Интернету, обычно защищаются брандмауэром (firewall), открывающим доступ только для определенных портов TCP/IP и для определенных протоколов передачи данных. Обычно открывается только порт 80, предназначенный для работы с Web-серверами посредством протокола HTTP, а также порты протоколов SMTP, POP3 и IMAP, с помощью которых осуществляется передача электронной почты. Эти ограничения обычно несовместимы с системами удаленной обработки, реализованными с использованием модели COM.
Что же касается ADO .NET, то этот метод доступа допускает представление данных в формате XML. При этом данные могут передаваться с использованием протокола HTTP, что позволяет объединять информационные системы каналами Интернета, даже если эти системы защищены брандмауэрами.
2.3.4 Провайдеры данных для управляемого кода
Программный компонент, называемый провайдером данных (data provider) выступает в качестве моста между приложением и источником данных. В его задачу входит извлечение данных из источника, а также обновление источника данных.
Для приложений, содержащих управляемый код и предназначенных для платформы Microsoft .NET, компания Microsoft разработала три провайдера данных. ЭтоSQL Server .NET Data Provider, OLE DB .NET Data Provider иODBC .NET Data Provider. Первые два из них входят в состав среды исполнения Microsoft .NET Framework, а третий можно загрузить с Web-сайта компании Microsoft по адресу msdn.microsoft.com/downloads.
Если приложение C# должно работать с сервером Microsoft SQL Server версии 7.0 или более новой версии, максимальная производительность будет достигнута при использовании провайдера данных SQL Server .NET Data Provider. К сожалению, специализированных провайдеров для прямого доступа из управляемого кода к СУБД других типов пока не существует.
Что же касается провайдера OLE DB .NET Data Provider, то он пригодится Вам для доступа к базам данных Microsoft Access и другим СУБД, для которых реализованы провайдеры OLE DB.
В том случае, когда единственно возможный способ интеграции приложения и СУБД заключается в использовании драйвера ODBC, можно воспользоваться провайдером ODBC .NET Data Provider.
Глава 3. Проектирование и разработка базы данных «Статьи» 3.1 Спецификация проекта
Очень часто возникает необходимость в хранении информации иерархического вида. Реляционные СУБД, такие как Microsoft SQL Server, позволяют хранить информацию в виде иерархического дерева, причем для представления такого дерева нужна всего одна таблица.
Каждая строка таблицы, хранящей структуру дерева, соответствует одному узлу этого дерева. При этом в таблице должно быть, как минимум, два столбца. Первый из них должен содержать уникальные идентификаторы строки (т.е. идентификаторы узлов), а второй — идентификатор соответствующего родительского узла. Для корневого узла в качестве идентификатора родительского узла обычно используется нулевое или какое-либо другое особое значение.
Для демонстрации способа хранения дерева в базе данных, а также для того, чтобы на конкретном примере изучить некоторые новые для меня методы работы с базами данных в приложениях C#, я разработал приложение ArticlesApp.
Приложение ArticlesApp представляет собой простейшую информационную систему, предназначенную для хранения текстовой информации. В базе данных этой системы Articlesхранятся статьи, организованные иерархическим образом.
В левой части этого окна имеется дерево, созданное с использованием элемента управления TreeView. Окно этого дерева отображает заголовки статей, а также так называемые веса сортировки заголовков, указанные в круглых скобках. Эти веса понадобятся мне далее в программе для корректного отображения иерархичности данных.
Замечу, что сразу после запуска приложения, когда в базе данных нет ни одной записи, дерево заголовков не содержит ни одного элемента. Если щелкнуть окно дерева правой клавишей мыши, на экране появится контекстное меню со строками Добавить статью, Удалить статью и Правка статьи. При нажатии на эти кнопки вызываются методы, позволяющие управлять содержимым базы данных.
Выбор строки Добавить статью приведет к тому, что на экране появится диалоговое окно Form2, специально созданное для этой цели. Оно содержит поле типа textboxдля хранения заголовка статьи, поле типа RichTextBoxдля хранения самого текста статьи. Также имеется поле типа numericUpDownдля хранения веса сортировки и 2 кнопки Сохранить и Отменить.Таким образом, при помощи этого окна можно добавить в базу данных новую статью, определив для нее заголовок, тело и вес сортировки.
Если в дереве нет ни одного элемента, то при первом использовании строки Добавить статью контекстного меню в дерево будет добавлен корневой элемент. Для того чтобы добавить в дерево дочерний элемент, нужно вначале выделить левой клавишей мыши заголовок родительского элемента, а потом, щелкнув этот заголовок правой клавишей мыши, выбрать из контекстного меню строку Добавить статью. Редактирование любого элемента выполняется аналогично. Для выполнения этой операции нужно выделить элемент, а затем, щелкнув его правой клавишей мыши, выбрать из контекстного меню строку Правка статьи. С помощью строки Удалить статью можно удалить элемент дерева. Замечу, что программа удаляет только элементы, не имеющие дочерних элементов. Попытки удалить элемент с дочерними элементами моё приложение игнорирует.
продолжение
--PAGE_BREAK--3.2 База данных Articles
Для создания приложения ArticlesAppмною была создана база данных Articlesна MicrosoftSQLServer2008. Она содержит 2 таблицы и 3 хранимые процедуры.
Таблица Tree предназначена для хранения структуры дерева статей. В ней создано четыре столбца с именами id, parent_id, title и weight. Столбец id является первичным ключом. Данную таблицу я создал с помощью sql-запроса следующего содержания:
CREATE TABLE [dbo].[Tree] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[parent_id] [int] NOT NULL ,
[title] [varchar] (50) COLLATE Cyrillic_General_CI_AS NOT NULL ,
[weight] [int] NOT NULL
) ON [PRIMARY].
Здесь столбец idхранит идентификаторы узлов дерева, а столбец parent_id— идентификаторы родительских узлов. Таким образом, вместе с каждым узлом хранится идентификатор его родительского узла.
Поля titleи weightпредназначены, соответственно, для хранения заголовка статьи и веса сортировки, назначенного этой статье. Вес сортировки необходим для визуализации заголовков статей в виде дерева. Чем выше вес сортировки, тем ниже располагается данная статья в дереве заголовков.
Можно было бы хранить тексты документов в самой таблице Tree, однако это привело бы к неэффективному расходованию памяти.
В самом деле, при отображении дерева мне фактически нужно загрузить в память все содержимое таблицы Tree. Однако в каждый момент времени пользователь просматривает или редактирует только одну статью, поэтому нет никакой необходимости загружать эти данные в память вместе со структурой дерева.
Для хранения текстов статей я создал отдельную таблицу Documents, содержащую столбцы id, document и tree_id. Первый из этих столбцов является ключевым. Ниже представлен sql-запрос, с помощью которого я создал таблицу Documents:
CREATE TABLE [dbo].[Documents] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[document] [varchar] (5000) COLLATE Cyrillic_General_CI_AS NOT NULL ,
[tree_id] [int] NOT NULL
) ON [PRIMARY]
В столбце idтаблицы Documentsхранятся уникальные идентификаторы статей, которые напрямую не используются в моём приложении.
Столбец tree_idхранит идентификатор узла дерева, соответствующего данной статье. Этот столбец является внешним ключом для таблицы Tree.
И, наконец, столбец documentхранит текст самой статьи.
3.3 Хранимые процедуры
Часть работы с базой данных моё приложение будет выполнять при помощи команд SQL, оформленных в виде объектов класса SqlCommand. Однако на примере этого приложения я покажу как можно работать с хранимыми процедурами сервера Microsoft SQL Server.
Хранимая процедура sp_InsertDocument предназначена для добавления нового документа в таблицу Documents:
CREATE PROCEDURE [dbo].[sp_InsertDocument]
@tree_id AS INT,
@document AS VARCHAR(2000)
AS
INSERT INTO dbo.Documents(tree_id, document) VALUES (@tree_id, @document);
RETURN @@identity
Этой процедуре необходимо передать два параметра @tree_id и @document. Первый из этих параметров предназначен для передачи идентификатора узла, в который добавляется статья, а второй — для передачи текста этой статьи. Процедура возвращает идентификатор добавленной строки @@identity.
Хранимая процедура sp_ InsertNode вставляет новую строку в таблицу Tree, возвращая идентификатор новой строки:
CREATE PROCEDURE [dbo].[sp_InsertNode]
@parent_id AS INT,
@title AS VARCHAR(50),
@weight AS INT
AS
INSERT INTO dbo.Tree(parent_id, title, weight) VALUES (@parent_id, @title, @weight);
RETURN @@identity
Этой процедуре нужно передать через входные параметры идентификатор родительского узла @parent_id(равный 0 для корневого узла), заголовок статьи @titleи вес сортировки @weight.
При помощи хранимой процедуры sp_UpdateDocumentмоё приложение обновляет тексты статей, хранящиеся в таблице Documents:.
ALTER PROCEDURE [dbo].[sp_UpdateDocument]
@tree_id as int,
@document AS VARCHAR(2000)
AS
UPDATE dbo.Documents SET document = @document WHERE (tree_id = @tree_id)
В качестве параметра этой хранимой процедуре необходимо передать идентификатор узла @tree_idобновляемой статьи, а также текст статьи @document.
3.4 Соединение с базой данных
Прежде всего, я обеспечил приложение возможностью соединения с базой данных Articles. С этой целью мною был добавлен программный компонент SqlConnection. Идентификатор этого компонента будет храниться в поле sqlConnection1 класса Form1.
Чтобы приложение могло корректным образом соединиться с базой данных Articlesсвойство ConnectionStringобъекта SqlConnection1 должно быть отредактировано следующим образом:
DataSource=.\SQLEXPRESS;AttachDbFilename=D:\Work\ArticlesApp\ArticlesApp\Articles.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True
Для того чтобы приложение могло загружать содержимое таблицы Tree базы данных Articles, хранящей структуру дерева статей, я добавил в него адаптер SqlDataAdapter, использующий соединение SqlConnection1. Таким образом ссылка на адаптер данных будет хранится в поле SqlDataAdapter1.
После добавления адаптера необходимо создать набор данных DataSet. Выбрав на панели инструментов одноимённый компонент, я создал набор данных DataSet1, содержащий обе таблицы базы данных Articles.
продолжение
--PAGE_BREAK--