Как составить базы каталогов

РЭДЛАЙН

Лучшие решения для Вас и Вашего бизнеса!

На нашем сайте вы можете получить информацию о веб-разработке, обслуживании и продвижении сайта. Интернет-маркетинге. SEO (поисковой оптимизации). Контекстной и медийной рекламе в Интернете. SMM. Регистрации доменов и хостинговых услугах. И современном дизайне сайтов. Вообщем того что касается веб-разработки, а также много другой полезной информации из мира интернета, бизнеса и интернет-технологий…



Как составить свою базу каталогов статей?

Сразу же возникает вопрос, нужна ли своя база, если в Интернете можно найти уже готовую и ее пользоваться . Не спорю, есть такие, встречал. Но как правило такие базы не первой свежести и составлялись они по принципу, чем больше, тем лучше.

Лично я проверил 4-5 таких баз. Что могу сказать, из таких списков можно смело удалять 90-95% каталогов. Так как в большинство каталогов не то, что статью нельзя разместить, их самих как таковых нет. А в те, которые еще находятся по своему адресу, уже 1-2 года как не добавлялись новые статьи.

Да зачем далеко ходить, возьмем к примеру мою базу каталогов статей. Я начал составлять ее месяца 2-3 назад. Получается как бы база достаточно свежая. Да не тут то было. При перепроверке мне пришлось удалить по тем или иным причинам около 40 каталогов. Вот так вот. Так что, если Вы не уверенны в том, что база каталогов, которой Вы пользуетесь, постоянно обновляется, то самое время составить свою.

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

  1. Каталоги, которые разрешают использовать ссылки из текста статьи. Эти ссылки имеют наибольшый вес.
  2. Каталоги, которые допускают одну ссылку, но не из текста статьи, а находящуюся вблизи статьи. На сегодняшний день такие ссылки утратили свою актуальность.
  3. Каталоги, которые размещают текст статьи, но не ставят ни одной ссылки на Ваш сайт. Оказывается есть и такие.

Буквально несколько дней назад, разместил одну из своих статей в одном таком каталоге. При добавлении статьи в этот каталог воспользовался функцией предварительного просмотра (у большинства каталогов есть такая возможность, перед отправкой статьи администратору посмотреть, как будет выглядеть статья в каталоге), так вот, при просмотре моя статья отображалась должным образом, имя автора, ссылки, абзацы, маркированные и нумерованные списки, в общем все как надо. Прошло 3-4 дня и моя статья появилась на страницах этого каталога, но в статье не было не то, что имени автора или ссылок, а даже абзацов. Я просмотрел другие статьи этого каталога – та же самая картина.

Этот сайт, в который я добавлял статью, имеет PR-4 и ТИЦ-90, что для каталога статей достаточно хороший показатель. Но нам пользы от этих показателей нет никакой, так как на наш сайт нет ссылок. Исходя из этого, третий тип каталогов отбрасываем сразу.

Второй тип — когда ссылка находится вблизи статьи, можно рассматривать в том случае, если каталог имеет приличные показатели по PR и ТИЦ. Или в том случае, когда Вы хотите заявить о себе как автор, то есть ссылки на Ваш сайт для Вас роли не играют.

Все свое внимание мы уделим первому типу (каталогам, разрешающим использовать ссылки из текста статьи), и именно из таких каталогов мы и будем формировать свою базу каталогов статей.

Итак, Вы наткнулись на очередной каталог статей, и хотите добавить его в свой список каталогов, обратите внимание на такие пункты:

  • допускаются ли ссылки из текста статьи. Если об этом нигде не говорится, но в тексте статьи разрешены HTML или BB код, статья добавляется с помощью визуального редактора, то практически во всех каталогах это признак того, что ссылки разрешены;
  • обратите свое внимание на раздел «последние статьи». В том случае, когда последние статьи добавлены больше месяца назад, это первый признак того, что на этот каталог не стоит тратить свое время. Если нет раздела «последние статьи» ищите раздел «архив»;
  • посмотрите на какие темы можно добавлять статьи в этот каталог. Каталог ориентированный на все, что связанно с мебелью не разместит статью о тортах;
  • с помощью сервисов для анализа сайта определите, какой PR и ТИЦ имеет данный каталог, есть ли он в индексе поисковиков.

Если найденный Вами каталог отвечает всем перечисленным требованиям, можете смело добавлять свою статью.  Но это еще не все. После того, как Вы добавили статью, Вам надо дождаться когда страница с Вашей статьей будет проиндексирована. При добавлении статьи в хороший каталог она появится в индексе поисковиков на 2-3 день. Но это не значит, что если страница какого-то каталога с Вашей статьей появится через месяц, то в этот каталог больше не следует добавлять статьи. Месяц это приемлемые сроки.

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

  • Комментарии

Статьи по теме

43 способа увеличить интернет-продажи

Не все принципы роста продаж обычного магазина работают для онлайн-бизнеса. Клиент не может потрогать и оценить реальный вид товара или …

2020-02-27

Как составить свою базу каталогов статей? |

2011-04-30 12:13:02 | 2011-04-30 12:13:02 |

|

Статьи и новости Интернет-маркетинга |


|


Сразу же возникает вопрос, нужна ли своя база, если в Интернете можно найти уже готовую и ее пользоваться . Не спорю, есть такие, встречал. Но как правило такие базы не первой свежести и составлялись
|


РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск
|

Дайджест новых статей по интернет-маркетингу на ваш email

Подписаться

Продающие сайты «под ключ»!

Наши сайты зарабытывают вам деньги. Landing-page. Эффективные продающие сайты точно в срок и под ключ! Всего от 14700 рублей
Подробнее…

Интернет-магазины и каталоги «под ключ»!

Эффективные и удобные инструменты торговли (электронной торговли) «под ключ». Продают, даже когда вы спите! Всего от 33800 рублей
Подробнее…

Комплексный интернет-маркетинг и продвижение сайтов

Максимальную эффективность дает не какой-то конкретный метод, а их комбинация. Комбинация таких методов и называется комплексным интернет-маркетингом. Всего от 8000 рублей в месяц
Подробнее…

Реклама в Yandex и Google

Контекстная реклама нацелена лишь на тех пользователей, которые непосредственно заинтересованы в рекламе Ваших услуг или товаров. Всего от 8000 рублей в месяц
Подробнее…

Social media marketing (SMM) — продвижение в социальных медиа

Реклама в Однокласcниках и на Mail.ru Создание, ведение и раскрутка групп и реклама ВКонтакте и Facebook. Всего от 8000 рублей в месяц
Подробнее…

Приглашаем к сотрудничеству рекламные агентства и веб-студии!

Внимание Акция! Приглашаем к сотрудничеству рекламные агентства и различные веб-студии России! Индивидуальные и взаимовыгодные условия сотрудничества.
Подробнее…

Ускоренная разработка любого сайта от 5 дней!

Внимание Акция! Ускоренная разработка любого сайта! Ваш сайт будет готов за 5-10 дней. Вы можете заказать разработку любого сайта «под ключ» за 5-10 рабочих дней, с доплатой всего 30% от его стоимости!
Подробнее…

Ждем новых друзей!

Внимание Акция! Ждем новых друзей! Скидка 10% на услуги по созданию и(или) обслуживанию вашего сайта при переходе к нам от другого разработчика.
Подробнее…

Приведи друга и получи скидку!

Внимание Акция! Приведи друга и получи скидку! Скидка 10% на услуги по созданию и(или) обслуживанию вашего сайта, если клиент заказавший наши услуги, пришел по Вашей рекомендации.
Подробнее…

Темы

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

Сенека Луций Анней — (1 до н. э. / 1 н. э.- 65 н. э.) — римский государственный деятель, писатель, философ

Остались еще вопросы? Просто позвоните и задайте их специалистам

Важная часть любого информационного проекта — это представление данных, в частности, формирование каталога. Сегодня появляется большое количество систем, основной задачей которых является каталогизация данных, причем в каждой из них заложены свои принципы формирования каталога, методы реализации которых часто уникальны и представляют собой «ноу-хау» разработчиков. В статье рассказывается об одном из методов создания каталога данных, который может быть интересен тем, кто впервые столкнулся с такой проблемой. Приводится пример проектирования Internet-каталога, а также разбираются основные приемы работы с ним средствами СУБД Oracle.

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

Сегодня появляется большое количество таких систем, основной задачей которых является классификация (каталогизация) данных: каталог информационных ресурсов Сети, электронная библиотека, Internet-магазин, законодательная база данных и т.п. В каждой из них заложены свои принципы формирования каталога, методы реализации которых представляют собой «ноу-хау» разработчиков. Рассмотрим один из методов создания каталога данных, который, быть может, и не уникален, но интересен и доступен для тех, кто впервые столкнулся с такой проблемой.

Принципы построения каталога

В основе любого каталога лежат три сущности: тематические разделы (категории), образующие иерархически зависимую структуру; связи, которые существуют между отдельными тематическими разделами; объекты рассматриваемой области, принадлежащие соответствующим разделам.

Объекты — любые предметы рассматриваемой области, обладающие определенными свойствами, поведением и т.п. Например, если речь идет о классификации Internet-ресурсов, то объектами можно считать сайты, посвященные той или иной теме, которая в данном случае является его свойством: скажем, www.gov.ru — органы государственной власти; www.culture.ru — новости культуры и искусства; www.movies.ru — кинофильмы; www.itar-tass.com — Информационное телеграфное агентство России.


Рис.1. Пример каталога

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

На самом верхнем уровне иерархии находится раздел «Интернет», который в данном случае является рассматриваемой областью. Он содержит такие разделы, как «Культура», «Политика», «СМИ». Те, в свою очередь, содержат другие подразделы и т.д.

Рассмотрев первые две сущности, выделим основные атрибуты, которыми они должны обладать. Для объекта — это его название, а также название или идентификатор раздела, к которому принадлежит объект. Для тематических разделов — это название, идентификатор, а также идентификатор родительского раздела.


Рис. 2. Пример каталога со связями

Некоторые группы объектов могут быть по смыслу связаны с другими группами, находящимися на других ветвях иерархии. Как это видно из рис. 1, такими связями могут обладать подразделы «Политика» и «Культура» раздела «СМИ», которые образуют смысловые связи с разделами «Политика» и «Культура». На рис. 2 эти связи указаны в виде ссылок на соответствующие разделы «СМИ».

Другими словами, все объекты, принадлежащие, например, разделу «Интернет/СМИ/Информационные агентства/Политика», могут быть отнесены в виртуальный подраздел «Политические новости» раздела «Интернет/Политика».

Основные атрибуты, которыми должны обладать связи, — это идентификатор раздела, содержащий объекты; идентификатор раздела, к которому привязывают эти объекты и псевдоним виртуального подраздела.

Помимо описания связей между разделами может возникнуть необходимость описать связи между отдельными объектами и разделами. Например, в разделе «Интернет/СМИ/Информационные агентства» может находиться сайт информационного агентства, который освещает события как политики, так и культуры. Было бы желательно, чтобы этот сайт был также виден из раздела «Интернет/Политика», не привязывая к нему целый раздел «Информационные агентства». Для описания такой связи («раздел-объект») можно определить новую сущность с атрибутами: идентификатор раздела, к которому нужно привязать данный объект и идентификатор этого объекта.

Представление каталога в базе данных


Рис. 3. Схема
базы данных

Определив три основные сущности каталога и его атрибуты, мы тем самым определили три таблицы базы данных и отношения между ними [2]. На примере проектирования Web-каталога, схема базы данных в нотациях UML [3] будет иметь вид, представленный на рис. 3.

Схема описывает три типа таблиц.

  • OBJECTS — таблица, содержащая объекты: id — идентификатор объекта; category_id — идентификатор раздела, к которому принадлежит объект; title — название объекта; url — адрес в Internet; description — описание объекта.
  • CATEGORIES — таблица, содержащая тематические разделы: category_id — идентификатор тематического раздела; parent_id — идентификатор родительского раздела; title — название раздела; description — описание раздела.
  • LINKS — таблица, содержащая описание связей между тематическими разделами: id — идентификатор связи; source_id — идентификатор раздела-источника; destination_id — идентификатор раздела, содержащего ссылку на источник; alias — псевдоним ссылки.

На языке SQL эти таблицы со всеми ограничениями целостности создаются следующими командами [4]:

Основная идея построения дерева заключена в соответствующей структуре таблицы CATEGORIES, в которой есть два поля: category_id и parent_id. Первое содержит уникальный идентификатор тематического раздела, а второе идентификатор родительского раздела, к которому принадлежит данный раздел (таблица 1). Причем одному и тому же родительскому разделу может принадлежать сколь угодно много дочерних разделов.

