Разработка баз данных "Articles" средствами платформы Microsoft.NET Framework
Размещено на http://www.
Министерство науки и образования РФ
ГОУ ВПО Тульский государственный педагогический университет
им. Л.Н. Толстого
Кафедра информатики и методики обучения информатике
Курсовая работа
на тему
РАЗРАБОТКА БАЗ ДАННЫХ «ARTICLES» СРЕДСТВАМИ ПЛАТФОРМЫ MICROSOFT.NET FRAMEWORK
студента 4 курса группы В
Трефилова Д. С.
Тула 2010
Содержание
Введение
Глава 1. Общие сведения о платформе Microsoft .NET Framework
1.1 Новые технологии
2.2 Платформа Microsoft .NET Framework
Глава 2. Приложения с базами данных и методы доступа к СУБД
2.1 Программные интерфейсы доступа к СУБД
2.1.1 Прямой вызов программного интерфейса СУБД
2.1.2 Использование программного интерфейса ODBC
2.2 Объектные интерфейсы СУБД
2.2.1 Интерфейс OLE DB
2.2.2 Интерфейс ActiveX Data Objects
2.3 Метод доступа ADO .NET
2.3.1 Многоуровневые системы
2.3.2 Рассоединенные системы
2.3.3 Распределенная обработка данных и XML
2.3.4 Провайдеры данных для управляемого кода
Глава 3. Проектирование и разработка базы данных «Статьи»
3.1 Спецификация проекта
3.2 База данных Articles
3.3 Хранимые процедуры
3.4 Соединение с базой данных
3.5 Создание узла дерева
3.5.1 Метод AddNode
3.5.2 Использование хранимых процедур
3.6 Диалоговая форма редактирования документа
3.6.1 Построение дерева
Заключение
Введение
На сегодняшний день проектирование баз данных и разработка эффективных приложений с базами данных является одной из самых популярных тем объектно-ориентированного программирования. Ещё более актуальной эта тема стала с появлением новой платформы .NET Framework, выпущенной компанией Microsoft, которая имеет огромный потенциал в решении вышеуказанных проблем. И это нисколько не удивительно, так как большинство деловых и офисных приложений, таких, например, как системы бухгалтерского или складского учёта, разного рода системы автоматизации финансового и хозяйственного учёта, а также Web-приложения, рассчитанные для работы в Интернете и интрасетях компаний интегрируются тем или иным способом с базами данных. Хоть .NET Framework и не была разработана специально для этих целей, но встроенные в неё языки программирования и стандартная библиотека классов, позволяют проектировать модели баз данных и разрабатывать клиентские приложения, содержащие базы данных, в полном объёме.
В рамках данной курсовой работы будут изложены основные сведения о платформе .NET Framework, продемонстрированы методы доступа к базам данных и системам управления базами данных, используя при этом в качестве программного инструментария продукт компании Microsoft «Microsoft Visual C# Express Edition 2008» и Microsoft SQL Server 2008.
Mною будет разработан собственный проект приложения «Статьи», содержащий базу данных и раскрывающий все аспекты разработки базы данных на языке C#, которые будут подробно рассмотрены в третьей главе настоящей курсовой работы.
Глава 1. Общие сведения о платформе Microsoft .NET Framework
1.1 Новые технологии
Новые технологии Microsoft .NET, ориентированные на разработку автономных и распределенных приложений Интернета, призваны облегчить создание сложных со временных приложений, их документирование и внедрение. В рамках Microsoft .NET разработчикам программ предоставляется новый интерфейс программирования (Application Program Interface, API), пригодный для создания обычных настольных программ Microsoft Windows, системных сервисов Microsoft Windows, а также Web-приложений и Web-сервисов.
В рамках Microsoft .NET доступны следующие языки программирования:
• Microsoft C#.
• Microsoft Visual Basic .NET.
• Managed C++.
• Microsoft Visual J# .NET.
• JScript.NET.
Кроме того, в рамках Microsoft .NET предоставляется чрезвычайно удобная интегрированная среда разработки приложений Microsoft Visual Studio .NET, а также среда выполнения программ Microsoft .NET Framework.
В составе Microsoft .NET имеется набор сетевых служб и серверов серии.NET Enterprise Server, предназначенных для решения задач аутентификации, для создания систем хранения данных, обработки электронной почты и создания бизнес-систем, а также средства для программирования и встраиваемых вычислительных систем, например, для мобильных телефонов, игровых приставок и т. п. Планируется выпуск ОС Microsoft Windows .NET, в полной мере реализующей преимущества технологии Microsoft .NET.
1.2 Платформа Microsoft .NET Framework
Платформа 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, так и в приложениях, создаваемых для этой ОС.
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-сервер, и только для него нужны клиентские лицензии.
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 по адресу http://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 кнопки Сохранить и Отменить. Таким образом, при помощи этого окна можно добавить в базу данных новую статью, определив для нее заголовок, тело и вес сортировки.
Если в дереве нет ни одного элемента, то при первом использовании строки Добавить статью контекстного меню в дерево будет добавлен корневой элемент. Для того чтобы добавить в дерево дочерний элемент, нужно вначале выделить левой клавишей мыши заголовок родительского элемента, а потом, щелкнув этот заголовок правой клавишей мыши, выбрать из контекстного меню строку Добавить статью. Редактирование любого элемента выполняется аналогично. Для выполнения этой операции нужно выделить элемент, а затем, щелкнув его правой клавишей мыши, выбрать из контекстного меню строку Правка статьи. С помощью строки Удалить статью можно удалить элемент дерева. Замечу, что программа удаляет только элементы, не имеющие дочерних элементов. Попытки удалить элемент с дочерними элементами моё приложение игнорирует.
3.2 База данных Articles
Для создания приложения ArticlesApp мною была создана база данных Articles на Microsoft SQL Server 2008. Она содержит 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.
3.5 Создание узла дерева
Создание дерева начинается с того, что пользователь запускает приложение, щелкает правой клавишей мыши пустое окно дерева и выбирает из контекстного меню строку Добавить статью. В результате на экране появляется диалоговое окно, показанное на рисунке ниже, где пользователь может ввести информацию для узла дерева:
Реализация процесса добавления статьи состоит в написании обработчика события для кнопки Добавить статью контекстного меню contextMenuStrip1. Ниже приведён обработчик для этого события:
private void добавитьToolStripMenuItem_Click(object sender, EventArgs e)
{
if (treeView1.SelectedNode != null)
{
int id = (int)treeView1.SelectedNode.Tag;
AddNode(id);
UpdateTree();
}
else
{
// Пустой список
if (treeView1.Nodes.Count == 0)
{
AddNode(0);
UpdateTree();
}
}
}
При самом первом запуске приложения и пустой базе данных в дереве treeView1 не выделено ни одного элемента, т.к. их там попросту нет. Соответственно, количество узлов дерева treeView1.Nodes.Count равно нулю. В этом случае моё приложение вызывает два метода:
AddNode(0);
UpdateTree();
3.5.1 Метод AddNode
Метод AddNode, определенный в моём приложении, создает узел дерева. В качестве единственного параметра этому методу нужно передать идентификатор родительского узла. Так как в первый раз пользователь создает корневой узел, то передаем методу AddNode нулевое значение.
Что же касается метода UpdateTree, то он тоже определен в моём приложении. Его задачей является наполнение окна дерева treeView1 содержимым таблицы Tree базы данных Articles. Я вызываю этот метод всякий раз после внесения изменений в структуру дерева (т.е. после добавления или удаления узлов дерева).
Для того чтобы содержимое дерева отображалось сразу после запуска приложения, я добавил вызов метода UpdateTree в конструктор класса Form1:
public Form1()
{
InitializeComponent();
UpdateTree();
}
В том случае, если в дереве есть узлы, и пользователь выделил какой-либо узел левой клавишей мыши или при помощи клавиатуры, наш обработчик событий добавитьToolStripMenuItem_Click выполняет следующие действия:
if (treeView1.SelectedNode != null)
{
int id = (int)treeView1.SelectedNode.Tag;
AddNode(id);
UpdateTree();
}
Вначале он извлекает из свойства treeView1.SelectedNode.Tag идентификатор строки таблицы Tree, соответствующий выделенному узлу. Этот идентификатор записывается в данное свойство методом UpdateTree в процессе построения дерева.
Замечу, что данный идентификатор обозначает узел, являющийся родительским по отношению к создаваемому узлу. Обработчик событий добавитьToolStripMenuItem_Click передает этот идентификатор методу AddNode, а затем перерисовывает обновленное дерево методом UpdateTree:
AddNode(id);
UpdateTree();
Рассмотрим реализацию метода AddNode, служащего для добавления нового узла в дереве заголовков статей и добавления всех необходимых записей в базу данных Articles:
public void AddNode(int id)
{
Form2 dialog = new Form2();
if (DialogResult.Yes == dialog.ShowDialog())
{
sqlConnection1.Open();
try
{
SqlCommand cmd = new SqlCommand("sp_InsertNode",sqlConnection1);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = cmd.Parameters.Add("RETURN_VALUE",SqlDbType.Int);
param.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("@parent_id", SqlDbType.Int).Value = id;
cmd.Parameters.Add("@title", SqlDbType.VarChar).Value =dialog.Title;
cmd.Parameters.Add("@weight", SqlDbType.Int).Value =dialog.Weight;
cmd.ExecuteNonQuery();
int tree_id = (int)cmd.Parameters["RETURN_VALUE"].Value;
cmd = new SqlCommand("sp_InsertDocument", sqlConnection1);
cmd.CommandType = CommandType.StoredProcedure;
param = cmd.Parameters.Add("RETURN_VALUE", SqlDbType.Int);
param.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("@tree_id", SqlDbType.Int).Value = tree_id;
cmd.Parameters.Add("@document", SqlDbType.Text).Value =dialog.Document;
cmd.ExecuteNonQuery();
int document_id = (int)cmd.Parameters["RETURN_VALUE"].Value;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка");
}
sqlConnection1.Close();
}
}
В самом начале работы метод AddNode отображает диалоговое окно для добавления новой статьи. Это диалоговое окно представляет собой класс Form2, добавленный непосредственно в проект приложения ArticlesApp.
Если пользователь завершил работу с данным диалоговым окном нажатием кнопки Сохранить, то метод AddNode извлекает данные, введённые пользователем и добавляет их в таблицы базы данных Articles:
Form2 dialog = new Form2();
if (DialogResult.Yes == dialog.ShowDialog())
{
...
Для добавления данных, прежде всего, открывается соединение с базой данных: sqlConnection1.Open();
Все дальнейшие операции выполняются в теле оператора try-catch, что позволяет перехватывать ошибки и отображать текст сообщений об ошибках на экране:
try
{
...
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка");}
После обновления содержимого базы данных метод AddNode закрывает соединение с базой данных SqlConnection1.Close();.
3.5.2 Использование хранимых процедур
Прежде всего, моя программа вызывает хранимую процедуру sp_InsertNode, предназначенную для добавления новой строки в таблицу Tree, хранящую структуру дерева. Напомню, что этой процедуре нужно передать через входные параметры идентификатор родительского узла @parent_id, заголовок статьи @title и вес сортировки @weight.
Вызов хранимой процедуры начинается с создания объекта класса SqlCommand:
SqlCommand cmd = new SqlCommand("sp_InsertNode",sqlConnection1);
cmd.CommandType = CommandType.StoredProcedure;
Далее программа должна задать тип команды в свойстве CommandType в виде константы CommandType.StoredProcedure: cmd.CommandType.
Это означает, что команда содержит не строку SQL, а имя хранимой процедуры.
На следующем этапе необходимо добавить параметры хранимой процедуры. Наша хранимая процедура sp_InsertNode имеет три входных и один выходной параметр.
Через выходной параметр со специальным именем RETURN_VALUE хранимая процедура возвращает идентификатор добавленной строки:
SqlParameter param = cmd.Parameters.Add("RETURN_VALUE",SqlDbType.Int);
В качестве первого параметра методу Add передается имя параметра хранимой процедуры, а в качестве второго — тип данных, соответствующих этому параметру.
Чтобы указать, что этот параметр является выходным, я записываю константу ParameterDirection.ReturnValue в свойство параметра с именем Direction:
param.Direction = ParameterDirection.ReturnValue;
Если этого не сделать, то по умолчанию параметр будет входным.
Вот как я указываю входные параметры для хранимой процедуры sp_InsertNode:
cmd.Parameters.Add("@parent_id", SqlDbType.Int).Value = id;
cmd.Parameters.Add("@title", SqlDbType.VarChar).Value =dialog.Title;
cmd.Parameters.Add("@weight", SqlDbType.Int).Value =dialog.Weight;
Следует отметить, что тип числовых данных указан как SqlDbType.Int, а тип строчных данных — как SqlDbT ype.VarChar.
Параметру хранимой процедуры @parent_id я присваиваю значение идентификатора родительского узла, который передается при вызове методу AddNode. Что же касается параметров @title и @weight, то для их инициализации я извлекаю значения из свойств Title и Weight, определенных мною в классе Form2 диалогового окна ввода данных узла.
Для запуска хранимой процедуры на выполнение вызывается метод ExecuteNonQuery:
cmd.ExecuteNonQuery();
Если у хранимой процедуры имеются параметры (как в моём случае), то их необходимо подготовить. Иначе при выполнении метода ExecuteNonQuery возникнет необработанное исключение.
После того как хранимая процедура завершит свою работу, программа может получить значение ее выходных параметров при помощи свойства Value.
Вот как я извлекаю значение, возвращаемое хранимой процедурой sp_InsertNode:
int tree_id = (int)cmd.Parameters["RETURN_VALUE"].Value;
Напомню, что моя хранимая процедура возвращает идентификатор узла, добавленного в таблицу Tree. Этот идентификатор понадобится нам в дальнейшем для инициализации ячейки внешнего ключа таблицы Documents, ссылающейся на таблицу Tree.
Для добавления текста документа, извлеченного из свойства dialog.Document диалогового окна класса Form2 я вызываю хранимую процедуру sp_InsertDocument:
cmd = new SqlCommand("sp_InsertDocument", sqlConnection1);
cmd.CommandType = CommandType.StoredProcedure;
param = cmd.Parameters.Add("RETURN_VALUE", SqlDbType.Int);
param.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("@tree_id", SqlDbType.Int).Value = tree_id;
cmd.Parameters.Add("@document", SqlDbType.Text).Value =dialog.Document;
cmd.ExecuteNonQuery();
int document_id = (int)cmd.Parameters["RETURN_VALUE"].Value;
Выходной параметр получает возможность получить идентификатор новой строки в таблице Documents. Я извлекаю его только для примера, но в приложении не использую. Что же касается входных параметров, то хранимой процедуре sp_InsertDocument передается идентификатор узла @tree_id обновляемой статьи, а также текст статьи @document.
3.6 Диалоговая форма редактирования документа
Для того чтобы программа могла инициализировать поля формы, а также получать значения, введенные в ней пользователем, необходимо создать в классе Form2 свойства Title, Weight и Document с помощью полей set и get. Ниже приведены исходные коды для этих свойств:
public string Title
{
get
{
return textBox1.Text;
}
set
{
textBox1.Text = value;
}
}
public int Weight
{
get
{
return (int)numericUpDown1.Value;
}
set
{
numericUpDown1.Value = value;
}
}
public string Document
{
get
{
return richTextBox1.Text;
}
set
{
richTextBox1.Text = value;
}
}
3.6.1 Построение дерева
Для построения дерева заголовков статей в окне элемента управления TreeView в нашем приложении определен метод UpdateTree, на который я уже ссылались ранее, а также метод CreateNodes.
Метод UpdateTree считывает структуру дерева из базы данных Articles и отображает ее в окне элемента управления treeView1 класса TreeView.
public void UpdateTree()
{
dataSet11.Clear();
sqlDataAdapter1.Fill(dataSet11);
treeView1.Nodes.Clear();
CreateNodes(0, (TreeNode)null);
}
Получив управление, метод UpdateTree очищает набор данных dataSet11, а затем наполняет его из таблицы Tree базы данных Aticles, пользуясь для этого адаптером sqlDataAdapter1 и методом Fill. Заполнение дерева treeView1 содержимым набора данных dataSet11 осуществляется методом CreateNodes.
public void CreateNodes(int iParent, TreeNode pNode)
{
DataView dvwData = new DataView(dataSet11.Tree);
dvwData.RowFilter = "[parent_id] = " + iParent;
foreach (DataRowView Row in dvwData)
{
int id = Int32.Parse(Row["id"].ToString());
if (pNode == null)
{
TreeNode zNode = treeView1.Nodes.Add(Row["title"].ToString() +
" (" + Row["weight"].ToString() + ")");
zNode.Tag = id;
CreateNodes(id, zNode);
}
else
{
if (id == iParent)
return;
TreeNode zNode = pNode.Nodes.Add(Row["title"].ToString() +
" (" + Row["weight"].ToString() + ")");
zNode.Tag = id;
CreateNodes(id, zNode);
}
}
}
Метод CreateNodes имеет два параметра.
Через первый параметр методу передается идентификатор узла, родительского по отношению к добавляемому узлу. Если создается корневой узел, то значение этого параметра равно нулю.
Второй параметр используется для передачи ссылки на родительский узел дерева treeView1, который является объектом класса TreeNode. При создании корневого узла этот параметр должен иметь значение null.
Прежде всего, он создает представление (view) таблицы dvwData, хранящейся в наборе данных dataSet11. Это представление включает в себя подмножество строк таблицы, столбец parent_id которых содержит идентификатор родительского узла, переданного методу CreateNodes в качестве первого параметра. Иными словами, здесь происходит отбор дочерних узлов заданного родительского узла.
Заключение
база данных приложение microsoft
В настоящей курсовой работе были изложены сведения о платформе Microsoft.NET Framework, рассказано о способах и методах доступа к базам данных и системам управления базами данных, а также на конкретном примере продемонстрирована работа по проектированию и программированию баз данных средствами выше упомянутой платформы. Мною было спроектировано приложение «Articles», исходный код которого прилагается к курсовой работе.
В ходе выполнения данной курсовой я узнал много новых аспектов, касающихся программирования баз данных на языке C#, а также познакомился со способами работы Microsoft SQL Server 2008. Считаю поставленную задачу полностью выполненной и реализованной.
Размещено на http://www.
1