Разработка переносимого графического интерфейса пользователя для работы со встраиваемой реляционной БД на примере СУБД SQLite

Система управления базами данных. Встраиваемая СУБД SQLite. Организация запросов к БД через использование библиотеки sqlite3.dll. Представление реляционной БД в виде иерархической структуры. Графический интерфейс пользователя, неявное построение запросов.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 03.06.2012
Размер файла 366,0 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Размещено на http://www.allbest.ru/

Федеральное агентство по образованию

Государственное образовательное учреждение

Высшего профессионального образования

ИРКУТСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

ИНСТИТУТ МАТЕМАТИКИ, ЭКОНОМИКИ И ИНФОРМАТИКИ

Кафедра теории алгоритмов и программирования

Разработка и создание переносимого графического интерфейса пользователя для работы со встраиваемой реляционной БД на примере СУБД SQLite

Курсовая работа

Научный руководитель

доцент кафедры ТАИП, к.ф.-м.н

Курганский Виктор Иванович

Исполнитель

студент 3-го курса специальности

010501.65 - «Прикладная математика

и информатика», гр. 2322

Кузнецов Алексей Александрович

Иркутск 2012г.

Содержание

Введение

1. Базы данных

1.1 Реляционная модель данных

1.2 Система управления базами данных

1.3 Встраиваемая СУБД SQLite

1.4 Организация запросов к БД через использование библиотеки sqlite3.dll (решение задачи 1, часть 1)

2. Графический интерфейс пользователя, неявное построение запросов

2.1 Некоторые технологии создания графических интерфейсов пользователя, краткое описание

2.2 Построение запросов к БД через заполнение диалоговых форм (решение задачи 1, часть 2)

2.3 Построение запроса на добавление таблицы в БД (решение задачи 1, часть 3)

3. Представление реляционной БД в виде иерархической структуры (XML файла)

3.1 Иерархическая модель данных

3.2 Формат данных - XML

3.3 Представление РБД в виде XML (решение задачи 2, часть 1)

3.4 Технология LINQ, а именно - LINQ to XML (решение задачи 2, часть 2)

Заключение

Приложение 1. Полный код приложения

Приложение 2. Схема запроса create table

Приложение 3. Пример полученного XML-файла

Введение

В современном мире обработка и предоставление в понятном для пользователя виде больших объемов данных является одним из самых необходимых направлений в прикладном программировании. Для решения этих и многих других связанных задач можно выделить целый ряд решений. Но одним из самых популярных, пожалуй, является представления необходимых данных в виде реляционных таблиц*. Множество же связанных таблиц называют (реляционной) базой данных**. Хотя самыми распространенными и используемыми системами управления БД*** являются клиент-серверные, для большого круга задач можно и нужно использовать встраиваемые СУБД. Они занимают меньше дискового пространства, потребляют меньше машинных ресурсов, а главное, они могут быть развернуты локально без использования парадигмы «клиент-сервер», хотя при их использовании и есть ряд ограничений.

Целью курсовой работы было поставлено: создание кроссплатформенного переносимого графического интерфейса пользователя для удобной работы со встраиваемой БД на примере СУБД SQLite. Т.е. интерфейса, не требующего установки и работающего на ряде операционных систем. Полностью разработанный интерфейс мог бы найти применение в личном использование на домашних компьютерах (например телефонная книга, фотоальбом, книга личных доходов/расходов) или в среде малого бизнеса (учет посещаемости работниками, корпоративный ежедневник) ввиду удобности и компактности.

В ходе разработки были поставлены и решены следующие задачи:

1. организовать работу с БД через графический интерфейс пользователя - т.е. фактически необходимо было решить задачу построение запросов к БД на основе заданных шаблон по заполненным пользователем полям;

2. организовать представление схемы БД в виде иерархической структуры в самом приложении и её сохранение в XML-файл - в дальнейшем этот файл, благодаря универсальности формата, может быть использован для решения каких-то других задач;

Задачи, которые могут быть поставлены при дальнейшем развитии проекта:

1. дополнение функциональности интерфейса и добавление новых возможностей: удаление, связывание таблиц БД; удаление, добавление полей в таблицы БД;

2. стандартизация и оформление свода правил представления БД в виде XML-файла.

*далее РТ - реляционная(-ые) таблица(-ы).

**далее БД - база(-ы) данных, РБД - реляционная(-ые) БД. В силу распространенности РБД иногда под сокращением БД подразумевают конкретно их.

***далее СУБД - система(-ы) управления БД.

1. Базы данных

Разрабатываемое приложение - это интерфейс для работы с БД. Но в первую очередь необходимо прояснить, что же представляют собой базы данных.

Достаточно сложно дать формальное определение этому термину в общем смысле. Такое определение вынуждено будет получиться слишком громоздким, чтобы описывать только то, что мы подразумеваем под БД и рассмотреть все случаи. Но и неформального определения хватает в большинстве случаев. База данных - это информационная модель, позволяющая хранить данные о группе (или группах) объектов, обладающих одинаковым набором свойств.

Ниже речь будет вестись преимущественно про реляционные БД. Но хотелось бы упомянуть, что есть и другие БД, основанные на других моделях представления информации (модель данных). К примеру, это:

· иерархическая,

· сетевая,

· объектно-ориентированная,

· объектно-реляционная,

· функциональная и др. модели данных.

В соответствии с каждой концепцией заданы свои правила построения баз данных и способов манипуляции с ними.

Ниже в данном разделе будет приведена краткая теоретическая информация по РБД и описаны ключевых моментов организации работы с БД в разработанном интерфейсе.

1.1. Реляционная модель данных

Реляционная модель данных (РМД) -- логическая модель данных, характеризующаяся характерной структурой с возможностью представления этих данных в табличном виде, а также возможностью использовать для обработки этих данных формального языка реляционной алгебры и реляционного исчисления.

РМД ориентирована на организацию данных в виде двумерных таблиц. Каждая реляционная таблица представляет собой двумерный массив и обладает следующими свойствами:

· каждый элемент таблицы -- один элемент данных;

· все ячейки в столбце таблицы однородные, то есть все элементы в столбце имеют одинаковый тип;