Допустим, таблица LINKS выглядит, как указано на таблице 2, а OBJECTS — как указано на таблице 3.

Для наглядности рассмотрим некоторые примеры SQL-запросов с использованием синтаксиса Oracle 9i. Добавление таких конструкций как START WITH и CONNECT BY в предложение SELECT позволяет делать различные выборки в каталоге одним запросом, избавляя разработчиков писать громоздкие хранимые процедуры. Эти конструкции являются внутренним стандартом Oracle, но реализация показанных далее запросов возможна и для других СУБД, в которых имеется возможность использования процедурного языка запросов.

Пример 1. Вывод заданной ветви каталога
сверху вниз
SELECT category_id, parent_id, title
FROM categories
START WITH category_id = 4
CONNECT BY PRIOR category_id = parent_id;

Конструкция START WITH указывает, с какого раздела следует начать движение по дереву, CONNECT BY связывает номера разделов поля category_id, с соответствующими номерами разделов поля parent_id. PRIOR, стоящий перед category_id, указывает на то, что поле category_id идентифицирует тематические разделы.

Результатом запроса будет вывод заданной ветви каталога, начиная с раздела ?СМИ? и заканчивая всеми ее подразделами (таблица 4).

Пример 2. Вывод заданной ветви каталога
снизу вверх
SELECT category_id, parent_id, title
FROM categories
START WITH category_id = 5
CONNECT BY category_id = PRIOR parent_id;

В этом запросе PRIOR стоит перед parent_id. Это означает, что поле parent_id идентифицирует тематические разделы, а поле category_id наоборот как бы становится ссылкой на родительский раздел. Благодаря этому, движение по дереву будет осуществляться снизу вверх. Результатом запроса будет вывод ветви каталога, начиная с раздела ?Музыка? и заканчивая самым верхним разделом ?Интернет? (таблица 5).

Заключение

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

Литература

  1. Г. Буч, «Объектно-ориентированный анализ и проектирование с примерами приложений на C++», 2-е издание. «Невский диалект», 1998
  2. К. Дж. Дейт, «Введение в системы баз данных», 7-е издание. «Вильямс», 2001
  3. Г. Буч, Д. Рамбо, А. Джекобсон, «Язык UML. Руководство пользователя». ДМК, 2000
  4. Д. Грофф, П. Вайнберг, «SQL: полное руководство», 2-е издание. «BHV-Киев» диалект», 2001

C Максимом Рябенко (МФТИ) можно связаться по электронной почте по адресу maxy@rt.mipt.ru.

Пилим каталог товаров не притрагиваясь к реляционной алгебре

Время на прочтение
7 мин

Количество просмотров 17K

Здравствуйте, меня зовут Дмитрий Карловский и я… давно не занимался бэкендом, но на днях вдруг наткнулся на мучения SbWereWolf по натягиванию ужа на ежа и не смог удержаться от соблазна сдуть пыль со своего мульти-инструмента OrientDB да оттяпать им чего-нибудь этакого.

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

Разбирать мы будем вот этот вот реляционный звездолёт:

17 таблиц

А собирать вот такой вот графовый скворечник:

5 классов

Схема базы данных

Все сущности нашего каталога у нас будут иметь следующие поля:

  • slug — человекопонятный идентификатор
  • created — время создания сущности
  • searchable — будет ли сущность находиться при поиске
  • title — человекопонятное название сущности в виде словаря «язык-текст»
  • description — человекопонятное описание сущности в виде словаря «язык-текст»

Чтобы не повторять эти поля в каждой сущности, как это сделано в звездолёте, мы просто создадим абстрактный класс «Object» от которого в дальнейшем будем наследовать остальные сущности:

Create class Object abstract

Create property Object.slug string ( collate ci , notnull true )
Create property Object.created datetime ( readonly true , default sysdate() )
Create property Object.searchable boolean ( default false )

Create property Object.title embeddedmap string ( collate ci )
Create property Object.description embeddedmap string ( collate ci )

slug должен быть уникальным для каждой сущности, а по названиям и описаниям нам потребуется поиск, поэтому добавим на эти поля соответствующие индексы:

Create index Object.slug unique

Create index Object.title on Object( title by value ) fulltext
engine lucene metadata {
    "analyzer" : "org.apache.lucene.analysis.ru.RussianAnalyzer"
}

Create index Object.description on Object( description by value ) fulltext
engine lucene metadata {
    "analyzer" : "org.apache.lucene.analysis.ru.RussianAnalyzer"
}

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

Самое главное в нашем магазине — товары, а каждый товар помимо стандартных свойств имеет ещё и цену:

Create class Product extends Object

Create property Product.price decimal

В звездолёте используется иерархия рубрик в виде дерева, но мы поступим интересней — всю иерархию мы разобьём на 2 типа узлов:

  • Тег — флаг, характеризующий конкретный товар.
  • Аспект — группа взаимоисключающих тегов, образующая характеристику товаров

В иерархии эти два типа узлов идут попеременно:

  • внутри тега могут находиться аспекты, но не теги
  • внутри аспекта могут находиться теги, но не аспекты

Примеры аспектов (а в скобочках — тегов):

  • Вид товара (еда, одежда, техника)
  • Производитель (Плюшкин Инкорпорейтед, Макинтош Лимитед, Экскаватор Трейдинг)
  • Цвет (Красный, Синий, Зелёный)

При этом выбор «цвета» имеет смысл давать только для тегов «одежда» и «техника», но не «еда».

Добавим эти две сущности и провяжем их друг с другом:

Create class Aspect extends Object
Create class Tag extends Object

Create property Aspect.tag linkset Tag
Create property Aspect.tag_sub linkset Tag

Create property Tag.aspect linkset Aspect
Create property Tag.aspect_sub linkset Aspect

Как видно, все связи у нас двусторонние «многие-ко-многим». Каждая сущность имеет ссылку на связанные с нею сущности. Осталось лишь связать нашу иерархию с товарами. Связь будет односторонней, чтобы не захламлять тег списком связанных с ним товаров, которым мы всё-равно не будем пользоваться:

Create property Product.tag linkset Tag

Например, для товара «Скатерть-самобранка» может быть выставлен тег «техника», который откроет нам аспект «цвет» и, как следствие, возможность выбрать «красный».

Чтобы поиск по тегам у нас не тормозил, мы добавим по ним индекс:

Create index Product.tag notunique

Кроме флагов, у сущностей должны быть и атрибуты других типов: строковые, целочисленные, десятичные, временные и тд. Чтобы описать эти атрибуты, введём соответствующую сущность:

Create class Attribute extends Object

Create property Attribute.type string ( default "string" )

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

Create property Tag.attribute linkset Attribute
Create property Attribute.tag linkset Tag

Например, если установлен тег «еда», то для товара становится доступен атрибут «срок годности». Само значение атрибута конкретного товара мы будем хранить в самом же товаре. В схему мы это выносить не будем, так как у каждого товара фактически может быть свой набор атрибутов в зависимости от того, какие теги ему были установлены.

Пользовательские сценарии

Полнотекстовой поиск

Если пользователь ввёл поисковой запрос, то мы сразу ищем все объекты, которые ему соответствуют:

Select from Object
where searchable = true
    and ( title lucene "Ска*" or description lucene "Ска*" )

Но если выдача получится слишком большой, то разумно будет предложить ему детализировать запрос по тегам из товаров в выдаче. Для этого запросим вместе с собственно найденными объектами ещё и связанные с ними теги и связанные с последними атрибуты и аспекты:

Select from Object
where searchable = true
    and ( title lucene "Ска*" or description lucene "Ска*" )
fetchplan *:0 slug:0 title:0 tag.slug:0 tag.title:0 tag.aspect.title:0 tag.attribute.title:0 tag.attribute.type:0

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

Select from Object
where searchable = true
    and ( title lucene "Ска*" or description lucene "Ска*" )
    and ( tag in ( Select from Tag where slug = "tag=tech" and slug="color=red" ) )
    and ( weight between 100 and 200 )
fetchplan *:0 slug:0 title:0 tag.slug:0 tag.title:0 tag.aspect.title:0 tag.attribute.title:0 tag.attribute.type:0

Навигация по каталогу

Когда пользователь только открыл сайт, разумно сразу предложить ему несколько направлений движения и очертить ассортимент. Поэтому мы выведем все корневые аспекты и возможные для них теги:

Select from Aspect
where ( tag is null )
fetchplan *:0 title:0 tag_sub.slug:0 tag_sub.title:0

Дальнейшее путешествие пользователя аналогично случаю полнотекстового поиска, но без собственно полнотекстового поиска:

Select from Product
where searchable = true
    and ( tag in ( Select from Tag where slug = "tag=tech" and slug="color=red" ) )
    and ( weight between 100 and 200 )
fetchplan *:0 slug:0 title:0 tag.slug:0 tag.title:0 tag.aspect.title:0 tag.attribute.title:0 tag.attribute.type:0

Как можно заметить, погружаясь всё глубже в кроличью нору, мы не переходим с одной рубрики на другую (вложенную), а добавляем в фильтрацию дополнительный тег. Например, на странице «красные ботинки» мы будем искать по тегам «одежда», «обувь», «ботинки», «красные», а на странице «красненькие ноутбуки» — «техника», «компьютеры», «ноутбуки», «красные». В обоих случаях «красные» — это один и тот же тег.

Создание товара

При создании товара, нет никакого смысла выводить для заполнения все возможные для товаров параметры. Например, параметр «соотношение сигнал/шум» совершенно бессмысленно для «ботинок». Поэтому точно так же, как с каталогом, мы выводим лишь корневые аспекты, а дополнительные аспекты становятся доступными лишь по мере выбора тегов пользователем, добавляющим товар. Список доступных атрибутов и аспектов c их тегами по списку выбранных тегов получается достаточно тривиально:

Select from Aspect
where ( tag is null )
    or ( tag in ( Select from Tag where slug = "tag=tech" and slug="color=red" ) )
fetchplan *:0 title:0 tag_sub.slug:0 tag_sub.title:0 tag_sub.attribute.title:0 tag_sub.attribute.type:0

Тут же мы можем предоставить пользователю возможность добавлять не только товар, но и расширять набор атрибутов, аспектов и тегов.

Создадим, например, аспект «Вид товара»:

Insert into Aspect set slug = "aspect=kind" , title = { "ru" : "Вид товара" }

Теперь добавим к нему, например, тег «Одежда»:

Insert into Tag
set
    slug = "tag=wear" ,
    searchable = true ,
    title = { "ru" : "Одежда" } ,
    aspect = ( Select from Aspect where slug = "aspect=kind" )

Update Aspect
add tag_sub = ( Select from tag where slug = "tag=wear" )
where slug = "aspect=kind"

Другие теги добавляются аналогично. Добавление вложенного в тег аспекта аналогично. Например, добавим аспект «Цвет» в теги «Одежда» и «Техника»:

Insert into Aspect
set
    slug = "aspect=color" ,
    title = { "ru" : "Цвет" } ,
    tag = ( Select from Tag where slug = "tag=wear" or slug = "tag=tech" )

Update Tag
add aspect_sub = ( Select from Aspect where slug = "aspect=color" )
where slug = "tag=wear"

Update Tag
add aspect_sub = ( Select from Aspect where slug = "aspect=color" )
where slug = "tag=tech"

Ну и, наконец, самое главное — добавление товара. Для примера, добавим «Скатерть-самобранку» красного цвета:

Insert into Product
set
    slug = "product=2" ,
    searchable = true ,
    title = { "ru" : "Скатерть-самобранка" } ,
    price = 999 ,
    tag = ( Select from Tag where slug = "tag=tech" or slug = "tag=red" )

Удаление товара

Удаление товара вовсе не должно приводить к удалению записи об этом товаре из базы данных, так в дальнейшем может потребоваться восстановить этот товар или найти данные о нём по идентификатору из какого-нибудь лога. Да даже чтобы выдавать 410(Gone) вместо 404(Not found) нужно, чтобы какая-то запись о товаре всё же оставалась. Кроме того есть такая сложная проблема как обеспечение того, чтобы никакая другая запись не ссылалась на удаляемую. Поэтому лучшее решение — изменять запись так, чтобы она исключалась из определённых процессов. Например, чтобы товар не находился ни в глобальном поиске, ни в каталоге, достаточно изменить флаг searchable на false. Именно поэтому во всех поисковых запросах мы указывали дополнительное условие where searchable = true.

