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

 

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

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

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

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

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

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







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


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



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

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

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

Исполнитель

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

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

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

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


Иркутск 2012г.


Содержание


Введение

. Базы данных

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

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

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

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

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

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

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

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

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

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

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

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

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

Заключение

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

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

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



Введение


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

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

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

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

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

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

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

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

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

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

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


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


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


Как было сказано выше, реализация SQLite представляет собой СУБД, расположенную внутри отдельной программной библиотеки, написанной на языке C. Библиотека самой последней на текущий момент версии SQLite3 занимает всего около 300 килобайт и может быть использована в большинстве современных языков программирования. Для использования на платформе .Net (Mono) на сайте www.sqlite.org <#"justify">·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.Построение запросов к БД через заполнение диалоговых форм (решение задачи 1, часть 2)


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



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


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

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

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

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


//проверим, чтобы было заданно имя для таблицы(Tb_NewTableName.Text != "")

{

//проверим, чтобы у таблицы были поля(Lb_Fields.HasItems)

{

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

if (hasPrimaryKey == true)

{[] fields = new string[Lb_Fields.Items.Count];_Fields.Items.CopyTo(fields, 0);

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

= "CREATE TABLE " + ifNotEx + Tb_NewTableName.Text + "(";(int i = 0; i < Lb_Fields.Items.Count - 1; i++)+= Lb_Fields.Items[i] + ", ";+= Lb_Fields.Items[Lb_Fields.Items.Count - 1] + ");";

();

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

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

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


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

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



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


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


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


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

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

Синтаксис:

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

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

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

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

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


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


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

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

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

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

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

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

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


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


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

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


/// <summary>

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

/// </summary>void BuildXDoc()

{

{= new XDocument(new XElement("DataBase"));.Root.SetAttributeValue("name", baseName);

<string> tablesNames = SQLiteProvider.GetTablesNames(appPath);.Root.SetAttributeValue("tablesCount", tablesNames.Count);

(string s in tablesNames)

{xEl1 = new XElement("Table");.SetAttributeValue("name", s);

= "SELECT * FROM " + s;[] drs = SQLiteProvider.Query(appPath, query);

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

(DataRow dr in drs)

{xEl2 = new XElement("Row");

i = 0;(object cell in dr.ItemArray)

{xEl3 = new XElement("Field");.SetAttributeValue("name", dr.Table.Columns[i].ColumnName);.SetAttributeValue("value", cell);++;.Add(xEl3);

}.Add(xEl2);

}.Root.Add(xEl1);

}


}


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

Заключение


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

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

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

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

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

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

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

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



Приложение 1


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


using System;

using System.IO;System.Collections.Generic;System.Data;System.Linq;System.Xml;System.Xml.Linq;System.Text;System.Windows;System.Windows.Controls;System.Windows.Data;System.Windows.Documents;System.Windows.Input;System.Windows.Media;System.Windows.Media.Imaging;System.Windows.Navigation;System.Windows.Shapes;Finisar.SQLite;

SQLiteSampleProject

{partial class MainWindow : Window

{

/// <summary>

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

/// </summary>appPath;


/// <summary>

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

/// </summary>baseName;


/// <summary>

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

/// </summary>

string query;


/// <summary>

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

/// </summary>xDoc = new XDocument();


//=======================================================================================MainWindow()

{.Initialize();();

}


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

/// <summary>

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

/// </summary>void Bt_Exit_Click(object sender, RoutedEventArgs e)

{();

}

/// <summary>

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

/// </summary>void ActivateButtons()

{_Table.IsEnabled = true;_Console.IsEnabled = true;

}



/// <summary>

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

/// </summary>void DeactivateButtons()

{_Table.IsEnabled = true;_Console.IsEnabled = true;

}


/// <summary>

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

/// </summary>void Bt_CreateBase_Click(object sender, RoutedEventArgs e)

{

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

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

(baseName != null)

{

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


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

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

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

return;


//создаем новый файл базы данных.Create(appPath);


//напишем сообщение в строку состояния_BottomBar.Items[0] = "База успешно создана: " + appPath + "";


//напишем сообщение в лог.AddInfo("Base successfully created -> " + appPath + "");



//-------------------------------------------------------------------= new XDocument(new XElement("DataBase"));.Root.SetAttributeValue("name", baseName);

.FromXDocument(Tv_BaseNavigator, xDoc);

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


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

}return;

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

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

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

}

}


/// <summary>

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

/// </summary>void Bt_OpenBase_Click(object sender, RoutedEventArgs e)

{

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

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

if (baseName != null)

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


//напишем сообщение в строку состояния_BottomBar.Items[0] = "База успешно загружена: " + appPath + "";


//напишем сообщение в лог.AddInfo("Base successfully loaded -> " + appPath + "");



//-------------------------------------------------------------------();.FromXDocument(Tv_BaseNavigator, xDoc);

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


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

}return;

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

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

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

}

}

/// <summary>

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

/// </summary>void Bt_CreateTable_Click(object sender, RoutedEventArgs e)

{

{= NewTable.GetQueryForTableCreate();

(query != null)

{

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

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

return;


//напишем сообщение в строку состояния_BottomBar.Items[0] = "Таблица успешно создана: #" + query + "#";


//напишем сообщение в лог.AddInfo("Table successfully created -> #" + query + "#");


//-------------------------------------------------------------------();.FromXDocument(Tv_BaseNavigator, xDoc);

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


}return;

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

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

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

}

}


/// <summary>

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

/// </summary>void BuildXDoc()

{

{= new XDocument(new XElement("DataBase"));.Root.SetAttributeValue("name", baseName);

<string> tablesNames = SQLiteProvider.GetTablesNames(appPath);.Root.SetAttributeValue("tablesCount", tablesNames.Count);

(string s in tablesNames)

{xEl1 = new XElement("Table");.SetAttributeValue("name", s);

= "SELECT * FROM " + s;[] drs = SQLiteProvider.Query(appPath, query);.SetAttributeValue("columnsCount", drs[0].Table.Columns.Count);

(DataRow dr in drs)

{xEl2 = new XElement("Row");

i = 0;(object cell in dr.ItemArray)

{xEl3 = new XElement("Field");.SetAttributeValue("name", dr.Table.Columns[i].ColumnName);.SetAttributeValue("value", cell);++;.Add(xEl3);

}.Add(xEl2);

}.Root.Add(xEl1);

}


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

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

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

}

}

/// <summary>

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

/// </summary>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());*/.Save(appPath + ".xml");.Save();.Current.Shutdown();

}


}


/// <summary>

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

/// </summary>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)

{b;

{.Items.Clear();

treeNode = new TreeViewItem();.Header = xDocument.Root.Name.LocalName + ": ";(XAttribute xA in xDocument.Root.Attributes())

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

}.IsExpanded = true;.Items.Add(treeNode);

(treeNode, xDocument.Root); = true;

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

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

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

}b;

}