· каждый столбец имеет уникальное имя;

· одинаковые строки в таблице отсутствуют;

· порядок следования строк и столбцов может быть произвольным.

Принципы РМД были сформулированы в 1969--1970 годах Э. Ф. Коддом (E. F. Codd).

1.2. Система управления базами данных

Система управления базами данных (СУБД) -- совокупность программных и лингвистических средств общего или специального назначения, обеспечивающих управление (создание, чтение, изменение, сохранение) БД.

Основные функции СУБД:

· управление данными во внешней памяти;

· управление данными в оперативной памяти;

· поддержка языков управления БД.

Возможная классификация СУБД:

· Файл-серверные (Access, Paradox, dBase, FoxPro, Visual FoxPro и др.)

· Клиент-серверные (Oracle, Firebird, MS SQL Server, PostgreSQL, MySQL и др.)

· Встраиваемые (SQLite, BerkeleyDB, Firebird Embedded, Microsoft SQL Server Compact и др.)

1.3. Встраиваемая СУБД SQLite

Локальная или встраиваемая СУБД (англ. embedded DBMS) - СУБД, которая может поставляться как составная часть некоторого программного продукта, не требуя процедуры самостоятельной установки. Встраиваемая СУБД предназначена для локального хранения данных своего приложения и не рассчитана на коллективное использование в сети. Физически встраиваемая СУБД чаще всего реализована в виде подключаемой библиотеки. Доступ к данным со стороны приложения может происходить через SQL либо через специальные программные интерфейсы.

SQLite является неотъемлемой частью (подключаемая библиотека sqlite3.dll) клиентского приложения и не функционирует вне его. Каждая база данных SQLite представляет собой один файл в пользовательской файловой системе, содержащий все таблицы и служебную информацию внутри себя. При использовании СУБД SQLite процесс, желающий получить доступ к базе данных, с помощью вызываемых функций библиотеки читает и пишет данные напрямую в файл, хранящийся на диске.

1.4. Организация запросов к БД через использование библиотеки sqlite3.dll (решение задачи 1, часть 1)

Как было сказано выше, реализация SQLite представляет собой СУБД, расположенную внутри отдельной программной библиотеки, написанной на языке C. Библиотека самой последней на текущий момент версии SQLite3 занимает всего около 300 килобайт и может быть использована в большинстве современных языков программирования. Для использования на платформе .Net (Mono) на сайте www.sqlite.org была скачана реализация СУБД для этой платформы. Далее библиотека была загружена и подключена к проекту. Для обращения к этой библиотеке было решено разработать отдельный статичный класс SQLiteProvider, так как это соответствует принятым нормам объектно-ориентированного программирования. Этот класс содержит следующие поля:

· ExecuteNonQuery(string appPath, string sSql) - обрабатывает запрос sSql по отношению к файлу БД appPath и возвращает количество затронутых полей. Например, запрос update.

· Query(string appPath, string sSql) - обрабатывает запрос sSql по отношению к файлу БД appPath и возвращает запрошенные данные. Например, запрос select.

· GetTablesNames(string appPath) - возвращает имена всех таблиц, содержащихся в файле БД appPath.

Обработка запросов заключается в создании так называемого коннектора (объекта класса SQLiteConnection) и вызове соответствующих методов. А коннектор, в свою очередь, уже физически работает с файлом БД.

Полный код класса SQLiteProvider находится в Приложении 1.

2. Графический интерфейс пользователя, неявное построение запросов

Как было заявлено во Введении, целью работы является не просто создать приложение по управлению БД, но сделать это управление удобным для не знакомого с техническими моментами пользователя. Данная задача обычно решается через создание GUI(Graphical user interface) - графический интерфейс пользователя.

Практически во всех современных клиент-ориентированных приложениях графический интерфейс пользователя является неотъемлемой частью. Взаимодействие с программой через такой интерфейс значительно упрощает и ускоряет работу конечного пользователя, оставляет у него приятное впечатление после её использования. На разработку новых методов отрисовки, описания, представления и хранения интерфейсов направлены немалые силы многих крупных компаний. Любой современный механизм по созданию и представлению интерфейсов должен отвечать целому ряду требований:

· кросплатформенность,

· набор стандартных компонентов,

· возможность добавлять разработчику свои компоненты,

· наименьшая требовательность к аппаратным ресурсам,

· поддержка событийной ООП модели и др.

В данном разделе будет приведена информация по некоторым технологиям создания графических интерфейсов и концепция Visual Query Building (визуальное построение запросов) - построение запросов к БД через заполнение пользователем диалоговых форм.

библиотека sqlite запрос

2.1. Некоторые технологии создания графических интерфейсов пользователя, краткое описание

· Windows Forms

Windows Forms - название интерфейса программирования приложений (API), отвечающего за графический интерфейс пользователя и являющегося частью платформы .Net. Windows Forms построена на основе устаревающего Win32 API и представляет собой обертку нижележащих компонентов Windows.

Поддерживаемые ОС - Windows, Mac OS X (реализация Mono)

· WPF (Windows Presentation Foundation)

Windows Presentation Foundation - система для построения клиентских приложений Windows с визуально привлекательным интерфейсом и поддерживающая элементы управления, привязку данных, макеты, двухмерную и трёхмерную графику, анимацию, стили, шаблоны, документы, текст, мультимедиа. В основе WPF лежит векторная система визуализации, не зависящая от разрешения устройства вывод. Графической технологией, лежащей в основе WPF, является DirectX, в отличие от Windows Forms, где используется GDI/GDI+, что значительно увеличивает производительность.

Также существует упрощенная версия, называющаяся WPF/E, она же известна как Silverlight.

Поддерживаемые ОС - Windows, Windows Phone.

· GTK#

GTK# - это обертка над GTK+, который в свою очередь является кроссплатформенным фреймворком для создания графического интерфейса пользователя. Будучи изначально частью графического редактора GIMP, он развился в отдельный проект и приобрел заметную популярность. GTK+ -- свободное ПО, распространяемое на условиях GNU LGPL, позволяющей создавать как свободное, так и проприетарное программное обеспечение.