Update Product set searchable = false where slug = "product=2"

Другой вариант «удаления» — удаление ссылок на сущность, вместо удаления самой сущности. Например, список тегов аспекта у нас хранится в свойстве tag_sub. Если мы хотим, чтобы больше нельзя было выбирать тег «Серобуромолиновый» в аспекте «Цвет», то просто удаляем его из tag_sub, но связь от тега к аспекту оставляем нетронутой. Таким образом, при просмотре товара с этим странным цветом ничего не сломается — будет показываться «Цвет: Серобуромалиновый», но при создании нового товара выбрать этот цвет будет невозможно.

Update Aspect
remove tag_sub = ( Select from Tag where slug = "tag=gray-brown-magenta" )
where slug = "aspect=color"

Резюме

Итого, у нас получилось 4 сущности: товар, тег, аспект и атрибут. Между собой они имеют 8 типов связей. И всего этого достаточно, чтобы реализовать свой Яндекс.Маркет с поиском, фильтрами и волшебницами всего за один беспокойный вечер.

Введение

Каталог товаров является обязательной частью любого магазина, он может использоваться для составления различных отчетов и формирования списка востребовнаных, но заканчивающихся товаров, например. Электронный каталог товаров предпологает хранение соответствующей информации в электронном виде, что позволяет более эффективно обрабатывать ее средствами ЭВМ. Такой каталог обязателен при электронной комерции, то есть любых продах товаров и услуг с использованием сети Интернет [1].

Чаще всего интернет магазны использую готовые движки, обзор которых приведен в [2], при этом отмечается, что одним из основных параметров движка является возможность интеграции с системой 1С. В базе 1С, помимо каталога товаров, может храниться информация о кадрах, документах, формироваться налоговая отчетность и прочее [3]. Однако, ряд магазинов такого функционала не имеет и хранит лишь каталог товаров в своей собственной базе данных.

Целью является разработка программного обеспечения, предоставляющего функции для работы с каталогом товаров. Такой каталог может использоваться в качестве составной части систем электронной комерции. Реализация выполнена с использованием языка С++ и библиотеки Qt [4]. Работа является примером выполнения курсового проекта для студентов.

1 Анализ проблемы и постановка задачи

Задача учета наличия товаров и предоставление информации по ним стоит перед любым магазином. Организационная структура магазина или торговой сети отличается в зависимости от размера предприятия, правовых норм, а также меняется со временем — эволюция организационных структур преприятий торговли рассмотрена в [5]. Из этого следует, что нельзя выделить какой либо универсальной структуры предприятия, использующего разрабатываемую систему, а значит — и определиться со списком пользовательских ролей. Поэтому решено ориентироваться на небольшое предприятие, занимающееся интернет-торговлей, где:

  • покупатель может выбрать товары в корзину и сформировать заказ;
  • есть 2 типа менеджеров, младший (МенеджерТоваров) занимается работой с товарами и обработкой заказов;
  • старший (МенеджерМагазина) может получать отчеты по работе предприятия за определенный период — эта роль соответствует интересам руководителя предприятия.

1.1 Выявление ролей и возможностей системы

Соответствующие роли и их возможности приведены на UML диаграмме прецедентов:

В результате анализа задания на проектирование несложно выделить две ключевых сущности — Товар и Каталог, в ходе анализа прецедентов можно также выделить сущности Заказ и Отчет. На основе этих сущностей сформирована модель предметной области системы и изображена на рисунке, приведенном ниже, с использованием нотации диаграммы классов [6].

Проанализировав бизнес процессы (прецеденты) можно обнаружить проблемы:

  • чтобы сформировать отчет, надо хранить информацию о проданных товарах. Кроме того, в класс товара добавлены поля годен_до и дата_поступления. Это позволит обнаружить товар, который дольше всех не продается, а также товары с истекающим сроком годности.
  • возможность заводить учетные записи для новых сотрудников можно дать менеджеру магазина, а пользователям предоставлять доступ к каталогу без учетной записи, при формировании заказа просить их указать электронную почту, например.

Доработанная диаграмма прецедентов:

Соответствующая ей модель предметной области:

Особенность этой системы также в том, что Товар тут задает одну единицу продукции, то-есть один мешок сахара, один стул или нож. Тут нет информации о том, является ли он сыпучим и может ли продаваться на разновес. Структура Товар также не хранит информации о количестве товаров такого типа — то-есть, она задает именно единицу товара, а не его тип. Так сделано потому, что в противном случае проблемы возникли бы при поступлении новых товаров — они могли бы иметь другой срок годности и другую дату поступления, а значит было бы недостаточно просто увеличить счетчик количествао_товара_в_наличии в одном объекте. Такая специфическая особенность системы накладывает ограничения на область ее применения, а также задает некоторую специфику ее исопльзования. В частности, если эта система будет применяться в книжном магазине и в магазин поступит 3 одинаковых книги — они должны будут добавлены в объект каталог трижды.

1.2 Функциональные требования и макеты интерфейса

К графическому представлению прецедентов Г. Буч [7] прилагает текстовое описание, которое с одной стороны является частью технического задания так как описывает желаемое поведение системы, а с другой — может использоваться как документация пользователя, так как представляет собой четкую последовательность действий, которую должен выполнить пользователь для выполнения функции, предусмотренной прецедентом. Однако, в [8] отмечается, что чтобы такую последовательность описать надо иметь представление о пользовательском интерфейсе чтобы в инструкции четко указывать «какую кнопку нажимать». Поэтому одновременно с прецедентами прорабатывались макеты интерфейса.

Название прецедента: просмотреть информацио о товарах
Действующее лицо: Покупатель
Предусловия: открыто окно «Товары Покупателя».
Главная последовательность:
1. Сразу после открытия список товаров отображается в таблице.
2. Пользователь может проматывать содержимое таблицы с помощью ползунков а также сортировать его по значениям в определенной колонке кликом по названию этой колонки.
3. Интересующие товары пользователь может добавить в корзину, для этого выделить товар в таблице и нажать кнопку «Добавить в корзину».

Макет окна «Товары Покупателя»:

Название прецедента: оформить заказ
Действующее лицо: Покупатель
Предусловия: в окне ТоварыПокупателя товары добавлены в корзину, нажата кнопка «Оформить заказ», в результате — открыто окно оформления заказа (рисунок 1.6)
Главная последовательность:
1. После открытия окна в таблице отображаются товары, добалвенные пользователем в корзину.
2. Пользователь может удалить лишние товары, для этого — выделить строку таблицы и нажать кнопку «Удалить из корзины».
3. Для передачи заказа на обработку Менеджеру Покупатель вводит свой e-mail и нажимает кнопку «Готово».
Постусловия: заказ добавлен в систему, открыто окно Товары Покупателя.
Альтернативная последовательность:
1. Если пользователь хочет добавить в заказ еще товаров — он может вернуться в окно ТоварыПокупателя без оформления заказа. Для этого нажимает кнопку «Назад».
Постусловия: открыто окно ТоварыПокупателя.

Макет окна оформления заказа:

Название прецедента: изменить информацию о товарах
Действующее лицо: МенеджерТоваров
Предусловия: Менеджер вошел в систему, открыто окно ТоварыМенеджера.
Главная последовательность:
1. Удалить старый товар;
2. Добавить новый товар, такой же как старый, но с исправленной информацией.
Постусловия: информация о товаре изменена.
Альтернативная последовательность: если после изменения товар некорректно описан — информация о нем не сохраняется в системе.

Макет окна управления заказами Менеджера:

Название прецедента: удалить товар
Действующее лицо: МенеджерТоваров
Предусловия: Менеджер вошел в систему, открыто окно ТоварыМенеджера.
Главная последовательность: Выделить удаляемый товар в таблице, нажать кнопку «Удалить товар».
Постусловия: товар удаляется из ситемы.

Название прецедента: добавить товар
Действующее лицо: МенеджерТоваров
Предусловия: Менеджер вошел в систему, открыто окно ТоварыМенеджера.
Главная последовательность:
1. Нажать кнопку «Добавить товар», открывается форма добавления товара.
2. Ввести информацию о товаре, нажать кнопку «Добавить».
Постусловия: товар добавлен в систему.
Альтернативная последовательность 1: если информация о товаре введена некорректно — кнопка «Добавить» не работает (нажатие ни к чему не приводит).
Альтернативная последовательность 2: при нажатии кнопки назад окно добавления товара закрывается, товар не добавляется.

Макет окна добавления товара товарами:

Название прецедента: обработать заказ
Действующее лицо: МенеджерТоваров
Предусловия: Менеджер вошел в систему, открыто окно ТоварыМенеджера.
Главная последовательность:
1. Нажать кнопку «Обработать заказы», открывается форма обработки.
2. Выбрать нужный заказ в таблице (работает ползунок и сортировка по полю).
3. Нажать кнопку удалить (если заказ нельзя сформировать) или продать если заказ удалось сформировать для клиента.
Постусловия: заказ обработан (удален или сформирован). В обоих случаях сущность «Заказ» из системы удаляется, но если он был продан — то соответствующие товары из категории Товар переходят в категорию ПроданныйТовар.
Альтернативная последовательность: нажата кнопка «Продать», но одного из необходимых товаров в заказе нет в наличии. При этом нажатие не приводит ни к каким действиям (ни один товар не продан, заказ не удален).
Альтернативная последовательность: нажата кнопка «Назад» — выполняется возврат в предыдущее окно, никакие данные в системе не меняются.

Макет интерфейса окна обработки заказов:

Название прецедента: войти в систему
Действующее лицо: МенеджерТоваров, МенеджерМагазина
Предусловия: открыто окно ТоварыПокупателя.
Главная последовательность:
1. Нажать кнопку «Войти в систему», открывается форма входа.
2. Ввести логин и пароль, нажать кнопку «Вход».
3. Открывается главно окно. Для МенеджераТовара — кнопки «Посмотреть отчет» и «Управление пользователями» неактивны, для менеджера магазина — активны.
Альтернативная последовательность 1: Если пара логин и пароль неверна — вход не происходит, поля логина и пароля очищаются.
Альтернативная последовательность 2: При нажатии кнопки назад окно закрывается.

Макет интерфейса окна входа:

Название прецедента: сформировать отчет по продажам за период
Действующее лицо: МенеджерМагазина
Предусловия: открыто окно ТоварыМенеджера.
Главная последовательность:
1. Нажать кнопку «Просмотреть отчет», открывается соответствующая форма.
2. Ввести дату начала и конца периода, нажать кнопку «Получить отчет».
3. В поле Количество выводится количество проданных товаров, в поле Выручка — их общая стоимость.
Альтернативная последовательность 1: Если дата начала или конца введена неверно — нажатие кнопки «Просмотреть отчет» ни к чему не приводит.
Альтернативная последовательность 2: При нажатии кнопки назад окно закрывается.

Макет интерфейса окна отчетов:

Название прецедента: управление пользователями
Действующее лицо: МенеджерМагазина
Предусловия: открыто окно ТоварыМенеджера.
Главная последовательность:
1. Нажать кнопку «Управление пользователями», открывается форма управления пользователям.
2. Для добавления пользователя заполняются поля группы «Добавить» и нажмается кнопка «Добавить». Если все успешно — пользователь добавляется в базу и появляется в таблице. Если поле «Управление Магазином» не заполнено — будет добавлен менеджер товаров, иначе — мееджер магазина.
3. Для удаления пользователя он выделяется в таблице и нажимается кнопка «Удалить».
Альтернативная последовательность 1: При попытке удалить самого себя — ничего не происходит. С одной стороны это нужно чтобы не удалить случайно из сситемы всех менеджеров, способных управлять пользователями, а с другой — что должна делать программа если такое удаление произойдет? Ведь после удаления самого себя текущий пользователь не является пользователем и вообще никаких прав не имеет.
Альтернативная последовательность 2: При попытке добавления пользователя, логин которого занят или логин с паролем пустые — ничего не произойдет.

Макет интерфейса окна управления пользователями:

1.3 Формат данных системы

Даты в системе хранятся в виде строк в формате YYYY.MM.DD, например, "2021.07.14". Такой формат удобен при сортировке, а также не накладывает никаких ограничений на СУБД. Это важно потому, что для работы с датой и временем в различных СУБД используются различные типы данных, а в некоторых из них никаких специальных типов для этого вообще нет.
При вводе e-mail проверяется что строка содержит символы "@" и ".". Проблемы более правильной проверки почтового адреса описаны в [9].
Логин и пароль представляют собой непустые строки.