/// <summary>

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

/// </summary>

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

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

private static void BuildNodes(TreeViewItem treeNode, XElement element)

{

//рекурсивный обход кстати(XNode child in element.Nodes())

{(child.NodeType)

{XmlNodeType.Element:childElement = child as XElement;childTreeNode = new TreeViewItem();.Header = childElement.Name.LocalName + ": ";(XAttribute xA in childElement.Attributes())

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

}.Items.Add(childTreeNode);(childTreeNode, childElement);;XmlNodeType.Text:childText = child as XText;.Items.Add(childText.Value);;

}

}

}

}


}

System;System.Windows;System.Windows.Input;

SQLiteSampleProject

{

/// <summary>

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

/// </summary>partial class NewBase : Window

{

/// <summary>

/// Имя базы.

/// </summary>baseName;


//=======================================================================================NewBase()

{();

}

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

/// <summary>

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

/// </summary>

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

{w = new NewBase();

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


return w.baseName;

}

void Window_Loaded(object sender, RoutedEventArgs e)

{

//добавим удобностей для пользователя:_NewBaseName.Focus(); //поле для ввода имени получает фокус_NewBaseName.SelectAll(); //весь текст в поле выбран

}

void Bt_OK_Click(object sender, RoutedEventArgs e)

{

//проверим, чтобы имя базы было не пустым(Tb_NewBaseName.Text != "")

{

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

baseName = Tb_NewBaseName.Text + ".db";

Close();

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

}

void Bt_Cancel_Click(object sender, RoutedEventArgs e)

{

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

baseName = null;();

}

void Tb_NewBaseName_KeyDown(object sender, KeyEventArgs e)

{

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

if (e.Key == Key.Enter)

{_OK_Click(Bt_Ok, null);

}

}

void Window_KeyDown(object sender, KeyEventArgs e)

{(e.Key == Key.Escape)

{_Cancel_Click(null, null);

}

}


}

}

System;System.IO;System.Windows;System.Windows.Input;System.Collections.Generic;

SQLiteSampleProject

{

/// <summary>

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

/// </summary>partial class OpenBase : Window

{

/// <summary>

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

/// </summary>baseName;


//=======================================================================================OpenBase()

{();

}


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

/// <summary>

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

/// </summary>

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

public static string GetOpenBaseName()

{w = new OpenBase();

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


return w.baseName;

}

void Window_Loaded(object sender, RoutedEventArgs e)

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

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

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

(string s in files)

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

}


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

Lb_Bases.Focus();

}

void Bt_OK_Click(object sender, RoutedEventArgs e)

{

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

if (Lb_Bases.SelectedItem != null)

{

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

baseName = Lb_Bases.SelectedItem.ToString();

Close();

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

}

void Bt_Cancel_Click(object sender, RoutedEventArgs e)

{

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

baseName = null;();

}

void Lb_Bases_KeyDown(object sender, KeyEventArgs e)

{

//выбор базы на клавишу(e.Key == Key.Enter)

{_OK_Click(Bt_Ok, null);

}

}

void Lb_Bases_MouseDoubleClick(object sender, MouseButtonEventArgs e)

{

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

Bt_OK_Click(Bt_Ok, null);

}

void Window_KeyDown(object sender, KeyEventArgs e)

{(e.Key == Key.Escape)

{_Cancel_Click(null, null);

}

}


}

}