Поддерживаемые ОС - Windows, Linux, Mac OS, Mac OS X.

Все перечисленные выше технологии позволяют создавать кроссплатформенные графические интерфейсы пользователя, которые могут быть запущены на ряде операционных системах. В будущем это может стать одной из задач - создание полностью кроссплатформенного переносимого интерфейса, где может быть использована технология GTK#. Во время работы графический интерфейс был реализован в двух вариантах - на WPF и на GTK#, но с гораздо меньшей функциональностью.

2.2. Построение запросов к БД через заполнение диалоговых форм (решение задачи 1, часть 2)

Как известно, взаимодействие с реляционной БД обычно основано на некотором формальном языке запросов. В случае СУБД SQLite это разновидность языка SQL. SQL (англ. Structured Query Language - «язык структурированных запросов») - универсальный язык, применяемый для создания, модификации и управления данными в реляционных базах данных. SQL основывается на исчислении кортежей. Данный язык является достаточно объемным и сложным для начинающих разработчиков или конечных пользователей. Но, по сути своей, все запросы построены по определенным правилам и имеют строгую структуру - любой запрос может быть сгенерирован в автоматическом режиме. В виду этих причин является возможным реализовать ряд диалоговых форм, через которые будет осуществляется «неявное построение запроса» - т.е. из заполненных на форме полей будут браться необходимые данные и полный текст (тело) запроса сформировываться автоматически по заданным в коде шаблонам. Такую концепцию так же называют Visual Query Building.

2.3. Построение запроса на добавление таблицы в БД (решение задачи 1, часть 3)

Одна из функций, реализованных в проекте - это построение запроса на добавление новой таблицы в БД. В общем виде схема запроса для СУБД SQLite на добавление таблицы выглядит следующим образом: Приложение 2.

Как видно, запрос достаточно разнообразен и объемен - но хорошо может быть представлен в виде шаблона.

В проекте было реализовано получение таких свойств для новой таблицы, как: имя таблицы; набор полей - имя поля, тип, не пустое, первичный ключ; создавать, только если не создана.

После этого происходит формирование запроса, которое выглядит так:

//проверим, чтобы было заданно имя для таблицы

if (Tb_NewTableName.Text != "")

{

//проверим, чтобы у таблицы были поля

if (Lb_Fields.HasItems)

{

//и проверим, чтобы был первичный ключ

if (hasPrimaryKey == true)

{

string[] fields = new string[Lb_Fields.Items.Count];

Lb_Fields.Items.CopyTo(fields, 0);

string ifNotEx = "";

if (Cb_IfNotExist.IsChecked.Value) ifNotEx = "IF NOT EXISTS ";

query = "CREATE TABLE " + ifNotEx + Tb_NewTableName.Text + "(";

for (int i = 0; i < Lb_Fields.Items.Count - 1; i++)

query += Lb_Fields.Items[i] + ", ";

query += Lb_Fields.Items[Lb_Fields.Items.Count - 1] + ");";

Close();

}

else MessageBox.Show("Задайте первичный ключ!");

}

else MessageBox.Show("Задайте поля!");

}

else MessageBox.Show("Введите имя таблицы!");

Как можно увидеть из приведенного фрагмента, часть SQL-запроса заданна прямо в коде в виде текстовых (string, в двойных кавычках) данных, а другая часть получается из полей на форме, которую должен заполнить пользователь. После этого сформированный запрос отправляется в основной класс приложения, а из него в класс провайдера к СУБД.

Полный код класса NewTable находится в Приложении 1.

3. Представление реляционной БД в виде иерархической структуры (XML-файла)

3.1. Иерархическая модель данных

Выше была описана реляционная модель данных. Но она не является единственной возможной моделью представления данных, а так же реляционные БД не являются единственными, хотя они и самые популярные и распространенные. Другой достаточно популярной моделью представления данных, в некоторых случаях более выгодной и удобной, является иерархическая модель данных. Смысл её заключается в том, что в БД задан набор объектов, имеющих ряд атрибутов и какое-то значении. Между объектами существуют связи, каждый объект может содержать в себе несколько объектов более низкого уровня (они являются значением этого объекта). Такие объекты находятся в отношении предка (объект более близкий к корню) к потомку, при этом возможна ситуация, когда объект-предок не имеет потомков или имеет их несколько, тогда как у объекта-потомка обязательно только один предок. Объекты, имеющие общего предка, называются близнецами (сестринскими объектами).

3.2. Формат данных - XML

XML - это описанная в текстовом формате иерархическая структура, предназначенная для хранения любых данных. Данный формат является универсальным и крайне распространенным, используется во многих отраслях - от компьютерных игр до автоматизации работы производственного оборудования. Визуально структура может быть представлена как дерево элементов. Элементы XML описываются тегами.

Синтаксис:

· тег - заключенный в `<' `>' текст, обычно для каждого элемента есть открывающийся и закрывающийся теги;

· элемент - узел дерева, имеющий множество атрибутов (возможно пустое) и содержимое (простой текст или множество дочерних элементов; возможен вариант с пустым элементом, т.е. без содержимого);

· атрибут - пара имя-значение, добавляемое в открывающий тег после названия элемента;

· важнейшее обязательное требование заключается в том, что документ имеет только один корневой элемент (англ. root element);

Данный формат может быть использован для реализации физического хранения данных (т.е. в виде отдельного файла на жестком диске компьютера), представленных в виде иерархическая модель данных.

3.3. Представление РБД в виде XML (решение задачи 2, часть 1)

Две описанные выше концепции (реляционная и иерархическая модели данных) в общем случае не совместимы между собой и данные не могут быть представлены из одной модели в другую без непосредственной обработки этих данных. Однако иерархическая модель отлично подходит для простого описания структуры РБД (так называемой схемы), что и являлось одной из задач, решенных в ходе работы.

Разработанный механизм генерирует дерево:

· корнем которого является БД (имя БД, кол-во таблиц);

· дочерние элементы первого уровня - таблицы (имя таблицы, кол-во записей);

· дочерними элементами второго уровня - строки;

· дочерними элементами третьего уровня - ячейки (имя столбца, значение).