Артикулы товаров в системе не могут повторяться. Даже если в системе есть несколько одинаковых товаров — у каждого из них должен быть свой артикул. Иначе проблемы возникли бы при изменении параметров товаров:

  • если пользователь переимеовал товар, то надо ли менять названия других товаров с этим артикулом? — Это же касается других параметров.
  • что если цена товара зависит от срока годности? — Получается, что у товаров с одним артикулом могут быть разные параметры.
    Цена товара и количество — целое число.

Отчеты в системе не хранятся, а лишь формируются в окне менеджера.

Проектирование. Программная часть

2.1 Выбор средств разработки

Описанная выше система может быть реализована на любом развитом языке программирования, например С++, Java или C#. Чаще всего в компаниях-производителях программного обеспечения используется определенный стек технологий, с которым знакомы работающие в ней программисты. С использованием именно этих технологий и ведется разработка любого заказанного в компании продукта так как переобучение программистов — это достаточно дорого, а также в новых проектах часто используют наработки из своих же уже выполненных проектов. По этим соображениям эта работа выполняется на языке С++, он мне лучше всего знаком.

Языка С++ и стандартной библиотеки для выполнения работы не достаточно, нужны сторонние библиотеки для работы с базами данных и реализации графического интерфейса. Обе задачи могут быть реализованы с исопльзованием фреймворка Qt. В состав этого фреймворка входит инструмент QtDesigner, позволяющий разрабатывать (верстать) пользовательский интерфейс без программирования, а перетаскиванием элементов управления мышкой. С его помощью были созданы, в частности, макеты интерфейса приведенные выше, остается лишь добавить к ним функции-обработчики событий/сигналов, выполняющие требуемые функции чтобы превратить это в работающее приложение.

2.2 Разработка структуры базы данных

Изначально в базу данных были добавлены все сущности из предметной области, а также таблица products_orders, соединяющая заказы и продукты. Такая таблица нужна для реализации отношения много-ко-многим, ведь один и тот же товар мог бы быть добалвен разными пользователями в разные заказы, а заказ может состоять из нескольких продуктов. ER-диаграмма отражающая полученную структуру таблиц приведена на рисунке:

Тут видно, что сущность ПроданныйТовар дублирует поля Товара, так сделано потому что в реляционных БД нет механизма наследования из объектно-ориентированного программирования. Возможны были и другие решения:

  • сохранять в таблице ПроданныйТовар идентификатор Товара и добавлять к нему дату продажи. Это плохо потому, что товары в нашей базе существуют в единственном экземпляре, то есть при поступлении второго мешка сахара в базе появится новая запись. В ларьке или небольшом магазине строительных материалов насчитается несколько десятков тысяч таких товаров, в магазине товаров ручной работы — скорее всего не более тысячи. Нет проблемы в хранении всех этих товаров в одной таблице. Однако, за год магазин продаст сотни тысяч товаров и если их не удалить из таблицы, то поиск товаров в наличии будет занимать много времени. Поэтому ПроданныеТовары целесообразно переносить в отдельную таблицу, поиск в которой выполняется достаточно редко, пир запросе от МенеджераМагазина — раз в месяц, например.
  • можно добавить в татаблицу Товара поля типа «продано_ли» и «дата_продажи». Такое решение даст ровно теже проблемы.
    Сгладить проблему с производительность может также индексирование, в частности, при втором подходе можно индексировать по полю «проданно ли», однако разделение таблиц — еще более эффективное решение.

При создании заказа пользователь выбирает товары, а затем нажимает кнопку. После этого система должна добавить заказ в базу и связать с ним товары, добавив записи в таблицу ТоварЗаказ. Тут возникла еще одна проблема, ведь поле ID (у заказа) пользователь не заполняет, обычно СУБД сами выдают идентификаторы записям и следят чтобы они не повторялись, для этого в SQL поле помечается как PRIMARY KEY AUTOINCREMENT. Это значит что после того как Заказ будет добавлен в базу, у нас не будет информации о поле ID этого заказа, но нам нужная эта информация чтобы приваязать к нему товары. Было найдено два решения этой проблемы:

  • использование запроса вида INSERT INTO ... ; SELECT last_insert_rowid();
  • использование ключевого слова RETURNING [10].

Однако, разработка велась с использованием версии SQLite, не поддерживающей эти конструкции. Это связано с тем, что библиотека Qt не исопльзует последнюю версию SQLite, поддерживающую эти конструкции. Это значит, что никак нельзя получить идентификатор последней добавленногй записи (заказа), а значит — нельзя и привязать к нему товары. В связи с этим, на разрабатываемую систему было наложено еще одно ограничение: товары привязываются к паре — email, дата. То-есть пользователь по одному email не сможет сделать два заказа за день. Сущность Заказ при этом оказывается вообще лишней, так как хранит она лишь дату и email. Конечная версия ER-диаграммы базы данных приведена на рисунке:

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

2.3 Архитектура системы

2.3.1 Файловая структура проекта

Система выполнена в объектно-ориентированном стиле, при этом если класс содержит только поля данных (является структурой) то он полностью описывается в заголовочном файле. Если же класс содержит также функции члены — то их реализация располагается в «.cpp» файле.

Так как программа выполнялась с использованием QtDesigner, то проект содержит также файлы описания интерфейса «.ui»-файлы для каждого окна программы. Для каждого такого файла среда разработки QtCreator генерирует описание класса формы, куда затем вносился исходный код, реализующий поведение элементом интерфейса. Описание класса автоматически располагается в паре файлов — «.h» и «.cpp».

Часть файлов, относящаяся только к модели (данным системы) помещена в подкаталог model.

На рисунке ниже приведена файловая структура проекта без выделения ".cpp" и ".h" файлов для отдельных модулей. Диаграмма использует нотацию диаграмм развертывания UML [11]. При этом пакетами изображены тройки файлов (".h" и ".cpp", ".ui"), отвечающие за реализацию какого-либо окна. Так как диаграмма достаточно сильно нагружена, на ней не изображены некоторые очевидные связи, например между файлами модуля users (реализует окно управления пользователями) и файлами user (хранят класс User).

2.3.2 Архитектурные особенности системы

Помимо реализации пользовательского интерфейса, система должна работать с базой данных. Для этого в библиотеке Qt предусмотрен ряд классов. Класс QSqlDatabase представляет базу данных в программе, QSqlQuery — служит для формирования запроса к ней и для получения результатов его выполнения. Чтобы локализовать код взаимодействия с базой данных — использован шаблон проектирования Фасад [12]. Класс ProductDB реализует интерфейс (набор публичных функций), активно используемый другими модулями.

Выходит, что существует один объект (база данных), к которой должны иметь доступ многие другие модули. Реализовать это можно через создание объекта базы в функции main, а затем, передаче его другим объектам через аргументы конструкторов. То-есть, в main создается объект класса CatalogBuyer (он открывается в программе первым), в него передается ссылка на базу данных. Однако, CatalogBuyer создает ряд других окон, например AuthWidget и OrderBuyer, которым также нужен доступ к базе — поэтому он передает эту ссылку дальше. Проблема в том, что глубина передачи такой зависимости достаточно большая и целесообразно использовать что-то типа глобальной переменной. В этой программе для реализации такого поведения используется Singleton-а Маерса взятый из статьи [13], он расположен в файле "singleton.h". Он примен для организации глобальной точки доступа к базе данных — объявлен макрос PRODUCT_DB и для запоминания текущего (вошедшего) пользователя — макрос CURRENT_USER. Запоминание текущего пользователя необходимо чтобы приложение сохраняло информацию о его правах (активность кнопок на окне Менеджера).

2.3.3 Диаграмма классов системы

Часть классов (заготовок) была сгенерирована средой QtDesigner и она мало интересна. В этой среде программист добавляет на форму с помощью мыши объекты и выставляет им имена. Система генерирует UI-класс с содержанием этой формы, но программист с ним напрямую почти не работает и он даже не отображается в среде разработки, программист лишь знает что в этом классе есть объекты с назначенными ему именами.

Сами по себе классы экранных форм, дорабатываемые программистом тоже не интересны как классы. Они содержат обработчик нажатий каждой кнопки, конструктор и деструктор. Однако, интересны классы, разработанные полностью вручную:

Видно, что на этой диаграмме нет сущности Отчет, хотя она была на модели предметной области. Это связано с тем, что отчет в системе не хранится и используется лишь одним окном, которым и формируется.

Класс SoltProduct соответствует проданному товару и в отличии от ER-диаграммы не дублирует поля Продукта, а использует механизм наследования.

Класс Order (Заказ) хранит идентификатор продукта, но напрямую с продуктом не связан. Такого типа связи на диаграмме показаны отношением ассоциации.

2.4 Сценарии работы системы

Сценарии работы системы в текстовом виде приведены в разделе 1.2, так как ожидаемое поведение системы является частью технического задания. Однако, при проектировании сценарии иногда визуализируются, в частности так делает Г. Буч [7]. Он использует для этого UML диаграммы активностей, состояний, последовательности и ряд других.

В этой части с помощью нотации диаграммы последовательности UML рассмотрены некоторые особенности использования системы, не описанные в задании.

На рисунке ниже показан маршрут товара в системе. Этот сценарий объединяет несколько прецедентов и поясняет как вообще продать что-либо в системе — сначала менеджер должен добавить товар, затем покупатель сформировать заказ и только после этого менеджер может обработав заказ пометить товары как проданные. На этой диаграмме, в отличии от сценариев, приведенной в первой главе, присутствуют детали реализации и используются классы, предложенные при проектировании. Символы объектов на диаграмме соответствуют обозначениям, введенным в методе Object-Oriented Software Engineering (проектированию на основе прецедентов) [14]. В частности, CatalogManager обозначен как граничный объект, так как является элементом интерфейса, а ProductDB — как сущность, ведь БД хранит данные дольше чем программа находится в памяти.

Последние два сообщения на этом рисунке соответствуют коду продажи товаров заказа в базе данных. Более подробно этот процесс показан на блок-схеме:

3 Разработка. Программный комплекс

В разделе приведены особенности реализации системы. В качестве документации пользователя могут выступать прецеденты, приведенные в первой части работы. Вопросы, связанные с разработкой интерфейса были освещены во второй части.

3.1 Контроль корректности данных

Для контроля корректности введенных данных в проекте используется механихзм валидаторов (семейство классов QValidator). В частности, в классе AddProduct есть такой фрагмент кода:

ui->cost->setValidator(new QIntValidator(0, 9999999, this));
ui->kind->setValidator(new QIntValidator(0, 10, this));
QRegExpValidator* dateValidator = new QRegExpValidator(QRegExp("20\d{2}\.[01]?\d\.[0123]?\d"), this);
ui->expiry_date->setValidator(dateValidator);

В первых двух строках к полям формы cost и вид прикрепляется валидатор целых чисел (QIntValidator). Во-первых, он не позволит ввести в поля что-либо отличное от целого числа, во-вторых, не позволит ввести целое число выходящее за границы указанного диапазона. В данном случае сорт — это число от 1 до 10.

В третьей строке создается валидатор даты, в данном случае он описан с помощью регулярного выражения [15]. Описание выражения расположено в строке: "20\d{2}\.[01]?\d\.[0123]?\d". Рассмотрим подробнее:

  • двойной слеш тут необходим для экранирования, на самом деле выражение выглядит так: "20d{2}.[01]?d.[0123]?d";
  • первыми двумя цифрами в дате обязательно были «20», так как система не предназначена для использования в 1900-ых годах и до 22 века не доживет;
  • затем идет две цифры ("d{2}");
  • на пятой позиции в строке стоит точка, ее необходимо экранировать, так как символ "." в регулярных выражениях соответствует «любому символу»;
  • дальше идет описание месяца. Первой цифрой месяца является 0 или 1, не бывает ведь 22 месяца, например — это задается перечислением в квадратных скобках «[01]«. Следующий символ вопросительного знака указывает на то, что эта цифра вообще не обязательная, то есть для ввода апреля ("04") можно просто ввести "4". Заканчивается описание месяца цифрой и точкой "d.".
  • в конце по аналогии описан день.

Возможно, это не лучший способ проверки даты, так как позволит ввести, например 18 месяц или 39 день.

Аналогичный валидатор даты встречается и в других классах.

3.2 Получение текущей даты

Получать текущую дату потребовалось в двух фрагментах программы — при создании заказа и при продаже товаров. Это нужно чтобы освободить пользователя от необходимости вводить эту самую дату, ведь можно взять системное время.