System;System.Collections.Generic;System.Windows;System.Windows.Input;SQLiteSampleProject

{

/// <summary>

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

/// </summary>partial class NewTable : Window

{

/// <summary>

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

/// </summary>query;


/// <summary>

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

/// </summary>hasPrimaryKey = false;


/=======================================================================================NewTable()

{();

}


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

/// <summary>

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

/// </summary>

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

public static string GetQueryForTableCreate()

{w = new NewTable();.ShowDialog();

w.query;

}

void Window_Loaded(object sender, RoutedEventArgs e)

{

//добавим удобностей для пользователя:_NewTableName.Focus(); //поле для ввода имени получает фокус_NewTableName.SelectAll(); //весь текст в поле выбран

}

void Bt_AddField_Click(object sender, RoutedEventArgs e)

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

(Cb_PrimaryKey.IsChecked.Value)

{

//поле определенно, как первичный ключ+= " PRIMARY KEY";


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

Cb_PrimaryKey.IsChecked = false;_PrimaryKey.IsEnabled = false;= true;

}(Cb_NotNull.IsChecked.Value) s += " NOT NULL";_Fields.Items.Add(s);

}

void Bt_OK_Click(object sender, RoutedEventArgs e)

{

//проверим, чтобы было заданно имя для таблицы(Tb_NewTableName.Text != "")

{

//проверим, чтобы у таблицы были поля(Lb_Fields.HasItems)

{

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

if (hasPrimaryKey == true)

{[] fields = new string[Lb_Fields.Items.Count];_Fields.Items.CopyTo(fields, 0);

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

= "CREATE TABLE " + ifNotEx + Tb_NewTableName.Text + "(";(int i = 0; i < Lb_Fields.Items.Count - 1; i++)+= Lb_Fields.Items[i] + ", ";+= Lb_Fields.Items[Lb_Fields.Items.Count - 1] + ");";

();

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

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

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

}

void Bt_Cancel_Click(object sender, RoutedEventArgs e)

{();

}

void Window_KeyDown(object sender, KeyEventArgs e)

{(e.Key == Key.Escape)

{_Cancel_Click(null, null);

}

}


}

}

System;System.Text;System.Collections.Generic;

System.Data;Finisar.SQLite;

SQLiteSampleProject

{

/// <summary>

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

/// </summary>static class SQLiteProvider

{

/// <summary>

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

/// </summary>

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

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

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

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

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

try

{(SQLiteConnection con = new SQLiteConnection())

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


//открыть базу для запросов.Open();


using (SQLiteCommand sqlCommand = con.CreateCommand())

{.CommandText = sSql;= sqlCommand.ExecuteNonQuery();

}

//закрыть базу.Close();

}

}(Exception ex)

{.Windows.Forms.MessageBox.Show(ex.Message, "Ошибка при запросе к базе!");.AddInfo("Error on Execute Non Query -> " + ex.Message);= null;

}n;

}


/// <summary>

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

/// </summary>

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

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

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

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

{[] datarows = null;dataadapter = null;dataset = new DataSet();datatable = new DataTable();

{(SQLiteConnection con = new SQLiteConnection())

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


//открыть базу для запросов.Open();


using (SQLiteCommand sqlCommand = con.CreateCommand())

{= new SQLiteDataAdapter(sSql, con);.Reset();.Fill(dataset);= dataset.Tables[0];= datatable.Select();

}


//закрыть базу.Close();

}

}(Exception ex)

{.Windows.Forms.MessageBox.Show(ex.Message, "Ошибка при запросе к базе!");.AddInfo("Error on Query -> " + ex.Message);= null;

}datarows;

}


/// <summary>

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

/// </summary>

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

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

public static List<string> GetTablesNames(string appPath)

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


{(SQLiteConnection con = new SQLiteConnection())

{.ConnectionString = @"Data Source=" + appPath + ";New=False;Version=3";query = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;";


//открыть базу для запросов.Open();


using (SQLiteCommand sqlCommand = con.CreateCommand())

{.CommandText = query;reader = sqlCommand.ExecuteReader();

(IDataRecord record in reader).Add(record["name"].ToString());

}

//закрыть базу.Close();

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

}

}(Exception ex)

{.Windows.Forms.MessageBox.Show(ex.Message, "Ошибка при запросе к базе!");.AddInfo("Error on Get Tables Names -> " + ex.Message);= null;

}s;

}


}

}