Далее это дерево отображается непосредственно во время работы приложения и сохраняется в XML-файл на жесткий диск после завершения работы. Такая схема дает общее представление об обрабатываемой БД, причем оно достаточно легко для понимания человеком.

3.4. Технология LINQ, а именно - LINQ to XML (решение задачи 2, часть 2)

При реализации представления РБД в виде иерархической структуры была использована технология Microsoft LINQ и конкретно возможность работать с XML. С её помощью обработка данных, заданных в виде дерева значительно упрощается и становится намного более наглядной.

В ниже следующем методе происходит построение схемы БД. Используются простые SQL-запросы, экземпляры классов XDocument - предоставляет всю информацию об объекте, XElement - узел дерева (элемент в иерархической структуре) и метод SetAttributeValue - добавляет/изменяет значение атрибута.

/// <summary>

/// Строит стуктуру БД в объект.

/// </summary>

private void BuildXDoc()

{

try

{

xDoc = new XDocument(new XElement("DataBase"));

xDoc.Root.SetAttributeValue("name", baseName);

List<string> tablesNames = SQLiteProvider.GetTablesNames(appPath);

xDoc.Root.SetAttributeValue("tablesCount", tablesNames.Count);

foreach (string s in tablesNames)

{

XElement xEl1 = new XElement("Table");

xEl1.SetAttributeValue("name", s);

query = "SELECT * FROM " + s;

DataRow[] drs = SQLiteProvider.Query(appPath, query);

xEl1.SetAttributeValue("columnsCount", drs[0].Table.Columns.Count);

foreach (DataRow dr in drs)

{

XElement xEl2 = new XElement("Row");

int i = 0;

foreach (object cell in dr.ItemArray)

{

XElement xEl3 = new XElement("Field");

xEl3.SetAttributeValue("name", dr.Table.Columns[i].ColumnName);

xEl3.SetAttributeValue("value", cell);

i++;

xEl2.Add(xEl3);

}

xEl1.Add(xEl2);

}

xDoc.Root.Add(xEl1);

}

}

Пример XML-файла, полученного в результате обработки РБД можно увидеть в Приложении 3.

Заключение

Конечным результатом работы можно назвать разработанный и реализованный переносимый графический интерфейс пользователя для работы со встраиваемой реляционной БД на примере СУБД SQLite с возможностью составления схемы БД в виде дерева и сохранения его в XML-файл.

Данный интерфейс, хоть и далек от идеального, но реализует поставленные задачи:

1) организована работа с БД через графический интерфейс пользователя: создание нового, загрузка созданного файла БД; добавление новых таблиц в БД; чтение таблиц, полей таблиц из БД;

2) организованно представление схемы БД в виде иерархической структуры в самом приложении и её сохранение в XML-файл;

Дальнейшее развитие проекта можно увидеть в:

1) увеличении функциональных возможностей по визуальному построению запросов,

2) в совершенствовании механизма и формальном описании правил представления РБД в виде иерархической модели данных (XML-файла),

3) добавления полнофункциональной переносимости приложения между различными ОС, отличными от семейства ОС Windows (кроссплатформенности).

Приложение 1

Полный код приложения

using System;

using System.IO;

using System.Collections.Generic;

using System.Data;

using System.Linq;

using System.Xml;

using System.Xml.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

using Finisar.SQLite;

namespace SQLiteSampleProject

{

public partial class MainWindow : Window

{

/// <summary>

/// Путь к папке с приложением.

/// </summary>

string appPath;

/// <summary>

/// Имя файла базы данных.

/// </summary>

string baseName;

/// <summary>

/// Запрос базе.

/// </summary>

string query;

/// <summary>

/// Структурированное представление бд.

/// </summary>

XDocument xDoc = new XDocument();

//=======================================================================================

public MainWindow()

{

Log.Initialize();

InitializeComponent();

}

//=======================================================================================

/// <summary>

/// Выход по кнопке в главном меню.

/// </summary>

private void Bt_Exit_Click(object sender, RoutedEventArgs e)

{

Close();

}

/// <summary>

/// Активация кнопок интерфейса (к примеру, после корректной загрузки или создания базы данных).

/// </summary>

private void ActivateButtons()

{

Bt_Table.IsEnabled = true;

Bt_Console.IsEnabled = true;

}

/// <summary>

/// Деактивация кнопок интерфейса.

/// </summary>

private void DeactivateButtons()

{

Bt_Table.IsEnabled = true;

Bt_Console.IsEnabled = true;

}

/// <summary>

/// Событие для создания нового файла базы данных.

/// </summary>

private void Bt_CreateBase_Click(object sender, RoutedEventArgs e)

{

try

{

baseName = NewBase.GetNewBaseName(); //открываем диалоговое окно, из которого получаем имя

//для файла новой базы

if (baseName != null)

{

appPath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), baseName);

//проверим, не создан ли уже такой файл

if (File.Exists(appPath))

if (MessageBox.Show("База: \"" + appPath + "\" уже создана. Переписать?", "Внимание!", System.Windows.MessageBoxButton.YesNo).ToString()

== System.Windows.Forms.DialogResult.No.ToString())

return;

//создаем новый файл базы данных

File.Create(appPath);

//напишем сообщение в строку состояния

StatBar_BottomBar.Items[0] = "База успешно создана: \"" + appPath + "\"";

//напишем сообщение в лог

Log.AddInfo("Base successfully created -> \"" + appPath + "\"");

//-------------------------------------------------------------------

xDoc = new XDocument(new XElement("DataBase"));

xDoc.Root.SetAttributeValue("name", baseName);

TreeViewBuilder.FromXDocument(Tv_BaseNavigator, xDoc);

//-------------------------------------------------------------------

//сделаем доступным интерфейс приложения

ActivateButtons();

}

else return;

}

catch (Exception ex) //если произошла ошибка при создании файла базы

{

MessageBox.Show(ex.Message, "Ошибка при создании базы!"); //покажем на экран

Log.AddInfo("Error on base creating -> " + ex.Message); //и запишем в лог

}

}

/// <summary>

/// Событие для открытия файла базы данных.

/// </summary>

private void Bt_OpenBase_Click(object sender, RoutedEventArgs e)

{

try

{

baseName = OpenBase.GetOpenBaseName(); //открываем диалоговое окно, из которого получаем имя

//файла базы данных, которую необходимо открыть

if (baseName != null)

{

appPath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), baseName);

//напишем сообщение в строку состояния

StatBar_BottomBar.Items[0] = "База успешно загружена: \"" + appPath + "\"";

//напишем сообщение в лог

Log.AddInfo("Base successfully loaded -> \"" + appPath + "\"");

//-------------------------------------------------------------------

BuildXDoc();

TreeViewBuilder.FromXDocument(Tv_BaseNavigator, xDoc);

//-------------------------------------------------------------------

//сделаем доступным интерфейс приложения

ActivateButtons();

}

else return;

}

catch (Exception ex) //если произошла ошибка при создании файла базы

{

MessageBox.Show(ex.Message, "Ошибка при загрузке базы!"); //покажем на экран

Log.AddInfo("Error on base loading -> " + ex.Message); //и запишем в лог

}

}

/// <summary>

/// Добавление в текущую базу новой таблицы.

/// </summary>

private void Bt_CreateTable_Click(object sender, RoutedEventArgs e)

{

try

{

query = NewTable.GetQueryForTableCreate();

if (query != null)

{

//отдаем сформированный запрос провайдеру для обработки и отсылки к базе

if (!SQLiteProvider.ExecuteNonQuery(appPath, query).HasValue)

return;

//напишем сообщение в строку состояния

StatBar_BottomBar.Items[0] = "Таблица успешно создана: #" + query + "#";

//напишем сообщение в лог

Log.AddInfo("Table successfully created -> #" + query + "#");

//-------------------------------------------------------------------

BuildXDoc();

TreeViewBuilder.FromXDocument(Tv_BaseNavigator, xDoc);

//-------------------------------------------------------------------

}

else return;

}

catch (Exception ex) //если произошла ошибка при создании новой таблицы

{

MessageBox.Show(ex.Message, "Ошибка при создании таблицы!"); //покажем на экран

Log.AddInfo("Error on table creating -> " + ex.Message); //и запишем в лог

}

}

/// <summary>

/// Строит стуктуру БД в объект.

/// </summary>

private void BuildXDoc()

{

try

{

xDoc = new XDocument(new XElement("DataBase"));

xDoc.Root.SetAttributeValue("name", baseName);

List<string> tablesNames = SQLiteProvider.GetTablesNames(appPath);

xDoc.Root.SetAttributeValue("tablesCount", tablesNames.Count);

foreach (string s in tablesNames)

{

XElement xEl1 = new XElement("Table");

xEl1.SetAttributeValue("name", s);

query = "SELECT * FROM " + s;

DataRow[] drs = SQLiteProvider.Query(appPath, query);

xEl1.SetAttributeValue("columnsCount", drs[0].Table.Columns.Count);

foreach (DataRow dr in drs)

{

XElement xEl2 = new XElement("Row");

int i = 0;

foreach (object cell in dr.ItemArray)

{

XElement xEl3 = new XElement("Field");

xEl3.SetAttributeValue("name", dr.Table.Columns[i].ColumnName);

xEl3.SetAttributeValue("value", cell);

i++;

xEl2.Add(xEl3);

}

xEl1.Add(xEl2);

}

xDoc.Root.Add(xEl1);

}

}

catch (Exception ex) //если произошла ошибка при генерации объекта, представляющего структуру бд

{

MessageBox.Show(ex.Message, "Ошибка при генерации структуры БД!"); //покажем на экран

Log.AddInfo("Error on building XDocument object -> " + ex.Message); //и запишем в лог

}

}

/// <summary>

/// Действия, которые необходимо выполнить перед закрытием приложения.

/// </summary>

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

/* if (System.Windows.Forms.MessageBox.Show("Приложение будет закрыто. Вы уверены?", "Внимание!", System.Windows.Forms.MessageBoxButtons.YesNo).ToString()

== System.Windows.Forms.DialogResult.No.ToString())

return;*/

xDoc.Save(appPath + ".xml");

Log.Save();

App.Current.Shutdown();

}

}

/// <summary>

/// Класс, позволяющий строить графическое представление иерархически структурированных данных.

/// </summary>

public static class TreeViewBuilder

{

/// <summary>

/// Построение заданного дерева из заданного объекта LINQ.

/// </summary>

/// <param name="treeView">Куда необходимо построить дерево.</param>

/// <param name="xDocument">Откуда взять данные для построения.</param>

/// <returns>True - если постороение успешно, False - если построение не удалось.</returns>

public static bool FromXDocument(TreeView treeView, XDocument xDocument)

{

bool b;

try

{

treeView.Items.Clear();

TreeViewItem treeNode = new TreeViewItem();

treeNode.Header = xDocument.Root.Name.LocalName + ": ";

foreach (XAttribute xA in xDocument.Root.Attributes())

{

treeNode.Header += xA.ToString() + " ";

}

treeNode.IsExpanded = true;

treeView.Items.Add(treeNode);

BuildNodes(treeNode, xDocument.Root);

b = true;

}

catch (Exception ex) //если произошла ошибка при построении дерева

{

MessageBox.Show(ex.Message, "Ошибка при построении дерева базы данных!"); //покажем на экран

Log.AddInfo("Error on building TreeView from XDocument -> " + ex.Message); //и запишем в лог

b = false;

}

return b;

}

/// <summary>

/// Переносит значение "имя тега" + "атрибут имя" из объекта в узел дерева.

/// </summary>

/// <param name="treeNode">Узел, куда надо поместить объект.</param>

/// <param name="element">Объект, который необходимо поместить.</param>

private static void BuildNodes(TreeViewItem treeNode, XElement element)

{

//рекурсивный обход кстати

foreach (XNode child in element.Nodes())

{

switch (child.NodeType)

{

case XmlNodeType.Element:

XElement childElement = child as XElement;

TreeViewItem childTreeNode = new TreeViewItem();

childTreeNode.Header = childElement.Name.LocalName + ": ";

foreach (XAttribute xA in childElement.Attributes())

{

childTreeNode.Header += xA.ToString() + " ";

}

treeNode.Items.Add(childTreeNode);

BuildNodes(childTreeNode, childElement);

break;

case XmlNodeType.Text:

XText childText = child as XText;

treeNode.Items.Add(childText.Value);

break;

}

}

}

}

}

using System;

using System.Windows;

using System.Windows.Input;

namespace SQLiteSampleProject

{

/// <summary>

/// Диалоговое окно с запросом имени для новой базы данных.

/// </summary>

public partial class NewBase : Window

{

/// <summary>

/// Имя базы.

/// </summary>

string baseName;

//=======================================================================================

private NewBase()

{

InitializeComponent();

}

//=======================================================================================

/// <summary>

/// Получить имя базы данных.

/// </summary>

/// <returns>Имя файла новой базы данных.</returns>

public static string GetNewBaseName()

{

NewBase w = new NewBase();

w.ShowDialog(); //важный момент - окно диалоговое и перехватывает управление на себя

return w.baseName;

}

private void Window_Loaded(object sender, RoutedEventArgs e)

{

//добавим удобностей для пользователя:

Tb_NewBaseName.Focus(); //поле для ввода имени получает фокус

Tb_NewBaseName.SelectAll(); //весь текст в поле выбран

}

private void Bt_OK_Click(object sender, RoutedEventArgs e)

{

//проверим, чтобы имя базы было не пустым

if (Tb_NewBaseName.Text != "")

{

//если все верно, то имя базы передаем в выходную переменную и закрываем окно

baseName = Tb_NewBaseName.Text + ".db";

Close();

}

else MessageBox.Show("Введите имя базы!"); //в противном случае просим ввести имя.

}

private void Bt_Cancel_Click(object sender, RoutedEventArgs e)

{

//закроем окно, задав имя базы, как пустое

baseName = null;

Close();

}

private void Tb_NewBaseName_KeyDown(object sender, KeyEventArgs e)

{

//для удобства организуем возможность принять изменения по нажатии клавиши на клавиатуре

if (e.Key == Key.Enter)

{

Bt_OK_Click(Bt_Ok, null);

}

}

private void Window_KeyDown(object sender, KeyEventArgs e)

{

if (e.Key == Key.Escape)

{

Bt_Cancel_Click(null, null);

}

}

}

}

using System;

using System.IO;

using System.Windows;

using System.Windows.Input;

using System.Collections.Generic;

namespace SQLiteSampleProject

{

/// <summary>

/// Диалоговое окно с возможностью выбрать базу данных для открытия.

/// </summary>

public partial class OpenBase : Window

{

/// <summary>

/// Имя базы для загрузки.

/// </summary>

string baseName;

//=======================================================================================

private OpenBase()

{

InitializeComponent();

}

//=======================================================================================

/// <summary>

/// Получить имя базы данных.

/// </summary>

/// <returns>Имя файла базы данных для открытия.</returns>

public static string GetOpenBaseName()

{

OpenBase w = new OpenBase();

w.ShowDialog(); //важный момент - окно диалоговое и перехватывает управление на себя

return w.baseName;

}

private void Window_Loaded(object sender, RoutedEventArgs e)

{

string[] files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.db"); //производим выборку всех файлов баз данных

//(файлов с расширением *.db) из папки приложения

Directory.GetFiles(Directory.GetCurrentDirectory(), "*.db3").CopyTo(files, files.Length - 1); //и с расширением *.db3

Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sqlite").CopyTo(files, files.Length - 1); //и с расширением *.sqlite

foreach (string s in files)

{

Lb_Bases.Items.Add(System.Text.RegularExpressions.Regex.Replace(s, @".+\\", "").ToString());

}

//поле выбора файла базы данных получает фокус

Lb_Bases.Focus();

}

private void Bt_OK_Click(object sender, RoutedEventArgs e)

{

//проверим, чтобы имя базы было не пустым

if (Lb_Bases.SelectedItem != null)

{

//если все верно, то имя базы передаем в выходную переменную и закрываем окно

baseName = Lb_Bases.SelectedItem.ToString();

Close();

}

else MessageBox.Show("База не выбрана!"); //в противном случае просим выбрать базу для загрузки.

}

private void Bt_Cancel_Click(object sender, RoutedEventArgs e)

{

//закроем окно, задав имя базы, как пустое

baseName = null;

Close();

}

private void Lb_Bases_KeyDown(object sender, KeyEventArgs e)

{

//выбор базы на клавишу

if (e.Key == Key.Enter)

{

Bt_OK_Click(Bt_Ok, null);

}

}

private void Lb_Bases_MouseDoubleClick(object sender, MouseButtonEventArgs e)

{

//выбор базы на двойной клик по ней

Bt_OK_Click(Bt_Ok, null);

}

private void Window_KeyDown(object sender, KeyEventArgs e)

{

if (e.Key == Key.Escape)

{

Bt_Cancel_Click(null, null);

}

}

}

}

using System;

using System.Collections.Generic;

using System.Windows;

using System.Windows.Input;

namespace SQLiteSampleProject

{

/// <summary>

/// Диалоговое окно для создания новой таблицы.

/// </summary>

public partial class NewTable : Window

{

/// <summary>

/// Запрос в текстовом виде.

/// </summary>

string query;

/// <summary>

/// Был ли уже задан для таблицы первичный ключ.

/// </summary>

bool hasPrimaryKey = false;

/=======================================================================================

private NewTable()

{

InitializeComponent();

}

//=======================================================================================

/// <summary>

/// Показать окно для формирования запроса.

/// </summary>

/// <returns>Сформированный запрос на создание таблицы.</returns>

public static string GetQueryForTableCreate()

{

NewTable w = new NewTable();

w.ShowDialog();

return w.query;

}

private void Window_Loaded(object sender, RoutedEventArgs e)

{

//добавим удобностей для пользователя:

Tb_NewTableName.Focus(); //поле для ввода имени получает фокус

Tb_NewTableName.SelectAll(); //весь текст в поле выбран

}

private void Bt_AddField_Click(object sender, RoutedEventArgs e)

{

string s = Tb_NewColumnName.Text + " " + Cmb_NewColumnType.Text;

if (Cb_PrimaryKey.IsChecked.Value)

{

//поле определенно, как первичный ключ

s += " PRIMARY KEY";

//далее запрещаем добавление еще одного первичного ключа

Cb_PrimaryKey.IsChecked = false;

Cb_PrimaryKey.IsEnabled = false;

hasPrimaryKey = true;

}

if (Cb_NotNull.IsChecked.Value) s += " NOT NULL";

Lb_Fields.Items.Add(s);

}

private void Bt_OK_Click(object sender, RoutedEventArgs e)

{

//проверим, чтобы было заданно имя для таблицы

if (Tb_NewTableName.Text != "")

{

//проверим, чтобы у таблицы были поля

if (Lb_Fields.HasItems)

{

//и проверим, чтобы был первичный ключ

if (hasPrimaryKey == true)

{

string[] fields = new string[Lb_Fields.Items.Count];

Lb_Fields.Items.CopyTo(fields, 0);

string ifNotEx = "";

if (Cb_IfNotExist.IsChecked.Value) ifNotEx = "IF NOT EXISTS ";

query = "CREATE TABLE " + ifNotEx + Tb_NewTableName.Text + "(";

for (int i = 0; i < Lb_Fields.Items.Count - 1; i++)

query += Lb_Fields.Items[i] + ", ";

query += Lb_Fields.Items[Lb_Fields.Items.Count - 1] + ");";

Close();

}

else MessageBox.Show("Задайте первичный ключ!");

}

else MessageBox.Show("Задайте поля!");

}

else MessageBox.Show("Введите имя таблицы!");

}

private void Bt_Cancel_Click(object sender, RoutedEventArgs e)

{

Close();

}

private void Window_KeyDown(object sender, KeyEventArgs e)

{

if (e.Key == Key.Escape)

{

Bt_Cancel_Click(null, null);

}

}

}

}

using System;

using System.Text;

using System.Collections.Generic;

using System.Data;

using Finisar.SQLite;

namespace SQLiteSampleProject

{

/// <summary>

/// Предоставляет возможность работать с базой данных на языке запросов SQLite.

/// </summary>

public static class SQLiteProvider

{

/// <summary>

/// Возвращает число записей, которые затронуло выполнение запроса. Для получения данных из базы используйте метод Query.

/// </summary>

/// <param name="appPath">Полный путь к файлу базы данных.</param>

/// <param name="sSql">Тект запроса.</param>

/// <returns>Число затронутых записей.</returns>

public static int? ExecuteNonQuery(string appPath, string sSql)

{

int? n = null; //число затронутых записей

try

{

using (SQLiteConnection con = new SQLiteConnection())

{

con.ConnectionString = @"Data Source=" + appPath + ";New=False;Version=3";

//открыть базу для запросов

con.Open();

using (SQLiteCommand sqlCommand = con.CreateCommand())

{

sqlCommand.CommandText = sSql;

n = sqlCommand.ExecuteNonQuery();

}

//закрыть базу

con.Close();

}

}

catch (Exception ex)

{

System.Windows.Forms.MessageBox.Show(ex.Message, "Ошибка при запросе к базе!");

Log.AddInfo("Error on Execute Non Query -> " + ex.Message);

n = null;

}

return n;

}

/// <summary>

/// Возвращает запрошенную информационную строку из таблиц базы данных. Если это не нужно, используйте метод ExecuteNonQuery.

/// </summary>

/// <param name="appPath">Полный путь к файлу базы данных.</param>

/// <param name="sSql">Тект запроса.</param>

/// <returns>Массив строк из базы данных.</returns>

public static DataRow[] Query(string appPath, string sSql)

{

DataRow[] datarows = null;

SQLiteDataAdapter dataadapter = null;

DataSet dataset = new DataSet();

DataTable datatable = new DataTable();

try

{

using (SQLiteConnection con = new SQLiteConnection())

{

con.ConnectionString = @"Data Source=" + appPath + ";New=False;Version=3";

//открыть базу для запросов

con.Open();

using (SQLiteCommand sqlCommand = con.CreateCommand())

{

dataadapter = new SQLiteDataAdapter(sSql, con);

dataset.Reset();

dataadapter.Fill(dataset);

datatable = dataset.Tables[0];

datarows = datatable.Select();

}

//закрыть базу

con.Close();

}

}

catch (Exception ex)

{

System.Windows.Forms.MessageBox.Show(ex.Message, "Ошибка при запросе к базе!");

Log.AddInfo("Error on Query -> " + ex.Message);

datarows = null;

}

return datarows;

}

/// <summary>

/// Возвращает имена всех созданных в базе данных таблиц.

/// </summary>

/// <param name="appPath">Полный путь к файлу базы данных.</param>

/// <returns>Массив имен всех таблиц.</returns>

public static List<string> GetTablesNames(string appPath)

{

List<string> s = new List<string>();

try

{

using (SQLiteConnection con = new SQLiteConnection())

{

con.ConnectionString = @"Data Source=" + appPath + ";New=False;Version=3";

string query = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;";

//открыть базу для запросов

con.Open();

using (SQLiteCommand sqlCommand = con.CreateCommand())

{

sqlCommand.CommandText = query;

SQLiteDataReader reader = sqlCommand.ExecuteReader();

foreach (IDataRecord record in reader)

s.Add(record["name"].ToString());

}

//закрыть базу

con.Close();

Log.AddInfo("Get tables names success -> #" + query + "#");

}

}

catch (Exception ex)

{

System.Windows.Forms.MessageBox.Show(ex.Message, "Ошибка при запросе к базе!");

Log.AddInfo("Error on Get Tables Names -> " + ex.Message);

s = null;

}

return s;

}

}

}

using System;

using System.IO;

using System.Text.RegularExpressions;

namespace SQLiteSampleProject

{

/// <summary>

/// Класс, поддерживающий создание и ведение лога текущего запуска.

/// </summary>

public static class Log

{

/// <summary>

/// Текст лога текущего запуска.

/// </summary>

public static string Data { get; private set; }

/// <summary>

/// Показывает, был ли инициализирован лог текущего запуска.

/// </summary>

static bool initialized = false;

/// <summary>

/// Содержит дату-время инициализации лога текущего запуска.

/// </summary>

static DateTime startAt;

//=======================================================================================

/// <summary>

/// Инициализация лога текущего запуска.

/// </summary>

public static void Initialize()

{

if (!(initialized))

{

startAt = DateTime.Now;

Data = "********** Log Start At [" + startAt.ToString() + "]**********\r\n\r\n";

initialized = true;

}

else System.Windows.Forms.MessageBox.Show("Лог текущего запуска уже инициализирован", "Запрещенная операция!");

}

/// <summary>

/// Добавление в лог сообщения по текущему системному времени.

/// </summary>

/// <param name="text">Текст сообщения</param>

public static void AddInfo(string text)

{

if (initialized)

Data += "[" + DateTime.Now.ToString() + "]: " + text + "\r\n";

else System.Windows.Forms.MessageBox.Show("Попытка добавить сообщение в неинициализированный лог", "Запрещенная операция!");

}

/// <summary>

/// Создает текстовый файл с текстом лога текущего запуска.

/// </summary>

public static void Save()

{

if (initialized)

{

//проверяем, чтобы была создана папка для логов - или создадим её

if (!Directory.Exists(Directory.GetCurrentDirectory() + "\\logs"))

Directory.CreateDirectory(Directory.GetCurrentDirectory() + "\\logs");

//удаляем наиболее старые логи, чтобы не переполнять папку

string[] files = Directory.GetFiles(Directory.GetCurrentDirectory() + "\\logs");

if (files.Length >= 10) File.Delete(files[0]);

//запишем текущие дату-время, как время окончания ведения лога

Data += "\r\n********** Log End At [" + DateTime.Now.ToString() + "]**********\r\n\r\n";

//сохраним лог в файл

File.AppendAllText(Directory.GetCurrentDirectory() + "\\logs\\log(" +

Regex.Replace(startAt.ToString(), "[:]", "-") + ").txt", Data);

//после сохранения мы не сможем писать в лог, пока не инициализируем его заново

Data = ""; initialized = false;

}

else System.Windows.Forms.MessageBox.Show("Попытка сохранить неинициализированный лог", "Запрещенная операция!");

}

}

}

Приложение 2

Схема запроса create table.

create-table:

column-def:

type-name:

column-constraint:

table-constraint:

foreign-key-clause:

Приложение 3

Пример полученного XML-файла

<DataBase name="nwind2009.db3" tablesCount="9">

<Table name="Shippers" columnsCount="3">

<Row>

<Field name="ShipperID" value="1" />

<Field name="CompanyName" value="Speedy Express" />

<Field name="Phone" value="(503) 555-9831" />

</Row>

<Row>

<Field name="ShipperID" value="2" />

<Field name="CompanyName" value="United Package" />

<Field name="Phone" value="(503) 555-3199" />

</Row>

<Row>

<Field name="ShipperID" value="3" />

<Field name="CompanyName" value="Federal Shipping" />

<Field name="Phone" value="(503) 555-9931" />

</Row>

</Table>

…………….

</DataBase>

Размещено на Allbest.ru


Подобные документы

  • Система управления базой данных - программный инструмент создания БД и приложений пользователя. Проект СУБД "ИС Продажа видео и аудио продукции". Разработка иерархической, сетевой и реляционной моделей, таблиц и схемы базы данных, форм, отчетов, запросов.

    курсовая работа [1,6 M], добавлен 17.06.2013

  • Разработка информационного обеспечения задачи, определение логической структуры реляционной базы данных. Разработка запросов и отчетов для обработки и отображения информации, интерфейса пользователя. Методика и этапы физического проектирования задачи.

    курсовая работа [33,5 K], добавлен 25.07.2012

  • Система управления базами данных (СУБД) как программная система для создания общей базы данных. Создание СУБД для управления поставкой и реализацией ювелирных изделий. Типы данных, физическая и логическая модели. Разработка интерфейса пользователя.

    курсовая работа [467,8 K], добавлен 14.12.2012

  • Выделение информационных объектов и их инфологическая модель. Логическая структура реляционной базы данных. Разработка таблиц в системе управления базами данных Access. Создание запросов, форм и отчетов в СУБД Access. Разработка приложения пользователя.

    курсовая работа [2,8 M], добавлен 05.02.2018

  • Составление схемы концептуальной модели данных. Разработка структуры реляционной базы данных и интерфейса пользователя. Особенности главных этапов проектирования базы данных. Способы реализации запросов и отчетов. Специфика руководства пользователя.

    курсовая работа [186,9 K], добавлен 18.12.2010

  • Проектирование базы данных на основе модели типа объект-отношение. Создание таблиц средствами СУБД Access, главной кнопочной формы и запросов с помощью операций реляционной алгебры. Изменение последовательности перехода. Введение всплывающей подсказки.

    курсовая работа [681,4 K], добавлен 16.01.2015

  • Стадии разработки программного продукта "BaseSurvey ECC" с помощью Delphi 2010 и SQLite. Проектирование интерфейса пользователя и разработка алгоритмов работы электронного журнала учёта осмотра мест происшествий. Разработка руководства пользователя.

    курсовая работа [1,9 M], добавлен 12.07.2012

  • Классификации баз данных и СУБД. Технология модели "клиент-сервер". Особенности языка структурированных запросов SQL. Структура и назначение операторов определения, манипулирования и управления данными. Разработка реляционной БД, создание SQL запросов.

    курсовая работа [1,4 M], добавлен 17.08.2015

  • Разработка пользовательского интерфейса и создание базы данных на основе реляционной СУБД Microsoft Access. Процедуры для ввода, корректировки, просмотра входных данных, их обработка и анализ. Формирование запросов и отчетов, их вывод на экран монитора.

    курсовая работа [2,7 M], добавлен 03.05.2014

  • Путь обработки запроса в реляционной СУБД. Оптимизации запросов на примере Oracle 9.2. Исследования по оптимизации планов выполнения запросов за счёт нормализации таблиц, выбора табличного пространства и распределения таблиц по этому пространству.

    курсовая работа [364,8 K], добавлен 12.01.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.