Для этого использовался такой фрагмент кода:

QString date_string = QDate::currentDate().toString(Qt::ISODate);
date_string.truncate(10);
date_string.replace("-", ".");

В первой строке вызывается встроенная функция для получения времени в формате ISODate. В этом формате год, месяц и день идут в точно таком же порядке, какой используется в программе. Однако, функция вернет не дату, а время, то есть полученную строку надо обрезать до 10 символа — это выполнено с truncate. Кроме того, формат ISODate использует символы тире вместо точек для разделения своиз частей, с помощью функции replace тире заменяется на точки.

3.3 Работа с базой данных

Для изоляции кода работы с БД от остальной программы используется класс фасад (ProductDB). В качестве СУБД взята SQLite. Этот класс отнаследован от DBFacade, который открывает файл базы данных (в нем указано имя файла с базой) и имеет функции для выполнения запросов и квотирования (взятия в кавычки) строк. Код этого класса и его описание взято в статье «Использование БД SQL. Шаблон проектирования «Фасад» (Facade)«.

Чтобы началь работать с БД надо сначала создать таблицы, делается это уже в классе ProductDB примерно так:

   void ProductDB::createTables() {
    if (false == m_db.tables().contains("users")) {
      exec("CREATE TABLE users"
           "("
              "login TEXT PRIMARY KEY, "
              "password TEXT NOT NULL, "
              "role TEXT"
           ");"
      );
    }

То есть сначала выполняется проверка наличия такой таблицы в БД и лишь при ее отсутствии создается новая.

Запросы к базе достаточно однотипно используют оператор SELECT SQL, поэтому ниже рассмотрены лишь несколько из них (наиболее характерных):

bool ProductDB::is_login_busy(QString login) {
  QString query = tr("SELECT login FROM users WHERE login = ") + qs(login);
  exec(query);
  return m_query->first();
}

Левая часть запроса описывает откуда выбирать данные, к ней прикрепляется логин пользователя, переданный в функцию в качестве аругмента. Затем, запрос выполняется с помомщью рассмотренной выше функции exec. После этого можно перебирать результаты поиска в базе, но в данном случае нужен лишь факт наличия/отсутствия пары логин+пароль в базе. Поэтому обращаемся к первой записи с помомщью функици first, если пары нет — она вернет nullptr, что эквивалентно false.

Для запросов на вставку возвращаемого значения нет поэтому после exec в них ничего не выполняется.

Для получения всех товаров в базе данных для их дальнейшего отображения в таблице используется такая функция, аналогично выполняется большинство других SELECT-запросов:

vector<Product> ProductDB::products() {
  vector<Product> products;
  QString query = tr("SELECT id, name, article, cost, kind, expiry_date, receipt_date FROM products ");
  exec(query);
  while (true == m_query->next()) {
    Product data;
    data.id = m_query->value(0).toInt();
    data.name = m_query->value(1).toString().toStdString();
    data.article = m_query->value(2).toString().toStdString();
    data.cost = m_query->value(3).toInt();
    data.kind = m_query->value(4).toInt();
    data.expiry_date = m_query->value(5).toString().toStdString();
    data.receipt_date = m_query->value(6).toString().toStdString();
    products.push_back(data);
  }
  return products;
}

В теле запроса указывается какие поля нужно выбрать из базы и их порядок. После выполнения запроса используется m_query->next() для перехода к следующей строке с результатом из БД. Все части строки нумеруются, начиная с нуля, в данном случае в начале результата стоит идентификатор товара, затем имя и так далее. Индексы элементов передаются в функцию value, для получения от нее результата в «привычном» формате к нему надо применить функции преобразования типа toString или toInt.

От всех остальных функций Фасада базы данных отличаются лишь sum и count, возвращающие сумму проданных товаров и их количество. Эта информация исопльзуется в окне отчета. Они используют агрегатные функции SQL:

int ProductDB::sum(QString from, QString to) {
    exec(
          tr("SELECT SUM(cost) FROM solt_products WHERE ") +
          tr("realization_date >= ") + qs(from) +
          tr(" AND realization_date <= ") + qs(to)
    );
    m_query->next();
    return m_query->value(0).toInt();
}

В данном случае выполняется выбора всех соответствующих запросу записей и для всех них считается сумма по полю cost.

3.4 Работа с таблицами пользовательского интерфейса

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

void Users::on_remove() {
  QList<QTableWidgetItem*> selectedItems = ui->table->selectedItems();
  set<int> selected_rows;
  set<QString> removed_users;

  for (auto item : selectedItems) {
    selected_rows.insert(item->row());
  }

  for (auto row : selected_rows) {
    auto login = ui->table->item(row, 0)->text();
    removed_users.insert(login);
  }

  for (auto login : removed_users) {
    User user = PRODUCT_DB.get_user(login);
    if (user.login == CURRENT_USER) {
      continue;
    }
    PRODUCT_DB.remove_user(user.login);
  }
}

Проблема заключается в том, что Qt позволяет выделять не только строки таблицы, но и отдельные ячейки. Получить мы можем только список ячеек, с помомщью функции selectedItems. Если мы для каждой ячейки получим номер строки и выполним с ней нужные нам операции то программа не будет корректно работать в случаях выделения нескольких ячеек в одной строке. Поэтому во всех таких функциях сначала формируется множество номеров выделенных строк selected_rows. Используется тип данных set из стандартной библиотеки С++, так как он автоматически уберет дублирующиеся элементы.

Формирование множества выделенных строк находится в строках 6-8. Затем, в строках 10-13 для каждой такой строки с помощью функции item выбирается элемент, находящийся в нужном столбце (в данном случае нулевом). В этой функции сначала формируется список всех логинов выделенных пользователей, а затем уже обрабатывается (удаляется).

В этой же функции используется глобальный объект CURRENT_USER, который формируется при входе в систему — в окне AuthWidget. Приведенный в 15-21 строках код не позволяет пользователю удалить самому себя, как этого и требует задание.

3.5 Инструкция по первому запуску

К программе прилагается файл с начальным содержимым базы данных. В базе есть один пользователь с логином «admin» и паролем «admin». Необходимо войти под этим пользователем, добавить менеджеров продукта и магазина.

3.6 Тестирование программы

Запустим программу, войдем под учетной записью администратора:

Откроем окно управления пользователями, добавим несколько менеджеров, кого-нибудь удалим:

Вернемся в окно товаров, добавим пару товаров:

Закроем программу и откроем снова, за счет этого окажемся в роли покупателя. На экране отобразятся добавленные товары:

Выберем некоторые из них и нажмем «Добавить в корзину», затем «Оформить заказ». Откроется форма оформления заказа, где надо ввести свою электронную почту, а также можно удалить некоторые лишние товары:

На этом этапе можно оформить несколько заказов вводя разные почтовые адреса.

В окне списка товаров нажмем «Войти в систему», войдем под одним из менеджеров Магазина. Откроем окно обработки заказов:

Продадим один из заказов. Можно удалить чтобы убедиться что удаление не влияет на формирование отчета:

Откроем отчет по продажам, введем диапазон дат, включающий сегодняшнее число (так как продажа случилась сегодня, текущее время подставлено автоматически):

Заключение

В ходе выполнения работы:

  • выполнен анализ предметной области, показано что есть ряд случаев, когда целесообразно писать собственную систему учета товаров и их продажи. В большинстве же случаев рациональнее взять готовые системы типа 1С.
  • определены границы системы — небольшой магазин, с небольшим количеством товаров. Лучше всего подойдет для магазинов изделий ручной работы. Разработана спецификация требований к системе, включающая функциональные требований в формате прецедентов и макеты интерфейса. Содержимое первого раздела может использоваться как руководство пользователя.
  • выполнено проектирование системы, содержимое второй и третьего раздела может использоваться как руководство программиста.
  • база заполнена эталонными данными

Исходный код проекта можно взять в репозитории.

Список использованной литературы

  1. Типовой закон об электронной торговле,принятый Комиссией Организации ОбъединенныхНаций по праву международной торговли, 1996 г. URL: https://docs.cntd.ru/document/499039311
  2. Антонов, И. Обзор CMS для создания интернет-магазинов / И. Антонов // Системный администратор. – 2014. – № 5(138). – С. 62-69.
  3. Программные продукты фирмы «1С». URL: https://1c.ru/rus/products/1c/default.jsp
  4. Qt — Cross-platform software development for embedded and desktop. URL: https://www.qt.io/
  5. Бобков А. Л., Денисов И. В., Кучмаева О. В. Развитие организационной структуры предприятий розничной торговли (на примере Чешской Республики) // Статистика и экономика. 2017. №3. URL: https://cyberleninka.ru/article/n/razvitie-organizatsionnoy-struktury-predpriyatiy-roznichnoy-torgovli-na-primere-cheshskoy-respubliki (дата обращения: 13.07.2021).
  6. Диаграммы классов UML // Блог программиста. URL: https://pro-prof.com/archives/3212
  7. Буч Градди Объектно-ориентированный анализ и проектирование с примерами приложений, 3-е изд. / Буч Градди, Максимчук Роберт А., Энгл Майкл У., Янг Бобби Дж., Коналлен Джим, Хьюстон Келли А.: Пер с англ. — М.: ООО «И.Д. Вильямс», 2010. — 720 с.
  8. Розенберг Д., Скотт К. Применение объектного моделирования с использованием UML и анализ прецедентов.: Пер. с англ. М.: ДМК Пресс, 2002
  9. Прекратите проверять Email с помощью регулярных выражений! // Хабр. URL: https://habr.com/ru/post/175375/
  10. RETURNING // SQLite. URL: https://www.sqlite.org/lang_returning.html
  11. Deployment Diagram // PlantUML. URL: https://plantuml.com/deployment-diagram
  12. Использование БД SQL. Шаблон проектирования «Фасад» (Facade) [C++, Qt] // Блог программиста. URL: https://pro-prof.com/archives/882
  13. Паттерн Singleton. Описание. Пример использования // Блог программиста. URL: https://pro-prof.com/archives/1546
  14. Розенберг Д., Скотт К. Применение объектного моделирования с использованием UML и анализ прецедентов.: Пер. с англ. М.: ДМК Пресс, 2002
  15. Учебник: Регулярные выражения (regular expressions) // Блог программиста. URL: https://pro-prof.com/archives/5414

Разработка базы данных каталога библиотечной литературы

Введение

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

Сейчас компьютер является неотъемлемой частью работы людей. Компьютеры
используются в школах и университетах. Они помогают систематизации полученные
данных, как в рабочих целях, так и в учебных.

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

Целью данной курсовой работы было создание приложения, которое бы позволяло
сохранять базу данных каталога библиотечной литературы.

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

Для разработки приложения используется среда программирования Microsoft
Visual Studio 2010. База данных создаётся на основе программного комплекса
Microsoft SQL Server 2008. Написание приложения производится при помощи языка
визуального программирования C#.


1.
Теоретическая часть

 

.1
Описание предметной области

Современная библиотека — это огромнейший каталог литературы самого
различного характера, жанра и направления. В её ходят дети и взрослые, студенты
и школьники, аспиранты и доктора наук. В связи с этим, есть необходимость в
строгой каталогизации для ускорения поиска по книжным полкам. В этом случае на
помощь приходят современные технологии. Персональный компьютер позволяет
хранить огромное количество информации, при этом обеспечивая быстрый поиск. Для
библиотеки, база данных со списком всей имеющейся литературы — незаменимая
вещь. Она позволит любому посетителю в считанные минуты найти интересующую его
книгу, будь то это художественный роман, фантастическая повести или научный
труд.

Для поиска книг обычно используются следующие данные:

—    Жанр

—       Название;

—       Автор;

—       Год издания;

—       Издательство;

—       Международный стандартный номер книги (ISBN);

—       Количество страниц.

Международный стандартный номер книги или ISBN (англ. International Standard Book Number) — уникальный номер книжного издания, необходимый для
распространения книги в торговых сетях и автоматизации работы с изданием.
Наряду с индексами ББК, УДК и авторским знаком, ISBN является частью так
называемого издательского пакета. Стандарт был разработан в Великобритании в
1966 году на базе 9-значного Стандартного номера книг (англ. Standard Book Numbering
(SBN) code) Гордона Фостера (англ. Gordon Foster). В 1970 году с небольшим изменением
был принят как международный стандарт ISO 2108 . С 1 января 2007 года введен
новый стандарт ISBN — 13-значный, совпадающий со штрих кодом. Существует также
подобный стандарт ISSN (International Standard
Serial Number) для периодических изданий.

В Беларуси ISBN используется — с 1993 года[1].

 

.2
Постановка задачи

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

Программа должна выполнять следующие функции:

·    подключение к базе данных;

·        просмотр списка жанров и книг, связанных с ними;

·        поиск в базе данных по трём критериям: автор, издательство,
название книги;

·        добавление новой книги в каталог;

·        удаление записи с информацией о книге;

·        добавление и удаление жанров в список.

Приложение должно иметь интуитивно понятный интерфейс и удобный вид.

Для написания приложения был выбран язык C# в составе среды разработки программного обеспечения Microsoft Visual Studio 2010. Этот современный программный комплекс позволяет
разрабатывать сложные приложения с графическим интерфейсом, при этом помогает
автоматизировать некоторые процессы проектирования визуального вида, дав
программисту возможность углубиться в разработку функционала приложения.

Язык C# — объектно-ориентированный язык программирования. Разработан в
1998-2001 годах группой инженеров под руководством Андерса Хейлсберга в
компании Microsoft как язык разработки приложений для
платформы Microsoft .NET Framework. C# относится к семье языков с
C-подобным синтаксисом, из них его синтаксис наиболее близок к C++ и Java [2].

Для управления базой данных было решено использовать SQL Server 2008, поскольку это решение наиболее подходит для
задач, связанных с хранением данных на персональном компьютере.

Microsoft SQL Server — система управления реляционными
базами данных (СУБД), разработанная корпорацией Microsoft. Основной используемый язык запросов
— Transact-SQL, создан совместно Microsoft и Sybase. Transact-SQL является реализацией стандарта ANSI/ISO по структурированному языку
запросов (SQL) с расширениями. Используется для работы с базами данных размером
от персональных до крупных баз данных масштаба предприятия; конкурирует с
другими СУБД в этом сегменте рынка [3].

Microsoft SQL Server обеспечивает удобство и надёжность
управления базами данных. Такие системы хранения обеспечивают высокую скорость
доступа к данным. Server
предназначен для упрощенного развертывания и быстрого создания прототипов; его
можно получить бесплатно и свободно распространять в составе приложений. SQL Server естественным образом интегрируется с
другими продуктами, входящими в серверную инфраструктуру.

 

.3
Описание алгоритмов

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

—    подключение к выбранной базе данных;

—       чтение и вывод на экран данных из таблиц базы данных;

—       добавление новых записей;

—       удаление уже существующих записей;

—       поиск и выборка соответствующих элементов из таблиц базы
данных.

Словесный алгоритм работы приложения может быть представлен в виде
следующей последовательности действий:

)     Запуск программы. Если есть подключение к базе данных по умолчанию
переход к пункту 3. Если нет доступа к базе — переход к пункту 2.