System;System.IO;System.Text.RegularExpressions;


SQLiteSampleProject

{

/// <summary>

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

/// </summary>static class Log

{

/// <summary>

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

/// </summary>static string Data { get; private set; }


/// <summary>

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

/// </summary>bool initialized = false;


/// <summary>

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

/// </summary>DateTime startAt;


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

/// <summary>

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

/// </summary>

public static void Initialize()

{(!(initialized))

{= DateTime.Now;= "********** Log Start At [" + startAt.ToString() + "]**********\r\n\r\n";= true;

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

}


/// <summary>

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

/// </summary>

/// <param name="text">Текст сообщения</param>static void AddInfo(string text)

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

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

}


/// <summary>

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

/// </summary>static void Save()

{(initialized)

{

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

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


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

string[] files = Directory.GetFiles(Directory.GetCurrentDirectory() + "\\logs");(files.Length >= 10) File.Delete(files[0]);

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

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


//сохраним лог в файл.AppendAllText(Directory.GetCurrentDirectory() + "\\logs\\log(" +.Replace(startAt.ToString(), "[:]", "-") + ").txt", Data);


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

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

}

}

}



Приложение 2


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


create-table:


column-def:


type-name:


column-constraint: 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>


Федеральное агентство по образованию Государственное образовательное учреждение Высшего профессионального образования ИРКУТСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРС

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