2)      Окно подключения к базе данных. По нажатию кнопки «Подключится»
переход к пункту 3.

)        Основное окно приложения «Электронный каталог библиотеки».

3.1) После нажатия кнопки «Добавить книгу» переход к пункту 4.

.2) После нажатия кнопки «Удалить книгу» переход к пункту 5.

.3) После нажатия кнопки «Экспорт в Excel» переход к пункту 6.

.4) После выполнения команды «Правка-Добавить жанр» переход к пункту 7.

.5) После выполнения команды «Правка-Удалить жанр» переход к пункту 8.

.6) После заполнения поля в блоке «Поиск по базе», выбора критерия поиска
и нажатия кнопки «Искать» будет произведен поиск и вывод результатов. Переход к
пункту 3.

)     Окно добавления новой книги в базу. После заполнения всех полей и
нажатия кнопки «Добавить в каталог» новая книга помещается в базу. Переход к
пункту 3.

5)      Окно удаления книги из базы. После заполнения поля данных и
нажатия кнопки «Удалить из каталога» книга удаляется из базы. Переход к пункту
3.

)        Открывается приложение Microsoft Excel,
содержащий экспортированные данные. Переход к пункту 3.

)        Окно добавления жанра в список. После заполнения поля данных и
нажатия кнопки «Добавить в список» новый жанр будет добавлен в базу. Переход к
пункту 3.

)        Окно удаления жанра из списка. После выбора из списка требуемого
жанра и нажатия кнопки «Удалить из списка» жанр будет удален из базы. Переход к
пункту 3.


2.
Практическая часть

 

.1 Схема
классов

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

Для обеспечения подключения к базе данных служит класс Form1, представленный на рисунке 2.1.
Исходный код на языке C#
находится в приложении.

Рисунок 2.1 — Класс Form1

Для обеспечения работоспособности всего функционала основной формы
приложения служит класс Form2,
представленный на рисунке 2.2. Исходный код на языке C# находится в приложении.

Рисунок 2.2 — Класс Form2

Для обеспечения работы добавления новой книги в базу данных служит класс Form3, представленный на рисунке 2.3.
Исходный код на языке C#
находится в приложении.

Рисунок 2.3 — Класс Form3

Для обеспечения работы удаления книги из базы данных служит класс Form4, представленный на рисунке 2.4.
Исходный код на языке C#
находится в приложении.

Рисунок 2.4 — Класс Form4

Для обеспечения работы добавления нового жанра в список служит класс Form5, представленный на рисунке 2.5.
Исходный код на языке C#
находится в приложении.

Рисунок 2.5 — Класс Form5

Для обеспечения работы удаления жанра из списка служит класс Form6, представленный на рисунке 2.6.
Исходный код на языке C#
находится в приложении.

Рисунок 2.6 — Класс Form6

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

Рисунок 2.7 — Диаграмма классов, связанных с базой данных

В создаваемой базе данных присутствуют две таблицы:

—    Жанр (название Genre)

—       Книги (название Books).

Названиям таблиц в базе данных были присвоены имена, состоящие из
латинских букв для предотвращения проблем с различными кодировками.

Таблица, изображённая на рисунке 2.8, отображает взаимосвязи между
таблицами в рамках одной базы данных. Связь происходит по внешнему ключу между
столбцами с названием «Жанр» каждой таблицы.

Рисунок 2.8 — Схема связей между таблицами базы данных

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

 

.2 Таблица
процедур обработки событий

Для удобства пользования, приложение разбито на 7 форм.

На первой форме, называемой «Подключение» и указанной в проекте под
именем Form1.cs происходит выбор базы данных и подключение к выбранной базе.
События, которые можно вызвать из первой формы, указаны в таблице 2.1.

Таблица 2.1 — События, вызываемые на форме «Подключение к
базе данных»

Событие

Возникает

Вызывает

button1_Click

Возникает при нажатии на
кнопку «Подключиться»

Подключение к выбранной
базе данных

button2_Click

Возникает при нажатии на
кнопку «Выход»

Прекращает работу
приложения

button3_Click

Возникает при нажатии на
кнопку «Обзор»

Открывает диалоговое окно
выбора базы данных на диске

Вторая форма является основной и называется «Электронный каталог
библиотеки» и появляется при успешном подключении к базе данных. В проекте она
отмечена как файл Form2.cs. События, вызываемые из неё, указаны в таблице 2.2.

Таблица 2.2 — События, вызываемые на форме «Подключение к
базе данных»

Событие

Возникает

Вызывает

dataGridView1_CellClick

Возникает при клике по
жанру в блоке «Жаны книг»

Отображение всех книг,
связанных с выбранным жанром в блоке «Результаты поиска»

button1_Click

Возникает при нажатии на
кнопку «Искать» после введения искомого слова в соответствующем поле

Производит поиск по
выбранному слову или группе слов в таблице со списком книг

button2_Click

Возникает при нажатии на
кнопку «Добавить книгу»

Открывает окно добавления
новой книги в базу

button3_Click

Возникает при нажатии на
кнопку «Удалить книгу»

Открывает окно удаления
книги из базы

button4_Click

Возникает при нажатии на
кнопку «Экспорт в Excel»

Вызывает процедуру экспорта
результатов поиска книг в документ Microsoft Excel

добавитьToolStripMenuItem_Click

Возникает при нажатии на
пункт «Правка-Добавить книгу» в главном меню программы

Открывает окно добавления
новой книги в базу

добавитьЖанрToolStripMenuItem_Click

Возникает при нажатии на
пункт «Правка-Добавить жанр» в главном меню программы

Открывает окно добавления
нового жанра в список

удалитьКнигуToolStripMenuItem_Click

Возникает при нажатии на
пункт «Правка-Удалить книгу» в главном меню программы

Открывает окно удаления
книги из базы

удалитьЖанрToolStripMenuItem_Click

Возникает при нажатии на
пункт «Правка-Удалить жанр» в главном меню программы

Открывает окно удаления
жанра из списка

экспортРезультатовВExcelToolStripMenuItem1_
Click

Возникает при нажатии на
пункт «Файл- Экспорт результатов в Excel» в главном меню программы

Вызывает процедуру экспорта
результатов поиска книг в документ Microsoft Excel

выходToolStripMenuItem_Click

Возникает при нажатии на
пункт «Файл-Выход» в главном меню программы

Закрывает приложение

оПрограммеToolStripMenuItem_Click

Возникает при нажатии на
пункт «Справка-О программе» в главном меню программы

Открывает окно информации о
программе

В таблице 2.3 находится описание событий, вызываемых из формы «Добавление
в базу новой книги», называемой в проекте Form3.cs.

Таблица 2.3 — События, вызываемые на форме «Добавление в базу
новой книги»

Событие

Возникает

Вызывает

button1_Click

Возникает при нажатии
кнопки «Добавить в каталог»

Производит попытку добавить
новую книгу в базу данных и в случае успеха, выдаёт сообщение об успешном
добавлении, а при ошибке — сообщение об ошибке

button2_Click

Возникает при нажатии на
кнопку «Отмена»

Закрывает форму добавления
новой книги в базу данных

В таблице 2.4 следует описание событий, вызываемых из формы «Удаление
книги из базы», называемой в проекте Form4.cs.

Таблица 2.4 — События, вызываемые на форме «Удаление книги из
базы»

Событие

Возникает

Вызывает

button1_Click

При нажатии кнопки «Удалить
из каталога»

Производит попытку удаления
книги из базы данных и в случае успеха, выдаёт сообщение об успешном
удалении, а при ошибке — сообщение об ошибке

Button2_Click

Возникает при нажатии на
кнопку «Отмена»

Закрывает форму удаления
книги из базы данных

В таблице 2.5 следует описание событий, вызываемых из формы «Добавление
нового жанра», называемой в проекте Form5.cs.


Таблица 2.5 — События, вызываемые на форме «Добавление нового
жанра»

Событие

Возникает

Вызывает

button1_Click

При нажатии кнопки
«Добавить в список»

Производит попытку
добавления нового жанра в базу данных и в случае успеха, выдаёт сообщение об
успешном добавлении, а при ошибке — сообщение об ошибке

button2_Click

Возникает при нажатии на
кнопку «Отмена»

Закрывает форму добавления
нового жанра в базу данных

В таблице 2.6 следует описание событий, вызываемых из формы «Удаление
существующего жанра», называемой в проекте Form6.cs.

Таблица 2.6 — События, вызываемые на форме «Удаление
существующего жанра»

Событие

Возникает

Вызывает

button1_Click

При нажатии кнопки «Удалить
из списка»

Производит попытку удаления
жанра из базы данных и в случае успеха, выдаёт сообщение об успешном
удалении, а при ошибке — сообщение об ошибке

button2_Click

Возникает при нажатии на
кнопку «Отмена»

Закрывает форму удаления
жанра из базы данных

Форма «О программе» несёт чисто информационный характер и позволяет
ознакомиться с программой и контактными данными автора. Список событий,
вызываемых в форме «О программе», называемой в проекте Form7.cs приведён в
таблице 2.7.

Таблица 2.7 — События, вызываемые на форме «О программе»

Событие

Возникает

Вызывает

button1_Click

Возникает при нажатии на
кнопку «Закрыть»

Закрывает форму «О
программе»

2.3
Руководство пользователя

Перед запуском программы убедитесь, что на компьютер обладает
минимальными системными требованиями:

·    Процессор Intel или AMD с частотой 800 MHz;

·        Оперативная память: 128 MB;

·        30 MB на
жёстком диске;

·        Операционная система Windows XP или выше;

·        Установленный Microsoft Excel 2003 или
выше.

Кроме этого на компьютере обязательно должно быть установлено следующее
программное обеспечение:

·    Microsoft .NET Framework 3.5;

·        Microsoft SQL Server 2008.

При успешном запуске программы появляется основное окно приложения,
изображённое на рисунке 2.9.

Рисунок 2.9 — Основное окно приложения

По умолчанию база данных называется Books.mdf и
расположена в одной директории с исполняемым файлом. Если по какой либо причине
файл базы данных не найден, пользователю будет отображено окно подключения
вместо основного окна приложения, оно изображено на рисунке 2.10.

Рисунок 2.10 — Окно подключения к базе

По нажатию кнопки «Обзор» открывается диалоговое окно выбора директории,
где находится файл с базой данных. После ее указания нужно нажать кнопку
«Подключится», для подключения к базе данных. Если нажать кнопку «Отмена»,
произойдет завершение работы приложения.

Просмотр списка книг по выбранному жанру осуществляется кликом левой
кнопкой мыши по интересующему жанру в блоке «Жаны книг», как это показано на
рисунке 2.11.

Рисунок 2.11 -Окно приложения со списком книг по жанру «Учебное пособие»

Программа позволяет производить поиск книг в базе данных по следующим
критериям:

—    по автору;

—       по издательству;

—       по названию.

На рисунке 2.12 показан пример поиска в базе данных по критерию поиска
«По издательству».

Рисунок 2.12 — Окно приложения со списком книг найденных по запросу
«Питер»

Для добавления новой книги в базу данных, нужно нажать кнопку «Добавить
книгу», либо выполнить команду меню «Правка — Добавить книгу». В этом случае откроется
новое окно для добавления книги. Для ее добавления, необходимо выбрать жанр из
списка, а затем заполнить все поля. Пример заполнения показан на рисунке 2.13.

Рисунок 2.13 — Окно добавления новой книги в базу

После заполнения всех полей необходимо нажать на кнопку «Добавить в
каталог». В случае успешного добавления появится сообщение, показанное на
рисунке 2.14.

Рисунок 2.14 — Сообщение об успешном добавлении книги в базу

Для удаления книги из базы данных, нужно нажать кнопку «Удалить книгу»,
либо выполнить команду меню «Правка — Удалить книгу». В этом случае откроется
новое окно удаления книги. Для ее удаления, необходимо в поле ввести код
издания удаляемой книги. Пример заполнения показан на рисунке 2.15.

Рисунок 2.15 — Окно удаления книги из базы

После ввода необходимо нажать на кнопку «Удалить из каталога». В случае
успешного удаления появится сообщение, показанное на рисунке 2.16.

Рисунок 2.16 — Сообщение об успешном удалении книги из базы

Для добавления нового жанра в список, нужно выполнить команду меню
«Правка — Добавить жанр». В этом случае откроется новое окно для добавления
жанра. Для добавления, необходимо ввести его название в поле. Пример заполнения
показан на рисунке 2.17.

Рисунок 2.17 — Окно добавления нового жанра в список

приложение база библиотечный литература

После ввода необходимо нажать на кнопку «Добавить в список». В случае
успешного добавления появится сообщение, показанное на рисунке 2.18.

Рисунок 2.18 — Сообщение об успешном добавлении жанра в список

Для удаления жанра из списка, нужно выполнить команду меню «Правка —
Удалить жанр». В этом случае откроется новое окно удаления жанра. Для его
удаления, необходимо в списке выбрать название удаляемого жанра. Пример показан
на рисунке 2.19.

Рисунок 2.19 — Окно удаления жанра из списка

После выбора необходимо нажать на кнопку «Удалить из списка». В случае
успешного удаления появится сообщение, показанное на рисунке 2.20.

Рисунок 2.20 — Сообщение об успешном удалении жанра из списка

В программе есть возможность экстпорта результатов поиска в документ
Microcoft Excel. Для ее использования нужно нажать кнопку «Экспорт Excel» или
выполнить команду меню «Файл — Экспорт результатов в Excel». В этом случае
откроется документ с экспортированными книгами. Пример показан на рисунке 2.21.

Рисунок 2.21 — Экспортированные результаты поиска в документ
Excel

Приложение имеет собственную справочную систему, запустить которую можно,
воспользовавшись пунктом «Справка» в главном меню. В справочном материале
описаны все возможности программы.


Заключение

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

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

В ходе данного курсового проекта было разработано полноценное приложение
для хранения и каталогизации списка книг библиотеки. По окончании работы были
получены следующие результаты:

—    разработано приложение на языке Visual C# для работы со
списками книг, хранящимися в базе данных;

—       реализованы возможности просмотра, добавления, удаления,
поиска записей;

—       разработана справочная система приложения;

—       приобретены и закреплены навыки работы с реляционными базами
данных на основе системы управления базами данных SQL Server.

Таким образом, можно сделать вывод, что цели и задачи курсового проекта
выполнены в полном объеме.


Список
использованных источников

1.   Википедия, — [Электронный ресурс]. Режим доступа: http:// ru.wikipedia.org

2.   Троелсен Э. — Язык программирования C# 2010 и платформа .NET 4.0, 5 издание — М.: Вильямс, 2010. — 1392 с.

3.      Роберт Э. Уолтерс, Майкл Коулс — SQL Server 2008: ускоренный курс
для профессионалов — М.: Вильямс, 2008. — С. 768.

4.      Евсеева Н.О., Шамшев А.Б. — Работа с базами данных на языке C#. Технология ADO.NET — М.: Ульяновск УлГТУ, 2009 — 170 с.

Приложение

.CS:

using System;System.Windows.Forms;System.Data.SqlClient;EKB

{partial class Form1 : Form

{Form1()

{();

}path;void Form1_Load(object sender, EventArgs e)

{.ControlBox = false;= Environment.CurrentDirectory +
@»»+ textBox1.Text.ToString() + «.mdf»;.frm1 = new
Form1();.frm1 = this;.frm1.Visible = false;ToolTip1 = new
ToolTip();.AutoPopDelay = 3000;.ShowAlways = true;.SetToolTip(this.button1,
«Нажмите для подключения к базе данных»);.SetToolTip(this.button2,
«Нажмите здесь, чтобы закрыть программу»);.SetToolTip(this.button3,
«Нажмите здесь, чтобы указать путь к базе данных вручную. Она должна
находиться в папке с программой!»);.SetToolTip(this.textBox1,
«Введите название базы данных»);.Filter = «Файлы базы данных sql
server (*.mdf)|*.mdf|All files (*.*)|*.*»;.Title = «Открытие файла
базы данных»;.ConnectionString =
@»Server=.SQLEXPRESS;AttachDbFilename=» + path + «;Integrated
Security=true»;.Conn = new SqlConnection(cls.ConnectionString);

{.Conn.Open();.frm1.Visible = false;.frm2 = new
Form2();.frm2.ShowDialog();

}

{.Show(«Нет соединения с Базой Данных.nnSQL Server не
доступен.nВозможно не правильно указали имя базы данных.nЛибо у Вас стоит
более поздний сервер. Для данного проложения нужен SQL Server 2005»,
«Ошибка подключение к базе данных», MessageBoxButtons.OK, MessageBoxIcon.Error);.frm1.Visible
= true;

}

}void button1_Click(object sender, EventArgs e) //подключение

{.ConnectionString =
@»Server=.SQLEXPRESS;AttachDbFilename=» + path + «;Integrated
Security=true»;.Conn = new SqlConnection(cls.ConnectionString);

{.Conn.Open();.frm1.Visible = false;.frm2 = new
Form2();.frm2.ShowDialog();

}

{.Show(«Нет соединения с базой данных.nnSQL Server не
доступен.nВозможно неправильно указано имя базы данных.nДля данного
приложения нужен SQL Server 2005 или выше.», «Ошибка подключение к
базе данных», MessageBoxButtons.OK, MessageBoxIcon.Error);

}

}void button2_Click(object sender, EventArgs e) //выход

{.Windows.Forms.Application.Exit();

}void button3_Click(object sender, EventArgs e) //обзор

{.InitialDirectory = Environment.CurrentDirectory;.Title =
«Выберите файл базы данных на локальном диске. Он должен находиться в
папке с программой!»;(openFileDialog1.ShowDialog() == DialogResult.OK)

{.Text = openFileDialog1.FileName;= textBox1.Text.ToString();

//label4.Hide();

}

}

}public class cls

{public SqlConnection Conn; //переменная подключения к
бдpublic Form1 frm1; //переменная формы 1public Form2 frm2; //переменная формы
2public Form3 frm3; //переменная формы 3public Form4 frm4; //переменная формы
4public Form5 frm5; //переменная формы 5public Form6 frm6; //переменная формы
6public Form7 frm7; //переменная формы 7public bool goAdd = false; //переменная
режима добавленияpublic string ConnectionString;

}

}

.CS:

using
System;System.Data;System.Windows.Forms;System.Data.SqlClient;Microsoft.Office.Interop;Microsoft.Office.Interop.Excel;System.Runtime.InteropServices;EKB

{partial class Form2 : Form

{Form2()

{();

}void Form2_FormClosing(object sender, FormClosingEventArgs
e)

{.Windows.Forms.Application.Exit();

}void ExportToExcel(DataGridView grid)

{Excel = new ApplicationClass();RefStyle =
Excel.ReferenceStyle;.Visible = true;wb = null;TemplatePath =
System.Windows.Forms.Application.StartupPath + @»Экспорт
данных.xlt»;

{= Excel.Workbooks.Add(TemplatePath);

}(System.Exception ex)

{new Exception(«Не удалось загрузить шаблон для экспорта
» + TemplatePath + «n» + ex.Message);

}ws = wb.Worksheets.get_Item(1) as Worksheet;(int j = 0; j
< grid.Columns.Count; ++j)

{

(ws.Cells[1, j + 1] as Range).Value2 = grid.Columns[j].HeaderText;(int
i = 0; i < grid.Rows.Count; ++i)

{Val = grid.Rows[i].Cells[j].Value;(Val != null)

(ws.Cells[i + 2, j + 1] as Range).Value2 = Val.ToString();

}

}.Columns.EntireColumn.AutoFit();.ReferenceStyle =
RefStyle;(Excel as Object);

}void ReleaseExcel(object excel)

{

// Уничтожение объекта Excel..ReleaseComObject(excel);

// Вызываем сборщик мусора для немедленной очистки
памяти.GetTotalMemory(true);

}void UpdateDG1()

{.Conn = new
SqlConnection(cls.ConnectionString);.Conn.Open();comm = new SqlCommand(@»select
* from Genre», cls.Conn);iReader =
comm.ExecuteReader(CommandBehavior.CloseConnection);i = -1;.RowCount =
1;.ColumnCount = 1;.Columns[0].Width = 352;.Columns[0].HeaderText =
«Жанр»;(iReader.Read())

{++;.Rows.Add();.Rows[i].Cells[0].Value = iReader[0].ToString();

}.Close();

}void Form2_Load(object sender, EventArgs e)

{ToolTip1 = new ToolTip();.AutoPopDelay = 3000;.ShowAlways =
true;.SetToolTip(this.button1, «Нажмите эту кнопку, чтобы произвести поиск
по базе данных»);.SetToolTip(this.button2, «Нажмите кнопку, чтобы
открыть форму добавления новой записи в базу
данных»);.SetToolTip(this.button3, «Нажмите кнопку, чтобы удалить
выбранную запись из базы»);.SetToolTip(this.button4, «Нажмите кнопку,
чтобы сохранить результаты поиска в Microsoft Excel»);.RowCount =
1;.ColumnCount = 7;.Columns[0].Width = 180;.Columns[1].Width =
182;.Columns[2].Width = 90;.Columns[3].Width = 55;.Columns[4].Width =
85;.Columns[5].Width = 107;.Columns[6].Width = 70;.Columns[0].HeaderText =
«Жанр»;.Columns[1].HeaderText = «Название»;.Columns[2].HeaderText
= «Автор»;.Columns[3].HeaderText = «Год
издания»;.Columns[4].HeaderText =
«Издательство»;.Columns[5].HeaderText = «Код
издания»;.Columns[6].HeaderText = «Кол. страниц»;.Checked =
true;.Enabled = false;();

}void Form2_FormClosing_1(object sender, FormClosingEventArgs
e)

{.frm1.Close();

}void dataGridView1_CellClick(object sender,
DataGridViewCellEventArgs e)

{.Conn = new
SqlConnection(cls.ConnectionString);.Conn.Open();selected =
Convert.ToString(dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[0].Value);comand
= new SqlCommand(@»SELECT * FROM Books WHERE (Жанр LIKE ‘» +
Convert.ToString(selected) + «‘)» , cls.Conn);iReader =
comand.ExecuteReader(CommandBehavior.CloseConnection);i = -1;.RowCount = 1;.ColumnCount
= 7;(iReader.Read())

{++;.Rows.Add();(int j = 0; j < 7;j++)

{.Rows[i].Cells[j].Value = iReader[j].ToString();

}

} .Close();.Enabled = true;

}void выходToolStripMenuItem_Click(object sender, EventArgs
e)

{.frm1.Close();.frm2.Close();

}void button2_Click(object sender, EventArgs e) //добавить
книгу

{.frm3 = new Form3();.frm3.ShowDialog();

}void добавитьToolStripMenuItem_Click(object sender,
EventArgs e)

{.добавитьToolStripMenuItem.Click += new
System.EventHandler(this.button2_Click);

}void button1_Click(object sender, EventArgs e) //поиск

{(textBox1.Text == «»)

{.Show(«Пустое поле поиска!», «Ошибка
поиска», MessageBoxButtons.OK, MessageBoxIcon.Error);

}

{text = textBox1.Text;.Conn = new
SqlConnection(cls.ConnectionString);.Conn.Open();i = -1;.RowCount =
1;.ColumnCount = 7;(radioButton1.Checked == true)

{comand = new SqlCommand(@»SELECT * FROM Books WHERE
(Издательство LIKE ‘%» + text + «%’)», cls.Conn);iReader =
comand.ExecuteReader(CommandBehavior.CloseConnection);(iReader.Read())

{++;.Rows.Add();(int j = 0; j < 7; j++)

{.Rows[i].Cells[j].Value = iReader[j].ToString();

}

}.Close();

}(radioButton2.Checked == true)

{comand = new SqlCommand(@»SELECT * FROM Books WHERE
(Название LIKE ‘%» + text + «%’)», cls.Conn);iReader =
comand.ExecuteReader(CommandBehavior.CloseConnection);(iReader.Read())

{++;.Rows.Add();(int j = 0; j < 7; j++)

{.Rows[i].Cells[j].Value = iReader[j].ToString();

}

}.Close();

}(radioButton3.Checked == true)

{comand = new SqlCommand(@»SELECT * FROM Books WHERE
(Автор LIKE ‘%» + text + «%’)», cls.Conn);iReader =
comand.ExecuteReader(CommandBehavior.CloseConnection);(iReader.Read())

{++;.Rows.Add();(int j = 0; j < 7; j++)

{.Rows[i].Cells[j].Value = iReader[j].ToString();

}.Close();

}.Enabled = true;

}

}void button4_Click(object sender, EventArgs e) // экспорт в
эксель

{(dataGridView2);

}void button3_Click(object sender, EventArgs e) //удалить
книгу

{.frm4 = new Form4();.frm4.ShowDialog();

}void удалитьКнигуToolStripMenuItem_Click(object sender,
EventArgs e)

{.frm4 = new Form4();.frm4.ShowDialog();

}void подключениеКБазеToolStripMenuItem_Click(object sender,
EventArgs e)

{.frm1 = new Form1();.frm1.ShowDialog();

}void добавитьЖанрToolStripMenuItem_Click(object sender,
EventArgs e)

{.frm5 = new Form5();.frm5.ShowDialog();

}void экспортРезультатовВExcelToolStripMenuItem1_Click(object
sender, EventArgs e)

{(dataGridView2);

}void удалитьЖанрToolStripMenuItem_Click(object sender,
EventArgs e)

{.frm6 = new Form6();.frm6.ShowDialog();

}void оПрограммеToolStripMenuItem_Click(object sender,
EventArgs e)

{.frm7 = new Form7();.frm7.ShowDialog();

}void оПрограммеToolStripMenuItem1_Click(object sender,
EventArgs e)

{.frm7 = new Form7();.frm7.ShowDialog();

}

}

}

Form3.CS:

using System;System.Data;System.Windows.Forms;System.Data.SqlClient;Microsoft.Office.Interop;Microsoft.Office.Interop.Excel;System.Runtime.InteropServices;EKB

{partial class Form3 : Form

{Conn;Form3()

{();

}void Form3_Load(object sender, EventArgs e)

{.Conn = new SqlConnection(cls.ConnectionString);.Conn.Open();comm
= new SqlCommand(@»select * from Genre», cls.Conn);iReader =
comm.ExecuteReader(CommandBehavior.CloseConnection);(iReader.Read())

{.Items.Add(iReader[0].ToString());

}.Close();

}void button2_Click(object sender, EventArgs e) //отмена

{.Text = «»;.Text = «»;.Text =
«»;.Text = «»;.Text = «»;.Text =
«»;.Text = «»;.Hide();

}void button1_Click(object sender, EventArgs e) //добавить
книгу

{(textBox1.Text == «» || textBox2.Text ==
«» || textBox3.Text == «» || textBox4.Text == «»
|| textBox5.Text == «» || textBox6.Text == «» ||
comboBox1.Text == «»)

{.Show(«Одно из полей ввода незаполнено!»,
«Ошибка ввода данных», MessageBoxButtons.OK, MessageBoxIcon.Error);

}

{

{genre = Convert.ToString(this.comboBox1.Text);name =
Convert.ToString(this.textBox1.Text);autor =
Convert.ToString(this.textBox2.Text);year =
Convert.ToString(this.textBox3.Text);isdat =
Convert.ToString(this.textBox4.Text);code =
Convert.ToString(this.textBox5.Text);kolstr =
Convert.ToString(this.textBox6.Text);.Conn.Open();myCommand = cls.Conn.CreateCommand();.CommandText
= «INSERT INTO » +

«Books (Жанр,Название,Автор,[Год
издания],Издательство,[Код книги],[Количество страниц]) » +

«VALUES (@genre, @name, @autor, @year, @isdat, @code,
@kolstr)»;.Parameters.Add(«@genre», SqlDbType.NChar, 100);.Parameters[«@genre»].Value
= genre;.Parameters.Add(«@name», SqlDbType.NChar,
50);.Parameters[«@name»].Value =
name;.Parameters.Add(«@autor», SqlDbType.NChar,
30);.Parameters[«@autor»].Value = autor;.Parameters.Add(«@year»,
SqlDbType.NChar, 5);.Parameters[«@year»].Value =
year;.Parameters.Add(«@isdat», SqlDbType.NChar,
30);.Parameters[«@isdat»].Value =
isdat;.Parameters.Add(«@code», SqlDbType.NChar,
20);.Parameters[«@code»].Value = code;.Parameters.Add(«@kolstr»,
SqlDbType.NChar, 6);.Parameters[«@kolstr»].Value =
kolstr;UspeshnoeIzmenenie = myCommand.ExecuteNonQuery();(UspeshnoeIzmenenie !=
0)

{.Show(«Издание успешно добавлено!»,
«Добавление»);

}

{.Show(«Не удалось добавить издание!»,
«Добавление»);

}

}(Exception ex)

{.Show(ex.ToString());

}

{.Conn.Close();.Hide();

}

}

}

}

}

Form4.CS:

using
System;System.Collections.Generic;System.ComponentModel;System.Data;System.Drawing;System.Linq;System.Text;System.Windows.Forms;System.Data.SqlClient;EKB

{partial class Form4 : Form

{Form4()

{();

}void button1_Click(object sender, EventArgs e) //удалить
книгу

{(textBox1.Text == «»)

{.Show(«Поле ввода должно содержать текст!»,
«Ошибка ввода данных», MessageBoxButtons.OK, MessageBoxIcon.Error);

}

{

{code = Convert.ToString(this.textBox1.Text);

// SqlConnection Conn;

// cls.Conn = new SqlConnection();

//cls.Conn.Open();comm = new SqlCommand(@»select * from
Books», cls.Conn);myCommand = cls.Conn.CreateCommand();.CommandText =
String.Format(«DELETE FROM Books WHERE [Код книги] = ‘{0}'»,
code);.Parameters.Add(«@code», SqlDbType.NChar,
20);.Parameters[«@code»].Value = code;UspeshnoeIzmenenie =
myCommand.ExecuteNonQuery();(UspeshnoeIzmenenie != 0)

{.Show(«Изменения внесены», «Изменение
записи»);

}

{.Show(«Не удалось внести изменения»,
«Изменения записи»);

}

}(Exception ex)

{.Show(ex.ToString());

}

{.Conn.Close();.Hide();

}

}

}void button2_Click(object sender, EventArgs e) // отмена

{.Text = «»;.Hide();

}void Form4_Load(object sender, EventArgs e)

{.Conn = new
SqlConnection(cls.ConnectionString);.Conn.Open();comm = new
SqlCommand(@»select * from Genre», cls.Conn);

}

}

}

Form5.CS:

using
System;System.Collections.Generic;System.Data.SqlClient;System.ComponentModel;System.Data;System.Drawing;System.Linq;System.Text;System.Windows.Forms;EKB

{partial class Form5 : Form

{Conn;Form5()

{();

}void button2_Click(object sender, EventArgs e) // омена

{.Text = «»;.Hide();

}void button1_Click(object sender, EventArgs e) //добавить
жанр

{(textBox1.Text == «» )

{.Show(«Поле ввода должно содержать текст!»,
«Ошибка ввода данных», MessageBoxButtons.OK, MessageBoxIcon.Error);

}

{

{genre = Convert.ToString(this.textBox1.Text);.Conn = new
SqlConnection(cls.ConnectionString);.Conn.Open();myCommand =
cls.Conn.CreateCommand();.CommandText = «INSERT INTO » +

«Genre (Жанр) » +

«VALUES (@genre)»;.Parameters.Add(«@genre»,
SqlDbType.NChar, 100);.Parameters[«@genre»].Value =
genre;UspeshnoeIzmenenie = myCommand.ExecuteNonQuery();(UspeshnoeIzmenenie !=
0)

{.Show(«Жанр успешно добавлен в список!»,
«Добавление»);.frm2.UpdateDG1();

}

{.Show(«Не удалось добавить жанр в список!»,
«Добавление»);

}

}(Exception ex)

{.Show(ex.ToString());

}

{.Conn.Close();.Hide();

}

}

}

}

}

Form6.CS:

using
System;System.Collections.Generic;System.ComponentModel;System.Data;System.Drawing;System.Linq;System.Text;System.Windows.Forms;System.Data.SqlClient;EKB

{partial class Form6 : Form

{Form6()

{();

}void button2_Click(object sender, EventArgs e) // отмена

{.Text = «»;.Hide();

}void button1_Click(object sender, EventArgs e) // удалить
жанр

{rezult = MessageBox.Show(«Внимание! Вы хотите удалить
один из жанров книг.nУбедитесь что все книги этого жанра удалены из
базы.nИначе они станут недоступными!nn Вы действительно хотите удалить
данный жанр?», «Удаление», MessageBoxButtons.OKCancel,
MessageBoxIcon.Question);(rezult == DialogResult.OK)

{(comboBox1.Text == «»)

{.Show(«Поле ввода должно содержать текст!»,
«Ошибка ввода данных», MessageBoxButtons.OK, MessageBoxIcon.Error);

}

{

{genredel =
Convert.ToString(this.comboBox1.Text);.Conn.Open();myCommand =
cls.Conn.CreateCommand();.CommandText = String.Format(«DELETE FROM Genre
WHERE Жанр='{0}'», genredel);UspeshnoeIzmenenie =
myCommand.ExecuteNonQuery();(UspeshnoeIzmenenie != 0)

{.Show(«Изменения внесены», «Изменение
записи»);.frm2.UpdateDG1();

}

{.Show(«Не удалось внести изменения»,
«Изменения записи»);

}

}(Exception ex)

{.Show(ex.ToString());

}

{.Conn.Close();.Hide();

}

}

}

}void Form6_Load(object sender, EventArgs e)

{.Conn = new
SqlConnection(cls.ConnectionString);.Conn.Open();comm = new SqlCommand(@»select
* from Genre», cls.Conn);iReader =
comm.ExecuteReader(CommandBehavior.CloseConnection);(iReader.Read())

{.Items.Add(iReader[0].ToString());

}.Close();

}

}

}

Form7.CS:

using
System;System.Collections.Generic;System.ComponentModel;System.Data;System.Drawing;System.Linq;System.Text;System.Windows.Forms;EKB

{partial class Form7 : Form

{Form7()

{();

}void button1_Click(object sender, EventArgs e)

{.Hide();

} }}

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как найти тупой угол у паралелограма
  • Как найти скрытый объект в ворде
  • Как исправить антисептик
  • Скол на ноутбуке как исправить
  • Системная ошибка ui самсунг как исправить

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии