МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
МІЖНАРОДНИЙ ЕКОНОМІКО-ГУМАНІТАРНИЙ УНІВЕРСИТЕТ
імені академіка Степана Дем’янчука
Факультет кібернетики
Кафедра інформаційних систем та обчислювальних методів
КУРСОВА РОБОТА
з дисципліни «Програмування»
на тему:
База даних «Телефонний довідник»
Рівне – 2010
1. Основи проектування реляційних баз даних
1.1 Інформаційні системи з базами даних
1.1.1 Інформація й дані
Перш ніж перейти до обговорення поняття інформаційної системи (ІС), спробуємо з'ясувати, що ж розуміється під словом інформація. Відповісти на це питання й просто, і складно: слово "інформація" пов'язане із широким колом понять.
Змістовна сторона поняття "інформація" дуже багатогранна й немає чітких семантичних меж. Однак завжди можна сказати, що можна з нею робити. Саме відповідь на це питання найчастіше й цікавить як системних аналітиків і розроблювачів ІС, так і користувачів інформації (її основних споживачів).
З погляду як користувачів, так і розроблювачів ІС, в інформації є одна важлива властивість - вона є одиницею даних, яка підлягає обробці. Звичайно інформація надходить споживачеві саме у вигляді даних: таблиць, графіків, малюнків, фільмів, усних повідомлень, які фіксують у собі інформацію певної структури й типу. Таким чином, дані виступають як засіб подання інформації у певній, фіксованій формі, придатній для обробки, зберігання й передачі. Хоча дуже часто терміни "інформація" й "дані" виступають як синоніми, варто пам'ятати про цю їхню істотну відмінність. Саме в даних інформація знаходить інтерпретацію у конкретній ІС.
При згадуванні про "форму" подання інформації варто сказати ще про одну, "людську" властивість інформації - її сприйняття різними категоріями людей. Дані можуть бути згруповані спільно у документ. Документ може мати або не мати певну внутрішню структуру. Дані можуть бути відображені на екрані дисплея комп'ютера. Документи можуть мати аудіо- або відеоформу. Розробляючи ІС, ніколи не потрібно забувати, для кого вони (системи) створюються й хто буде їх використовувати. Форма подання інформації в ІС визначає також і категорії користувачів. ІС створюються для конкретних груп користувачів, тобто вони, як правило, проблемно-орієнтовані.
Інформація є дані, яким надається деякий зміст (інтерпретація) у конкретній ситуації у рамках деякої системи понять. Інформація представляється за допомогою кодування даних і витягається шляхом їхнього декодування й інтерпретації.
У цьому визначенні фіксується три основних перетворення інформації й даних у процесі їхньої обробки в ІС: інформація – дані, дані – дані, дані– інформація.
На рис. 1.1 подані дві сторони визначення поняття інформації: функціональна й представницька. Перша загалом визначає коло дій над інформацією, а друга – результат виконання цих дій.
Рисунок 1.1 – Зміст поняття "інформація"
1.1.2 Інформаційні системи
Основною метою створення ІС є задоволення інформаційних потреб користувачів шляхом надання необхідної їм інформації на основі збережених даних. Потреба в інформації як такій не вичерпує поняття інформаційних потреб. Звичайно в поняття інформаційних потреб включають певні вимоги до якості інформаційного обслуговування й поводження системи в цілому (продуктивність, актуальність і надійність даних, орієнтація на користувача та ін.).
Під інформаційною системою розуміється організаційна сукупність технічних засобів, технологічних процесів і кадрів, що реалізують функції збору, обробки, зберігання, пошуку, видачі й передачі інформації.
Необхідність підвищення продуктивності праці у сфері інформаційної діяльності призводить до того, що як зовнішні засоби зберігання й швидкий доступ до інформації найчастіше використовуються засоби обчислювальної техніки (цифровий й аналоговий) на основі комп'ютерів. Сучасні ІС - складні комплекси апаратних і програмних засобів, технології й персоналу, які ще називають автоматизованими інформаційними системами. Структурно ІС містять у собі апаратне (hardware), програмне (software), комунікаційне (netware), проміжного шару (middleware), лінгвістичне й організаційно-технологічне забезпечення.
Апаратне забезпечення ІС містить у собі широкий набір засобів обчислювальної техніки, передачі даних, а також цілий ряд спеціальних технічних пристроїв (пристрою графічного відображення інформації, аудио- і відеопристрою, засобу мовного уведення й т.д.). Апаратне забезпечення є основою будь-якої ІС.
Комунікаційне (мережне) забезпечення містить у собі комплекс апаратних мережних комунікацій і програмних засобів підтримки комунікацій в ІС. Воно має істотне значення при створенні розподілених ІС й ІС на основі Інтернету.
Програмне забезпечення ІС забезпечує реалізацію функцій введення даних, їх розміщення на носіях, модифікації даних, доступ до даних, підтримку функціонування устаткування. Програмне забезпечення можна розділити на системне (яке вінчає процес вибору апаратно-програмного рішення, або платформи) і користувальницьке (яке застосовується для рішення завдань задоволення потреб користувача у комп'ютерному середовищі).
Лінгвістичне забезпечення ІС призначене для рішення завдань формалізації змісту повнотекстової й спеціальної інформації для створення пошукового образу даних (профілю). У класичному змісті звичайно воно включає процедури індексування текстів, їхню класифікацію й тематичну рубрикацію. Найчастіше ІС, що містять складно-структуровану інформацію, містять у собі тезауруси термінів і понять. Сюди можна віднести й створення процесорів спеціалізованих формальних мов кінцевих користувачів, наприклад мов для маніпулювання бухгалтерською інформацією й т.д. Найчастіше роботам по розробці лінгвістичного забезпечення ненадається належного значення. Подібні недогляди найчастіше ведуть до несприйняття користувачами самої. Це відноситься в першу чергу до вузько спеціалізованих ІС.
У міру зростання складності й масштабів ІС важливу роль починає грати організаційно-технологічне забезпечення, що з'єднує різнорідні компоненти (апаратури, програми й персонал) у єдину систему й забезпечує процедури її керування й функціонування. Недооцінка цієї складової ІС найчастіше призводить до зриву строків впровадження системи й виводу її на виробничі потужності.
На рис. 1.2 наведені функції ІС через її основні структурні компоненти.
Рисунок 1.2 – Визначення інформаційної системи
2. Предметна область БД та її моделі
2.1 Поняття предметної області
Основним призначенням ІС є оперативне забезпечення користувача інформацією про зовнішній світ шляхом реалізації питально-відповідного відношення. Питально-відповідні відношення дозволяють виділити для
Рисунок 1.6 - Основні типи моделей даних
ІС певний її фрагмент - предметну область (ПО), - який буде втілений в автоматизованій ІС. Інформація про зовнішній світ подається в ІС у формі даних, що обмежує можливості змістовної інтерпретації інформації й конкретизує семантику її подання в ІС. Сукупність цих виділених для ІС даних, зв'язків між ними й операцій над ними утворить інформаційну й функціональну моделі ПО, що описують її стан із певною точністю. Інформаційна й функціональна моделі ПО є вхідними даними для процесу проектування БД.
Сукупність реалій (об'єктів) зовнішнього світу - об'єктів, про які можна задавати питання, - утворює об'єктне ядро ПО, яке має онтологічний статус. Не можна одержати в ІС відповідь на питання про те, що їй невідомо. Термін "об'єкт" є первинним поняттям. Синонімами терміна "об'єкт" є "реалія, сутність, річ". Сутність ПО є результатом абстрагування реального об'єкта шляхом виділення й фіксації набору його властивостей. На рис. 1.7 наведений один із підходів до класифікації об'єктів ПО.
Рисунок 1.7 - Класифікації об'єктів ПО
Прикладами сутностей (з погляду ІС) або об'єктів (з погляду зовнішнього світу) є окремий студент, група студентів, аудиторія, час занять, слова, числа, символи. Звичайно вважається, що бути об'єктом - це значить бути дискретним і помітним.
З об'єктами пов'язано дві проблеми: ідентифікація й адекватний опис. Для ідентифікації використовують ім'я. Використовується тільки вказівна функція імені. Ім'я – це прямий спосіб ідентифікації об'єкта. До непрямих способів ідентифікації об'єкта відносять визначення об'єкта через його властивості (характеристики або ознаки).
2.2 Інформаційна модель ПО БД
Інформаційна модель даних призначена для подання семантики ПО у термінах суб'єктивних засобів опису - сутностей, атрибутів, ідентифікаторів сутностей, супертипів, підтипів і т.д.
Інформаційна модель ПО БД містить такі основні конструкції:
· діаграми "сутність-зв'язок" (Entity - Relationship Diagrams);
· визначення сутностей;
· унікальні ідентифікатори сутностей;
· визначення атрибутів сутностей;
· відношення між сутностями;
· супертипи й підтипи.
Елементи інформаційної моделі даних ПО є вхідними даними для вирішення завдання проектування БД - створення логічної моделі даних.
Предметом інформаційної моделі є абстрагування об'єктів або явищ реального світу у рамках ПО, у результаті якого виявляються сутності (entity) ПО. Як правило, вони позначаються іменником природної мови.
Сутність описується за допомогою даних, іменованих властивостями або атрибутами (attributes) сутності. Як правило, атрибути є визначеннями у висловленні про сутності й позначаються іменниками природної мови. Сутності вступають у зв'язки один з одним через свої атрибути. Кожна група атрибутів, що описуює один реальний прояв сутності, являє собою екземпляр (instance) сутності. Іншими словами, екземпляри сутності - це реалізації сутності, що відрізняються один від одного й допускають однозначну ідентифікацію.
Одним із основних комп'ютерних засобів розпізнавання сутностей у базі даних є присвоєння сутностям ідентифікаторів (Entity identifier). Часто ідентифікатор сутності називають ключем. Завдання вибору ідентифікатора сутності є суб'єктивним завданням. Оскільки сутність визначається набором своїх атрибутів, то для кожної сутності доцільно виділити таку підмножину атрибутів, що однозначно ідентифікує дану сутність.
Завдання розробника БД - забезпечити при збереженні екземплярів сутності у БД наявність у кожного її нового екземпляра унікального дентифікатора.
Унікальний ідентифікатор сутності - це атрибут сутності, що дозволяє відрізняти одну сутність від іншої. Якщо сутність має кілька унікальних ідентифікаторів, так званих можливих ключів, то розробник повинен обрати первинний ключ сутності.
Розрізняють однозначні й багатозначні атрибути. Однозначними є атрибути, які в межах конкретного екземпляра сутності мають тільки одне значення. У протилежному випадку вони вважаються багатозначними. Кожен атрибут сутності має домен (domain). Домен це вираз, який визначає значення, дозволені для даного атрибута. Іншими словами, домен - це область значень атрибута.
Розробник БД повинен проконтролювати, щоб в інформаційній моделі ПО для кожного атрибута сутностей був визначений домен.
Сутності не існують окремо один від одного. Між ними є реальні відношення
(Relationship), і вони повинні бути відбиті в інформаційній моделі ПО. При виділенні відношень акцент робиться на фіксацію зв'язків та їх характеристик. Відношення (зв'язок) являє собою з'єднання (взаємовідношення) між двома або більше сутностями. Кожен зв'язок реалізується через значення атрибутів сутностей. Звичайно зв'язок позначається дієсловом. Кожен зв'язок також повинен мати свій унікальний ідентифікатор зв'язку.
Розробник БД повинен проконтролювати, щоб зв'язок між сутностями здійснювався через точно зазначені атрибути, які будуть визначати унікальний ключ зв'язку. Вибір ключів сутностей - одне з найважливіших проектних рішень, що повинен бути зробити розробник при переході від інформаційної моделі ПО до логічної моделі БД.
Зв'язки характеризуються ступенем зв'язку й класом приналежності сутності до зв'язку. Ступінь (потужність) зв'язку - це відношення числа сутностей, що беруть участь в утворенні зв'язку. Існують такі типи: "один-до-одного", "один-до-множини", "множина-до- множини".
Типовою формою документування інформаційної моделі ПО є діаграми "сутність-зв'язок" (ER-діаграми). ER-діаграма дозволяє графічно подати всі елементи інформаційної моделі згідно простим, інтуїтивно зрозумілим, але чітко визначеним правилам - нотаціям. Далі ми будемо користуватися умовними позначками, прийнятими в методології інформаційного проектування.
Сутність на ER-діаграмі наводиться прямокутником з ім'ям у верхній частині. Будемо використовувати англійські слова для іменування елементів моделі.
Рисунок 1.9 – Подання сутності Person (персонал) на ER-діаграмі з атрибутами й унікальним ідентифікатором сутності
У прямокутнику перераховуються атрибути сутності, при цьому атрибути, що становлять унікальний ідентифікатор сутності, підкреслюються.
Домени призначаються аналітиками й фіксуються в спеціальному документі - словнику даних (Data Dictionary). На стадіях розроблення логічної й фізичної моделей реляційної БД домени уточнюються у сутностях на ER-діаграмі.
Розробник БД повинен ретельним образом вивчити домени кожного атрибута з погляду на можливість їх реалізації у СКБД.
Рисунок 1.10 – Візуалізація визначення доменів атрибутів на ER-діаграмі при створенні фізичної моделі реляційної БД
Відношення (зв'язок) сутностей на ER-діаграмі зображується лінією, що з'єднує ці сутності. Ступінь зв'язку зображується за допомогою символу "пташина лапка", що вказує на те, що у зв'язку бере участь багато (N) екземплярів сутності, і одинарною горизонтальною рисою, що вказує на те, що у зв'язку бере участь один екземпляр сутності.
Відношення читається вздовж лінії або зліва направо, або справа наліво. На рис. 1.11 наведене таке відношення: кожна спеціальність зі створення повинна бути зареєстрована за певною фізичною особою (персоною), фізична особа може мати одну або більше спеціальностей зі створення.
2.3 Функціональна модель ПО БД
Другим ключовим моментом створення ІС з метою автоматизації інформаційних процесів організації є аналіз функціональної взаємодії об'єктів автоматизації. Аналітики наводять результати у вигляді функціональної моделі ПО БД. Склад функціональної моделі істотно залежить від контексту конкретного ІТ-проекту і може бути представлений за допомогою досить широкого спектра документів у вигляді текстової й графічної інформації.
Рисунок 1.11 – Подання відношення між двома сутностями на ER-діаграмі
Функціональна модель призначена для опису процесів обробки даних у рамках виділеної ПО з різних точок зору.
Визначимо функціональну модель ПО БД як сукупність деяких моделей, призначених для опису процесів обробки інформації. Будемо називати ці моделі конструкціями функціональної моделі. Нижче наведений перелік основних конструкцій функціональної моделі, які необхідні для виконання проектування реляційних БД.
Моделі процесів:
· бізнес-модель процесів (ієрархія функцій системи);
· модель потоку даних.
Моделі станів:
· модель життєвого циклу сутності;
· набір специфікацій функцій системи (вимоги);
· опис функцій системи через сутності й атрибути;
· бізнес-правила, які реалізують функції.
Елементи інформаційної моделі ПО є вхідними даними для завдання створення
логічної моделі даних. Елементи функціональної моделі ПО є вхідними даними для завдання проектування додатків БД і частково для завдання створення фізичної моделі БД.
2.4 Процес проектування БД
Значна частина проектів в області інформаційних технологій спрямована на розроблення й створення ІС, у рамках яких здійснюється обробка даних різної складності. Практично у всіх таких проектах вирішується завдання проектування БД певного типу.
В експлуатації БД повинна задовольняти набору вимог за рядом інтегрованих параметрів, таких як:
функціональність й адаптованість;
продуктивність обробки транзакцій;
пропускна здатність;
час реакції
Такі параметри іноді перебувають у протиріччі один до одного. Так, високі вимоги до функціональності на даному конкретному устаткуванні можуть вступати у конфлікт із високими вимогами до продуктивності. Наприклад, звіти можуть генеруватися протягом декількох годин і знизити в цей час реакції користувачів, що працюють із системою в діалоговому режимі.
Таким чином, процес проектування БД полягає у досягненні компромісів між функціональними, інформаційними, апаратними, архітектурними й технологічними вимогами до БД і будується на інформованому прийнятті рішень за структурою БД.
Проектування БД - це пошук засобів задоволення функціональних вимог засобами наявної комп'ютерної технології з урахуванням заданих обмежень.
Як правило, ІТ-проекти зі створення БД містять у собі такі етапи:
1. Визначення стратегії побудови системи.
2. Аналіз вимог до БД.
3. Проектування БД.
4. Реалізація БД.
5. Тестування
6. Впровадження БД.
Етап проектування БД вважається одним із самих складних етапів створення БД, який не має явно вираженого початку й закінчення. Порівняно з аналізом вимог до БД або розробкою додатків, проектування БД, на думку багатьох провідних фахівців, є невдало структурованим завданням. Якщо всі етапи створення БД перекриваються один з одним у своїй послідовності, то етап проектування перекривається з усіма іншими етапами. Проектування починається з моменту прийняття стратегічних рішень і триває на етапах реалізації й тестування.
Процес проектування БД охоплює кілька основних сфер:
· проектування об'єктів БД (таблиці, подання, індекси, тригери, збережені процедури, функції, пакети) для подання даних ПО в БД;
· проектування інтерфейсу взаємодії з БД (форми, звіти й т.д.), тобто проектування додатків, які будуть супроводжувати дані в БД і реалізовувати питально-відповідні відношення на цих даних;
· проектування БД під конкретне обчислювальне середовище або інформаційну технологію (архітектура "клієнт-сервер", паралельні архітектури, розподілене обчислювальне середовище);
· проектування БД під призначення системи (інтелектуальний аналіз даних, OLAP, OLTP і т.д.).
Типова бізнес-модель процесу проектування БД
Процес проектування БД може бути поданий у вигляді моделі бізнес-процесів. Бізнес-модель процесу проектування дозволяє:
· відобразити суб'єктивну думку розробника БД на процес проектування конкретної БД;
· врахувати особливості ІТ-проекту, у рамках якого проектується БД;
· досить швидко скласти план проектування конкретної БД;
· прорахувати тривалість проектних робіт (створити тимчасову модель проектування).
Розглянемо типову бізнес-модель процесу проектування БД.
На рис. 1.12 наведена контекстна діаграма процесу проектування БД.
Як бачимо з рисунка, на вхід процесу проектування БД подаються:
· інформаційна модель ПО БД: діаграми "сутність-зв'язок" (ER-діаграми);
· функціональна модель ПО БД: бізнес-модель процесів, діаграми потоку даних (DF- діаграми), діаграми станів, - діаграми життєвих циклів сутностей, специфікації на системи (вимоги), бізнес-правила;
· загальносистемні вимоги й обмеження;
· завдання зворотного впливу.
На виході процесу проектування БД формуються такі результати:
· фізична модель БД, що може бути перетворена у скрипт для створення БД;
· фізична БД;
· специфікація модулів додатків БД;
· план тестування БД.
Продовжуючи функціональну декомпозицію процесу проектування БД, приходимо до діаграми декомпозиції процесу проектування БД першого рівня, яка відбиває основні найбільш великі професійні завдання (етапи) проектування БД (рис. 1.13).
Рисунок 1.12 – Контекстна діаграма процесу проектування БД
Такими завданнями (етапами) є:
· збір й аналіз вхідних даних – це початковий етап проектування, на якому здійснюється збір і контроль якості результатів аналізу ПО БД, готується план проектування БД;
· створення логічної моделі БД – це етап, на якому на підставі інформаційної моделі
ПО БД створюється логічна структура БД, незалежна від її реалізації;
· створення фізичної моделі БД: внутрішня схема – це етап, на якому на підставі логічної моделі БД створюється фізична структура БД, залежна від її реалізації. На цьому етапі виконується перетворення відношення логічної моделі реляційної БД у команди створення об'єктів фізичної БД, у результаті чого створюється так звана внутрішня схема БД. Додатково може бути створена так звана зовнішня схема БД, останнє відбиває точку зору користувачів на дані в БД;
Рисунок 1.13 – Діаграма декомпозиція процесу проектування БД: перший рівень
· створення фізичної моделі БД: облік впливу транзакцій – це етап, на якому аналізуються можливі транзакції системи, виконується при потребі денормалізація відношення для забезпечення більш високої продуктивності БД;
· створення серверного коду – це етап, на якому на підставі функціональної моделі ПО БД створюється серверний код БД у вигляді тригерів, збережених процедур і пакетів. Ці модулі створюються розробником БД і виконуються сервером;
· проектування модулів додатків БД – це етап, на якому створюються специфікації модулів додатків, розробляються стратегії тестування БД і додатків, створюється план тестування додатків БД і готуються тестові дані;
· контроль якості проектування БД полягає в перевірці якості результатів проектування на кожному його етапі;
· облік завдань зворотного впливу полягає у настройці деяких транзакцій до БД і локальному перепроектуванні БД відповідно до вимог, що надходять з інших етапів створення БД.
Коротко розглянемо бізнес-моделі другого рівня.
Бізнес-модель процесу проектування БД: збір й аналіз вхідних даних
На рис. 1.14 наведена діаграма декомпозиції процесу проектування БД другого рівня, що відбиває основні завдання етапу збору й аналізу вхідних даних.
Такими завданнями є:
· збір документації з результатами аналізу ПО БД у вигляді діаграм, специфікацій і вимог;
· контроль якості результатів аналізу ПО БД;
· систематизація вимог і специфікацій замовника до БД;
· підготовка плану проектування БД.
Рисунок. 1.14 – Діаграма декомпозиції процесу проектування БД: збір й аналіз вхідних даних
У ході контролю якості основними моментами діяльності є контроль ER-діаграм і контроль діаграм функціональної моделі ПО. На підставі ER-діаграм створюється логічна модель реляційної БД; на підставі діаграм функціональної моделі розробляється серверний код і проектуються модулі додатків БД.
Систематизація вимог замовника до БД виконується з метою їх адекватного розподілу по етапах проектування БД. Важливим результатом систематизації є висновок про достатність вимог і можливість реалізації БД. Аналіз вимог на можливість реалізації БД у рамках конкретного ІТ-проекту є основою для ухвалення рішення менеджером проекту про можливості реалізації в цілому.
Дійсна бізнес-модель процесу проектування БД являє собою досить простий типовий приклад бізнесу-моделі проектування. У загальному випадку зміст бізнес-моделі проектування залежить від багатьох факторів: особистості менеджера й складу команди проекту, обсягу проекту, проектних ризиків і т.д.
Бізнес-модель процесу проектування реляційної БД: створення логічної моделі БД (рис. 1.15). Основною метою етапу створення логічної моделі БД є перетворення інформаційної моделі ПО БД у логічну модель реляційної БД. Створення логічної моделі БД припускає рішення таких основних завдань і виконання операцій у рамках таких завдань:
· нормалізація сутностей ПО: одержати список атрибутів сутності; визначити функціональні залежності (ФЗ) у сутності; визначити детермінанти сутності; визначити можливі ключі відношення, зокрема, розглянувши унікальний ідентифікатор сутності; виконати нормалізацію сутності (перетворити сутність у відношення); для отриманого відношення призначити первинні ключі; сформувати список кандидатів на зовнішні ключі, якщо необхідно; сформувати бізнес-правила підтримки цілісності сутності, якщо необхідно;
· нормалізація відношення логічної моделі БД;
· визначити ступінь зв'язку сутностей;
· визначити клас приналежності сутності до зв'язку: нормалізувати відношення (дозволити зв'язку);
· призначити первинні ключі єднальних відношень, виходячи з унікального ідентифікатора зв'язку й процедури міграції ключів при нормалізації; визначити атрибути єднальних відношень, якщо необхідно; сформувати бізнес-правила підтримки цілісності зв'язків;
· перевірка правильності логічної моделі реляційної БД: перевірка відношень на відповідність нормальній формі Бойса-Кодда; перевірка відношень на властивості з'єднання без втрат і збереження функціональних залежностей; запобігання втрати даних;
· шляхом міграції первинних ключів відношення й призначення зовнішніх ключів; перевірка на відсутність незамкнутих зв'язків; перевірка на відсутність одиночних відношень;
· формулювання частини вихідних даних для вирішення завдання керування посилальною цілісністю;
· документування логічної моделі реляційної БД;
· ухвалення рішення про можливість реалізації побудованої логічної моделі реляційної БД;
· ухвалення рішення про розроблення фізичної моделі реляційної БД.
Результатом проектування логічної моделі БД є нормалізована схема відношень БД.
Відзначимо, що в ході виконання етапу створення логічної моделі БД можуть бути створені нові об'єкти БД, не передбачені в інформаційній моделі ПО, наприклад, єднальна сутність при нормалізації відношень зі ступенем зв'язку "множина-до-множини".
Подані завдання становлять мінімально необхідний набір завдань, що дозволяють спроектувати логічну модель БД, і можуть розглядатися як один з можливих способів організації робіт у цій області.
Рисунок 1.15 – Бізнес-модель процесу створення логічної моделі БД
Бізнес-модель етапу проектування - створення фізичної моделі реляційної БД
Основна мета вирішення цього завдання: перетворити логічну модель реляційної БД у послідовність команд SQL для створення об'єктів реляційної БД. Таким чином, розробник
БД відображає відношення логічної моделі реляційної БД (сутності ПО, подані в нормалізованій формі на ER-діаграмах) у таблиці й індекси реляційної БД.
Це завдання включає виконання ряду обов'язкових послідовних процедур:
· створення базових таблиць. Вони представляють основні блоки зберігання даних і виводяться із сутностей логічної моделі даних. При створенні кожної таблиці розробник повинен розглянути й урахувати ряд факторів: визначити список колонок у таблиці (колонки виводяться з атрибутів сутності логічної моделі даних); визначити типи даних для кожної колонки (типи даних колонок або задані специфікацією домену атрибута логічної моделі, або визначаються розробником самостійно); визначити ім'я таблиці (воно може бути виведене з імені сутності логічної моделі БД або задано розробником самостійно. Бажано в цей момент визначити власника таблиці - користувача, що буде мати усі права доступу на таблицю, а також потенційних користувачів таблиці); визначити ряд параметрів, пов'язаних із характером зберігання таблиці у фізичній БД; визначити обмеження на значення колонок, виходячи з ряду бізнес-правил;
· створення єднальних таблиць, необхідних для дозволу відношення "множина-до- множини", якщо вони мають місце в логічній моделі БД. У рамках ER-діаграм це відношення може бути вже дозволено. Тоді мова йтиме тільки про його реалізації в командах SQL;
· ухвалити рішення щодо засобів підтримки посилальної цілісності в БД. Якщо буде вирішено підтримувати посилальну цілісність на рівні команд SQL, то розробити специфікацію обмеження посилальної цілісності. Це завдання вирішується в чотири етапи: ідентифікувати первинні ключі кожної таблиці; побудувати індекси первинного ключа; визначити зовнішні ключі в дочірніх таблицях, якщо необхідно; побудувати команди SQL, які ідентифікують зовнішні ключі в дочірніх таблицях і правила підтримки посилальної цілісності; якщо необхідно, побудувати подання зовнішньої схеми БД.
У результаті вирішення даного завдання робиться важливий вивід про правильність отриманої першої ітерації фізичної моделі БД, здійснюється документування фізичної моделі даних у вигляді скріпту, береться рішення про характер подальшої розробки фізичної моделі даних. Зі вказаної в попередніх розділах лекції зрозумілий такий алгоритм дій:
Створення об'єктів для зберігання даних:
Створення таблиць:
Ідентифікування таблиці
Визначення типів даних колонок
Визначення первинного ключа
Додавання обмежень
Створення таблиць для взаємозв'язку "множина-до-множини"
Створення індексів
Створення подань
Створення інших об'єктів БД
Перевірка коректності створеної фізичної моделі
На рис. 1.16 нижче подана модель бізнес-процесу першої ітерації фізичної моделі БД.
Головна мета етапу - створити послідовність команд SQL для створення об'єктів зберігання даних. Також можна створювати інші об'єкти, такі як синоніми, подання й індекси. Можна ухвалити рішення щодо підтримки посилальної цілісності БД програмними механізмами СКБД і створити відповідний набір команд SQL.
Бізнес-модель етапу проектування - створення фізичної моделі реляційної БД: облік впливу транзакцій. Вирішуючи професійне завдання створення фізичної моделі даних - облік впливу транзакцій, - розробник реляційної прагне створити таку фізичну модель даних, яка б, на його думку, давала найбільшу продуктивність обробки запитів БД. На практиці, особливо при створенні й розробці нових БД, таке завдання навряд чи може бути вирішене повністю. Ясно, що для його вирішення необхідно мати перелік всіх запитів до БД, їхній частоті й обсязі вибірок по кожному, що в принципі неможливо.
Рисунок 1.16 – Декомпозиція етапу проектування - створення першої ітерації фізичної моделі БД: внутрішня схема
Тому розробники БД на основі аналізу вихідної документації й опитувань потенційних користувачів намагаються систематизувати транзакції до БД, оцінити кардинальність таблиць у цілому й окремих колонках зокрема. На основі таких оцінок розробник БД намагається визначити критичні транзакції й налаштувати структури таблиць, задіяних у таких транзакціях, на досягнення максимальної продуктивності. При цьому він висуває гіпотези про застосовність того або іншого засобу підвищення продуктивності обробки запитів й перевіряє їх. Далі ухвалюється рішення щодо застосування найбільш підходящого.
Слід розуміти, що завдання забезпечення високої продуктивності БД - це завдання, яке постійно вирішує адміністратор БД у процесі її експлуатації. На цьому етапі проектування БД розробник, у міру можливості, готовить успішне вирішення цього завдання. Цей етап є дуже відповідальним у фізичному проектуванні БД, тому варто дотримувати при вирішенні цього завдання розумного прагматизму і документувати свої рішення. Повинне діяти емпіричне правило: якщо розробник БД не має досить даних для надійного вирішення завдання підвищення продуктивності БД, то рішення цього завдання повинне бути передане адміністраторові БД.
На цьому етапі проектування фізичної моделі розробник реляційної БД:
· виходячи з вимог до характеру обробки даних, визначає тип додатка БД;
· за наявними вимогами й описами виконує систематизацію й опис за можливістю всіх транзакцій;
· відштовхуючись від вихідної документації, визначає можливі розміри таблиць, а якщо це неможливо, робить припущення про їхній можливий розмір;
· виходячи з фактичних розмірів таблиць і вимог до продуктивності виконання транзакцій, визначає критичні транзакції;
· для кожної критичної транзакції необхідно оцінити кардинальність кожної колонки, задіяної у транзакції й, за можливістю, кардинальність вибірки;
· далі, розглядаючи в першу чергу критичні транзакції й таблиці, які в них беруть участь, розробник БД приймає суб'єктивні рішення по зміні структури таблиць внутрішньої схеми БД, виходячи з тих механізмів, які йому надає конкретна СКБД;
· по завершенні зміни структур таблиць розробник БД документує ці зміни, приводячи обґрунтування своїх рішень для адміністратора БД.
У результаті розробник БД створює фізичну модель БД, що враховує характер обробки даних у БД, виражений через облік впливу транзакцій.
Побудова бізнес-моделі етапу проектування фізичної моделі реляційної БД: облік впливу транзакцій проходить у кілька таких етапів (рис. 1.17):
Визначення основного типу додатка БД;
Документування й опистранзакцій;
Визначення критичних транзакцій;
Для кожної критичної транзакції:
Визначення таблиць транзакції
Визначення способу підвищення продуктивності
Денормализація таблиці;
Розбиття таблиці;
Секціонування таблиці;
Кластерізація таблиці;
Побудова додаткових індексів;
Зміна структури внутрішньої схеми БД;
Документування змін;
Для кожної таблиці БД Вибір індексів:
Визначення транзакцій таблиці;
Визначення кардинальності таблиць;
Визначення кардинальності колонок;
Визначення індексів;
Зміна внутрішньої схеми;
Короткий розгляд завдань створення серверного коду й підготовки скріпту Професійне завдання проектування БД - розроблення серверного коду БД - виникають, як правило, в обчислювальному середовищі з багатьма користувачами. У цих системах користувачі спільно використовують обчислювальні ресурси, зокрема ресурси дискової пам'яті й оперативної пам'яті процесора. Обчислювальні ресурси можуть бути сконцентровані в одному місці (централізовані обчислення) або бути розосередженими в різних вузлах, об'єднаних у комп'ютерну мережу (розподілені обчислення). СКБД у кожному разі покликана координувати й здійснювати доступ користувачів до баз даних та їхніх об'єктів.
Рисунок 1.17 – Декомпозиція етапу проектування - створення першої ітерації фізичної моделі БД: внутрішня схема
Більшість сучасних СКБД підтримують концепцію клієнт-серверної технології для розподілених обчислень. Це означає, що існують концентратори обчислень (названі серверами), на яких виконується найбільший обсяг обчислень із даними (сервери БД), і машини користувачів (клієнти), на яких виконуються додатки користувачів. Додатки формують запити у формі команд SQL до БД, відправляють їхнім серверам БД, одержують запитувані дані й обробляють їх.
3. Постановка завдання
Написати базу даних (БД), що дозволяє накопичувати інформацію, а саме - телефонний довідник Програма повинна містити утримувати основні функції: додавання добавляти запису, видалення віддалення запису, редагування запису, пошук. Додатково розробити ступені захисту до БД.
4. Загальний опис програми
Програмний продукт написаний в середовищі об'єктно орієнтованого програмування Microsoft Visual C# 2008 Exspress Edition.
Сама програма містить 3 основні форми:
MainForm.cs – головна форма програми. Зосереджено основний інтерфейс.
ItemForm.cs – форма вводу інформації про абонента записної книжки.
UserForm.cs – форма створення користувача БД(телефонного довідника). Інтерфейс захисту БД.
Вихідний код програми розміщений в додатках.
Програмний продукт дає можливість запису та зберігання інформації про абонента, а саме його ім’я, номер мобільного та домашнього телефону, його електронну та фізичну адресу, а також дату рейестрації його в БД. Відповідно, ми можемо редагувати записи в телефонному довілнику, - видаляти та змінювати вміст, а також задавати пошук необхідного.
Також ми можемо заходити в БД під своїм логіном та паролем.
Висновок
В рамках даної курсової роботи було поставлено завдання розробити базу даних (БД),що дозволяє зберігати інформацію про абонентів(Ім’я, телефон, мобільний, адреса, email, дата рейестрації). База даних містить утримувати основні функції: додавання добавляти запису, видалення віддалення запису, редагування запису, пошук заданої інформації.
Було проведено ознайомлення з відповідною літературою по дисципліні «бази даних». Після цього була написана програма в середовищі об’єктно-орієнтованого програмування Microsoft Visual C# 2008 Express Edition.
Програмний продукт містить простий та інтуїтивно-зрозумілий інтерфейс. Після тестування програми можна зробити висновок, що вона коректно працює в середовищі Microsoft Windows XP SP3. Вона повністю відповідає вимогам, поставлених в даній курсовій роботі, належить до категорії Open Source, тобто має можливість бути змінена, вдосконалена за бажанням в подальшій розробці.
Додаток 1: Вихідний код програми
Головна форма:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Phonebook.Classes;
using System.Diagnostics;
using System.IO;
using System.Xml.Linq;
using System.Globalization;
namespace Phonebook
{
public partial class MainForm: Form
{
float FontSize = 10.0f;
public MainForm()
{
InitializeComponent();
}
#region Buttons
void buttonNew_Click(object sender, EventArgs e)
{
try
{
ItemForm newForm = new ItemForm(true, false);
newForm.Font = new Font(this.Font.Name, this.FontSize, this.Font.Style, this.Font.Unit, this.Font.GdiCharSet, this.Font.GdiVerticalFont);
newForm.Text = "Додати новий запис";
newForm.lableRegDate.Text = christianToolStripMenuItem.Checked ? DateTime.Now.ToString(): ConvertToPersianDate(DateTime.Now.ToString());
newForm.ShowDialog();
LoadPhoneBookItems();
int contactsNumbers = Variables.xDocument.Descendants("Item").Where(q => q.Attribute("UserID").Value == Variables.CurrentUserID).Count();
this.Text = Variables.Caption + Variables.CurrentUserName + ": " + contactsNumbers.ToString() + " Contacts";
}
catch (Exception ex)
{
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
void buttonClearSearchTextBox_Click(object sender, EventArgs e)
{
textBoxSearch.Text = "";
LoadPhoneBookItems();
}
void buttonEdit_Click(object sender, EventArgs e)
{
try
{
if (listView1.SelectedItems.Count < 1) return;
string id = listView1.SelectedItems[0].Name.Replace("Item", "");
var item = (from q in Variables.xDocument.Descendants("Item")
where q.Attribute("UserID").Value == Variables.CurrentUserID && q.Attribute("ID").Value == id
select q).First();
if (item == null) return;
ItemForm editForm = new ItemForm(false, true);
editForm.Font = new Font(this.Font.Name, this.FontSize, this.Font.Style, this.Font.Unit, this.Font.GdiCharSet, this.Font.GdiVerticalFont);
editForm.Text = "Edit Item";
editForm.textBoxAddress.Text = item.Attribute("Address").Value;
editForm.textBoxEMail.Text = item.Attribute("Email").Value;
editForm.textBoxMobile.Text = item.Attribute("Mobile").Value;
editForm.textBoxName.Text = item.Attribute("Name").Value;
editForm.textBoxPhone.Text = item.Attribute("Phone").Value;
editForm.lableRegDate.Text = christianToolStripMenuItem.Checked ? item.Attribute("RegDate").Value: ConvertToPersianDate(item.Attribute("RegDate").Value);
editForm.ItemID = id;
editForm.ShowDialog();
LoadPhoneBookItems();
}
catch (Exception ex)
{
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
void buttonDelete_Click(object sender, EventArgs e)
{
try
{
if (listView1.SelectedItems.Count < 1) return;
if (MessageBox.Show("Ви впевнені, що хочете видалити запис,його потім не відновиш?", "Попередження", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) return;
string id = listView1.SelectedItems[0].Name.Replace("Item", "");
var item = (from q in Variables.xDocument.Descendants("Item")
where q.Attribute("UserID").Value == Variables.CurrentUserID && q.Attribute("ID").Value == id
select q).First();
item.Remove();
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
//Variables.xDocument.Save("debug.xml");
LoadPhoneBookItems();
int contactsNumbers = Variables.xDocument.Descendants("Item").Where(q => q.Attribute("UserID").Value == Variables.CurrentUserID).Count();
this.Text = Variables.Caption + Variables.CurrentUserName + ": " + contactsNumbers.ToString() + " Contacts";
}
catch (Exception ex)
{
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
#endregion
#region Menu Strip Events
#region Settings
void rightToLeftToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
rightToLeftToolStripMenuItem.Checked = true;
leftToRightToolStripMenuItem.Checked = false;
textBoxSearch.RightToLeft = RightToLeft.Yes;
listView1.RightToLeft = RightToLeft.Yes;
var query = (from q in Variables.xDocument.Descendants("Setting")
where q.Attribute("UserID").Value == Variables.CurrentUserID
select q).First();
query.Attribute("RightToLeft").Value = "Yes";
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
//Variables.xDocument.Save("debug.xml");
}
catch { }
}
void leftToRightToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
leftToRightToolStripMenuItem.Checked = true;
rightToLeftToolStripMenuItem.Checked = false;
textBoxSearch.RightToLeft = RightToLeft.No;
listView1.RightToLeft = RightToLeft.No;
var query = (from q in Variables.xDocument.Descendants("Setting")
where q.Attribute("UserID").Value == Variables.CurrentUserID
select q).First();
query.Attribute("RightToLeft").Value = "NO";
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
}
catch { }
}
void toolStripMenuItemFontSize_Click(object sender, EventArgs e)
{
try
{
toolStripMenuItemFontSize8.Checked = toolStripMenuItemFontSize10.Checked = toolStripMenuItemFontSize12.Checked = toolStripMenuItemFontSize14.Checked = toolStripMenuItemFontSize16.Checked = toolStripMenuItemFontSize18.Checked = false;
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
menuItem.Checked = true;
this.FontSize = float.Parse(menuItem.Text.Trim());
if (this.Font.Size!= this.FontSize)
{
this.Font = new Font(this.Font.Name, this.FontSize, this.Font.Style, this.Font.Unit, this.Font.GdiCharSet, this.Font.GdiVerticalFont);
var query = (from q in Variables.xDocument.Descendants("Setting")
where q.Attribute("UserID").Value == Variables.CurrentUserID
select q).First();
query.Attribute("FontSize").Value = this.FontSize.ToString();
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
//Variables.xDocument.Save("debug.xml");
}
}
catch { }
}
void christianToolStripMenuItem_Click(object sender, EventArgs e)
{
christianToolStripMenuItem.Checked = true;
persianToolStripMenuItem.Checked = false;
var query = (from q in Variables.xDocument.Descendants("Setting")
where q.Attribute("UserID").Value == Variables.CurrentUserID
select q).First();
query.Attribute("Dates").Value = "Christian";
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
//Variables.xDocument.Save("debug.xml");
}
void persianToolStripMenuItem_Click(object sender, EventArgs e)
{
christianToolStripMenuItem.Checked = false;
persianToolStripMenuItem.Checked = true;
var query = (from q in Variables.xDocument.Descendants("Setting")
where q.Attribute("UserID").Value == Variables.CurrentUserID
select q).First();
query.Attribute("Dates").Value = "Persian";
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
//Variables.xDocument.Save("debug.xml");
}
#endregion
void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
void newUserToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
UserForm newUserForm = new UserForm(true, false, false);
newUserForm.Font = new Font(this.Font.Name, this.FontSize, this.Font.Style, this.Font.Unit, this.Font.GdiCharSet, this.Font.GdiVerticalFont);
newUserForm.ShowDialog();
ApplySettings();
LoadPhoneBookItems();
if (Variables.CurrentUserName!= "" && Variables.CurrentUserID!= "")
{
int contactsNumbers = Variables.xDocument.Descendants("Item").Where(q => q.Attribute("UserID").Value == Variables.CurrentUserID).Count();
this.Text = Variables.Caption + Variables.CurrentUserName + ": " + contactsNumbers.ToString() + " Contacts";
DisableEnableControls(true);
}
else
DisableEnableControls(false);
}
catch (Exception ex)
{
DisableEnableControls(false);
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
void changeUserToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
UserForm userForm = new UserForm(false, true, false);
userForm.Font = new Font(this.Font.Name, this.FontSize, this.Font.Style, this.Font.Unit, this.Font.GdiCharSet, this.Font.GdiVerticalFont);
userForm.ShowDialog();
ApplySettings();
LoadPhoneBookItems();
if (Variables.CurrentUserName!= "" && Variables.CurrentUserID!= "")
{
int contactsNumbers = Variables.xDocument.Descendants("Item").Where(q => q.Attribute("UserID").Value == Variables.CurrentUserID).Count();
this.Text = Variables.Caption + Variables.CurrentUserName + ": " + contactsNumbers.ToString() + " Contacts";
DisableEnableControls(true);
}
else
DisableEnableControls(false);
}
catch (Exception ex)
{
DisableEnableControls(false);
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
void changeInfoToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
UserForm changeInfoForm = new UserForm(false, false, true);
changeInfoForm.Font = new Font(this.Font.Name, this.FontSize, this.Font.Style, this.Font.Unit, this.Font.GdiCharSet, this.Font.GdiVerticalFont);
var userElement = from q in Variables.xDocument.Descendants("User")
where q.Attribute("ID").Value == Variables.CurrentUserID
select q;
string username = userElement.First().Attribute("UserName").Value;
string email = userElement.First().Attribute("Email").Value;
changeInfoForm.textBoxUsername.Text = username;
changeInfoForm.textBoxEmail.Text = email;
changeInfoForm.ShowDialog();
if (Variables.CurrentUserName!= "" && Variables.CurrentUserID!= "")
{
int contactsNumbers = Variables.xDocument.Descendants("Item").Where(q => q.Attribute("UserID").Value == Variables.CurrentUserID).Count();
this.Text = Variables.Caption + Variables.CurrentUserName + ": " + contactsNumbers.ToString() + " Contacts";
DisableEnableControls(true);
}
else
DisableEnableControls(false);
}
catch (Exception ex)
{
DisableEnableControls(false);
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
void aboutProgrammerToolStripMenuItem_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("http://vkontakte.ru/id2688556");
}
#endregion
void LoadPhoneBookItems()
{
try
{
listView1.Items.Clear();
var items = from q in Variables.xDocument.Descendants("Item")
where q.Attribute("UserID").Value == Variables.CurrentUserID
select q;
if (items.Count() < 1)
return;
foreach (var item in items)
{
ListViewItem listViewItems;
if (christianToolStripMenuItem.Checked)
listViewItems = new ListViewItem(new string[]
{ item.Attribute("Name").Value,
item.Attribute("Phone").Value,
item.Attribute("Mobile").Value,
item.Attribute("Email").Value,
item.Attribute("Address").Value,
item.Attribute("RegDate").Value});
else
listViewItems = new ListViewItem(new string[]
{ item.Attribute("Name").Value,
item.Attribute("Phone").Value,
item.Attribute("Mobile").Value,
item.Attribute("Email").Value,
item.Attribute("Address").Value,
ConvertToPersianDate(item.Attribute("RegDate").Value)});
listViewItems.Name = "Item" + item.Attribute("ID").Value;
listView1.Items.Add(listViewItems);
}
}
catch (Exception ex)
{
DisableEnableControls(false);
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
void ApplySettings()
{
try
{
if (Variables.xDocument == null)
{
DisableEnableControls(false);
return;
}
var Settings = (from q in Variables.xDocument.Descendants("Setting")
where q.Attribute("UserID").Value == Variables.CurrentUserID
select q).First();
if (Settings.Attribute("RightToLeft").Value == "Yes")
rightToLeftToolStripMenuItem_Click(null, null);
else
leftToRightToolStripMenuItem_Click(null, null);
if (Settings.Attribute("Dates").Value == "Persian")
{
persianToolStripMenuItem.Checked = true;
christianToolStripMenuItem.Checked = false;
}
else
{
persianToolStripMenuItem.Checked = false;
christianToolStripMenuItem.Checked = true;
}
this.FontSize = float.Parse(Settings.Attribute("FontSize").Value);
this.Font = new Font(this.Font.Name, this.FontSize, this.Font.Style, this.Font.Unit, this.Font.GdiCharSet, this.Font.GdiVerticalFont);
if (this.FontSize == 8)
{
toolStripMenuItemFontSize8.Checked = true;
toolStripMenuItemFontSize10.Checked = false;
toolStripMenuItemFontSize12.Checked = false;
toolStripMenuItemFontSize14.Checked = false;
toolStripMenuItemFontSize16.Checked = false;
toolStripMenuItemFontSize18.Checked = false;
}
else if (this.FontSize == 10)
{
toolStripMenuItemFontSize8.Checked = false;
toolStripMenuItemFontSize10.Checked = true;
toolStripMenuItemFontSize12.Checked = false;
toolStripMenuItemFontSize14.Checked = false;
toolStripMenuItemFontSize16.Checked = false;
toolStripMenuItemFontSize18.Checked = false;
}
else if (this.FontSize == 12)
{
toolStripMenuItemFontSize8.Checked = false;
toolStripMenuItemFontSize10.Checked = false;
toolStripMenuItemFontSize12.Checked = true;
toolStripMenuItemFontSize14.Checked = false;
toolStripMenuItemFontSize16.Checked = false;
toolStripMenuItemFontSize18.Checked = false;
}
else if (this.FontSize == 14)
{
toolStripMenuItemFontSize8.Checked = false;
toolStripMenuItemFontSize10.Checked = false;
toolStripMenuItemFontSize12.Checked = false;
toolStripMenuItemFontSize14.Checked = true;
toolStripMenuItemFontSize16.Checked = false;
toolStripMenuItemFontSize18.Checked = false;
}
else if (this.FontSize == 16)
{
toolStripMenuItemFontSize8.Checked = false;
toolStripMenuItemFontSize10.Checked = false;
toolStripMenuItemFontSize12.Checked = false;
toolStripMenuItemFontSize14.Checked = false;
toolStripMenuItemFontSize16.Checked = true;
toolStripMenuItemFontSize18.Checked = false;
}
else if (this.FontSize == 18)
{
toolStripMenuItemFontSize8.Checked = false;
toolStripMenuItemFontSize10.Checked = false;
toolStripMenuItemFontSize12.Checked = false;
toolStripMenuItemFontSize14.Checked = false;
toolStripMenuItemFontSize16.Checked = false;
toolStripMenuItemFontSize18.Checked = true;
}
}
catch (Exception ex)
{
DisableEnableControls(false);
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
void MainForm_Shown(object sender, EventArgs e)
{
try
{
if (!File.Exists(Variables.DBFile))
{
newUserToolStripMenuItem_Click(null, null);
return;
}
Variables.xDocument = XDocument.Parse(TripleDES.DecryptFromFile(Variables.DBFile, TripleDES.ByteKey, TripleDES.IV));
var users = from q in Variables.xDocument.Descendants("User")
select q;
if (users.Count() < 1)//No user exist
{
newUserToolStripMenuItem_Click(null, null);
return;
}
else//More than one user exist
{
changeUserToolStripMenuItem_Click(null, null);
}
}
catch (Exception ex)
{
DisableEnableControls(false);
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
try
{
File.Delete(Variables.DBFile);
}
catch
{
MessageBox.Show("Будь-ласка, видаліть файл бази даних", "Критична помилка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
void DisableEnableControls(bool enable)
{
if (enable)
{
changeInfoToolStripMenuItem.Enabled = settingsToolStripMenuItem.Enabled = true;
textBoxSearch.Enabled = listView1.Enabled = true;
buttonNew.Enabled = true;
}
else
{
changeInfoToolStripMenuItem.Enabled = settingsToolStripMenuItem.Enabled = false;
textBoxSearch.Enabled = listView1.Enabled = false;
buttonNew.Enabled = false;
}
}
string ConvertToPersianDate(string stringDate)
{
try
{
DateTime dateTime = DateTime.Parse(stringDate);
PersianCalendar persianCalendar = new PersianCalendar();
var str = persianCalendar.GetYear(dateTime).ToString() + " / " +
persianCalendar.GetMonth(dateTime).ToString() + " / " +
persianCalendar.GetDayOfMonth(dateTime).ToString() + " " +
persianCalendar.GetHour(dateTime).ToString() + ":" +
persianCalendar.GetMinute(dateTime).ToString() + ":" +
persianCalendar.GetSecond(dateTime).ToString();
return str;
}
catch (Exception ex)
{
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
return "";
}
}
#region listview
void textBoxSearch_TextChanged(object sender, EventArgs e)
{
try
{
if (textBoxSearch.Text.Trim() == "")
{
LoadPhoneBookItems();
return;
}
listView1.Items.Clear();
var query = from q in Variables.xDocument.Descendants("Item")
where q.Attribute("UserID").Value == Variables.CurrentUserID &&
(q.Attribute("Name").Value.ToLower().Contains(textBoxSearch.Text.Trim().ToLower())
q.Attribute("Phone").Value.ToLower().Contains(textBoxSearch.Text.Trim().ToLower())
q.Attribute("Mobile").Value.ToLower().Contains(textBoxSearch.Text.Trim().ToLower())
q.Attribute("Email").Value.ToLower().Contains(textBoxSearch.Text.Trim().ToLower())
q.Attribute("Address").Value.ToLower().Contains(textBoxSearch.Text.Trim().ToLower()))
select q;
if (query.Count() < 1) return;
foreach (var item in query)
{
ListViewItem listViewItems = new ListViewItem(new string[]
{ item.Attribute("Name").Value,
item.Attribute("Phone").Value,
item.Attribute("Mobile").Value,
item.Attribute("Email").Value,
item.Attribute("Address").Value,
item.Attribute("RegDate").Value});
listViewItems.Name = "Item" + item.Attribute("ID").Value;
listView1.Items.Add(listViewItems);
}
}
catch (Exception ex)
{
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
//var item = listView1.GetItemAt(e.X, e.Y);
buttonEdit_Click(null, null);
}
#endregion
}
}
Форма введення запису про абонентів:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using Phonebook.Classes;
using System.Xml.Linq;
using System.IO;
using System.Drawing.Imaging;
namespace Phonebook
{
public partial class ItemForm: Form
{
public string ItemID = "";
bool NewItem = false;
bool EditItem = false;
public ItemForm(bool newItem, bool editItem)
{
InitializeComponent();
this.tableLayoutPanel1.CellPaint += new TableLayoutCellPaintEventHandler(tableLayoutPanel1_CellPaint);
//////////////////////
this.NewItem = newItem;
this.EditItem = editItem;
if (NewItem)
this.Text = "Додати новий запис";
else if (EditItem)
this.Text = "Редагувати запис";
}
void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
{
try
{
if (e.Row % 2 == 0)
{
Graphics g = e.Graphics;
Rectangle r = e.CellBounds;
g.FillRectangle(new SolidBrush(Color.FromArgb(225, 225, 225)), r);
}
}
catch (Exception ex)
{
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
private void buttonSubmit_Click(object sender, EventArgs e)
{
try
{
errorProvider1.Clear();
#region add new item
if (NewItem)
{
if (textBoxName.Text.Trim() == "")
{
errorProvider1.SetError(textBoxName, "Будь-ласка, введіть ім'я");
return;
}
int maxID = 0;
try
{
maxID = (from q in Variables.xDocument.Descendants("Item")
where q.Attribute("UserID").Value == Variables.CurrentUserID
select (int)q.Attribute("ID")).Max();
}
catch { }
maxID++;
XElement newItem = new XElement("Item", new XAttribute("ID", maxID),
new XAttribute("UserID", Variables.CurrentUserID),
new XAttribute("Name", textBoxName.Text.Trim()),
new XAttribute("Mobile", textBoxMobile.Text.Trim()),
new XAttribute("Phone", textBoxPhone.Text.Trim()),
new XAttribute("Email", textBoxEMail.Text.Trim()),
new XAttribute("Address", textBoxAddress.Text.Trim()),
new XAttribute("RegDate", DateTime.Now.ToString()));
var ItemsElement = (from q in Variables.xDocument.Descendants("Items")
select q).First();
ItemsElement.Add(newItem);
}
#endregion
#region edit item
else if (EditItem)
{
if (textBoxName.Text.Trim() == "")
{
errorProvider1.SetError(textBoxName, "Будь-ласка, введіть ім'я");
return;
}
var theItem = (from q in Variables.xDocument.Descendants("Item")
where q.Attribute("ID").Value == this.ItemID
select q).First();
theItem.Attribute("Name").Value = textBoxName.Text.Trim();
theItem.Attribute("Mobile").Value = textBoxMobile.Text.Trim();
theItem.Attribute("Phone").Value = textBoxPhone.Text.Trim();
theItem.Attribute("Email").Value = textBoxEMail.Text.Trim();
theItem.Attribute("Address").Value = textBoxAddress.Text.Trim();
}
#endregion
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
//Variables.xDocument.Save("debug.xml");
this.Close();
}
catch (Exception ex)
{
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
#region
Image ResizeImage(Image FullsizeImage, int NewWidth, int MaxHeight, bool OnlyResizeIfWider)
{
// Prevent using images internal thumbnail
FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
if (OnlyResizeIfWider)
{
if (FullsizeImage.Width <= NewWidth)
{
NewWidth = FullsizeImage.Width;
}
}
int NewHeight = FullsizeImage.Height * NewWidth / FullsizeImage.Width;
if (NewHeight > MaxHeight)
{
// Resize with height instead
NewWidth = FullsizeImage.Width * MaxHeight / FullsizeImage.Height;
NewHeight = MaxHeight;
}
System.Drawing.Image NewImage = FullsizeImage.GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero);
// Clear handle to original file so that we can overwrite it if necessary
FullsizeImage.Dispose();
// Save resized picture
return NewImage;
}
string ImageToBase64String(Image image, ImageFormat format)
{
MemoryStream memory = new MemoryStream();
image.Save(memory, format);
string base64 = Convert.ToBase64String(memory.ToArray());
memory.Close();
return base64;
}
Image ImageFromBase64String(string base64)
{
MemoryStream memory = new MemoryStream(Convert.FromBase64String(base64));
Image result = Image.FromStream(memory);
memory.Close();
return result;
}
#endregion
}
}
Форма користувача:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml.Linq;
using Phonebook.Classes;
using System.Diagnostics;
using System.Net.Mail;
using System.Net;
namespace Phonebook
{
public partial class UserForm: Form
{
bool NewUser = false;
bool ChangeUser = false;
bool ChangeInfo = false;
public UserForm(bool newUser, bool changeUser, bool changeInfo)
{
InitializeComponent();
/////////////////////
this.NewUser = newUser;
this.ChangeInfo = changeInfo;
this.ChangeUser = changeUser;
if (NewUser)
{
this.Text = "Додати нового користувача";
labelPass1.Text = "Пароль:";
labelPass2.Text = "Підтвердити пароль:";
checkBoxForgetPass.Enabled = false;
}
else if (ChangeUser)
{
this.Text = "Обрати користувача";
labelPass1.Text = "Пароль:";
labelPass2.Text = "Новий пароль:";
labelPass2.Enabled = textBoxPassword2.Enabled = false;
labelEmail.Enabled = textBoxEmail.Enabled = false;
}
else if (ChangeInfo)
{
this.Text = "Змінити інформацію користувача";
labelPass1.Text = "Старий пароль:";
labelPass2.Text = "Новий пароль:";
}
}
private void buttonSubmit_Click(object sender, EventArgs e)
{
try
{
errorProvider1.Clear();
#region Forgets the password
if (checkBoxForgetPass.Enabled && checkBoxForgetPass.Checked)
{
if (textBoxUsername.Text.Trim() == "")
{
errorProvider1.SetError(this.textBoxUsername, "Будь-ласка, введіть ім'я користувача");
textBoxUsername.Focus();
return;
}
errorProvider1.Clear();
var user = Variables.xDocument.Descendants("User").Where(q => q.Attribute("UserName").Value.ToLower() == textBoxUsername.Text.Trim().ToLower());
if (user.Count() < 1)
{
errorProvider1.SetError(this.textBoxUsername, "Таке ім'я користувача відсутнє у базі даних!!!!");
return;
}
string password = user.First().Attribute("Password").Value;
try
{
NetworkCredential loginInfo = new NetworkCredential("username", "password");
MailMessage msg = new MailMessage();
msg.From = new MailAddress("CyberkillerPS@gmail.ru");
msg.To.Add(new MailAddress(user.First().Attribute("Email").Value));
msg.Subject = "Phonebook Password";
msg.Body = "Yours Password = " + password;
msg.IsBodyHtml = true;
SmtpClient client = new SmtpClient("smtp.gmail.ru");
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Credentials = loginInfo;
client.Send(msg);
MessageBox.Show("Ваш пароль був відісланий вам на email", "Відправка пароля", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Помилка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return;
}
#endregion
#region add new user
else if (this.NewUser)
{
if (textBoxUsername.Text.Trim() == "" && textBoxUsername.Enabled)
{
errorProvider1.SetError(this.textBoxUsername, "Будь-ласка, введіть ім'я користувача");
return;
}
else if (textBoxPassword1.Text.Trim() == "" && textBoxPassword1.Enabled)
{
errorProvider1.SetError(this.textBoxPassword1, "Будь-ласка, введіть пароль");
return;
}
else if (textBoxPassword2.Text.Trim() == "" && textBoxPassword2.Enabled)
{
errorProvider1.SetError(this.textBoxPassword2, "Будь-ласка, введіть підтвердження пароля");
return;
}
else if (textBoxPassword2.Text.Trim()!= textBoxPassword1.Text.Trim())
{
errorProvider1.SetError(this.textBoxPassword1, "Ваші паролі повинні співпадати");
errorProvider1.SetError(this.textBoxPassword2, "Ваші паролі повинні співпадати");
return;
}
else if (textBoxEmail.Text.Trim() == "" && textBoxEmail.Enabled)
{
errorProvider1.SetError(this.textBoxEmail, "Будь-ласка, введіть правельний Email");
return;
}
if (!File.Exists(Variables.DBFile))
{
Variables.xDocument = new XDocument(
new XComment("\n Don't edit manually \n"),
new XElement("PhoneBook",
new XElement("Users",
new XElement("User",
new XAttribute("ID", "01"),
new XAttribute("UserName", textBoxUsername.Text.Trim()),
new XAttribute("Password", textBoxPassword1.Text.Trim()),
new XAttribute("Email", textBoxEmail.Text.Trim()),
new XAttribute("RegDate", DateTime.Now.ToString()))),
new XElement("Settings",
new XElement("Setting",
new XAttribute("UserID", "01"),
new XAttribute("RightToLeft", "NO"),
new XAttribute("Dates", "Persian"),
new XAttribute("FontSize", "10"))),
new XElement("Items")));
Variables.CurrentUserID = "01";
}
else
{
Variables.xDocument = XDocument.Parse(TripleDES.DecryptFromFile(Variables.DBFile, TripleDES.ByteKey, TripleDES.IV));
var SameUserQuery = from q in Variables.xDocument.Descendants("User")
where q.Attribute("UserName").Value.ToLower() == textBoxUsername.Text.Trim().ToLower()
select q;
if (SameUserQuery.Count() >= 1)
{
errorProvider1.SetError(this.textBoxUsername, "Таке ім'я користувача вже існує, Будь-ласка, оберіть інше");
return;
}
int maxID = 0;
try
{
maxID = (from q in Variables.xDocument.Descendants("User")
select (int)q.Attribute("ID")).Max();
}
catch { }
maxID++;
Variables.CurrentUserID = maxID.ToString();
XElement xElement = new XElement("User",
new XAttribute("ID", maxID),
new XAttribute("UserName", textBoxUsername.Text.Trim()),
new XAttribute("Password", textBoxPassword1.Text.Trim()),
new XAttribute("Email", textBoxEmail.Text.Trim()),
new XAttribute("RegDate", DateTime.Now.ToString()));
var usersElement = (from q in Variables.xDocument.Descendants("Users")
select q).First();
usersElement.Add(xElement);
xElement = new XElement("Setting",
new XAttribute("UserID", maxID),
new XAttribute("RightToLeft", "NO"),
new XAttribute("Dates", "Persian"),
new XAttribute("FontSize", "10"));
var settingsElement = (from q in Variables.xDocument.Descendants("Settings")
select q).First();
settingsElement.Add(xElement);
}
Variables.CurrentUserName = textBoxUsername.Text.Trim();
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
//Variables.xDocument.Save("debug.xml");
}
#endregion
#region change user
else if (this.ChangeUser)
{
if (Variables.xDocument == null)
{
MessageBox.Show("Ваше ім'я користувача та пароль невірні", "Помилка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (textBoxUsername.Text.Trim() == "")
{
errorProvider1.SetError(this.textBoxUsername, "Будь-ласка, введіть ім'я користувача");
return;
}
else if (textBoxPassword1.Text.Trim() == "" && textBoxPassword1.Enabled)
{
errorProvider1.SetError(this.textBoxPassword1, "Будь-ласка, введіть пароль");
return;
}
var query = from q in Variables.xDocument.Descendants("User")
where textBoxUsername.Text.Trim().ToLower() == q.Attribute("UserName").Value.ToLower()
&& textBoxPassword1.Text.Trim().ToLower() == q.Attribute("Password").Value.ToLower()
select q;
if (query.Count() == 1)
{
Variables.CurrentUserID = query.First().Attribute("ID").Value;
Variables.CurrentUserName = textBoxUsername.Text.Trim();
}
else
{
Variables.CurrentUserID = "";
Variables.CurrentUserName = "";
MessageBox.Show("Ваше ім'я користувача та пароль невірні", "Помилка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
#endregion
#region change info
else if (this.ChangeInfo)
{
bool changePassword = true;
if (textBoxUsername.Text.Trim() == "" && textBoxUsername.Enabled)
{
errorProvider1.SetError(this.textBoxUsername, "Ваше ім'я користувача та пароль невірні");
return;
}
else if (textBoxEmail.Text.Trim() == "" && textBoxEmail.Enabled)
{
errorProvider1.SetError(this.textBoxEmail, "Будь-ласка, введіть вірний Email");
return;
}
else if (textBoxPassword1.Text.Trim() == textBoxPassword2.Text.Trim() && textBoxPassword2.Text.Trim() == "")
{
changePassword = false;
}
else if (textBoxPassword1.Text.Trim() == "" && textBoxPassword1.Enabled)
{
errorProvider1.SetError(this.textBoxPassword1, "Будь-ласка, введіть старий пароль");
return;
}
else if (textBoxPassword2.Text.Trim() == "" && textBoxPassword2.Enabled)
{
errorProvider1.SetError(this.textBoxPassword2, "Будь-ласка, введіть новий пароль");
return;
}
errorProvider1.Clear();
var query = (from q in Variables.xDocument.Descendants("User")
where q.Attribute("ID").Value == Variables.CurrentUserID
select q).First();
string oldPassword = query.Attribute("Password").Value;
if (oldPassword.ToLower()!= textBoxPassword1.Text.Trim().ToLower() && changePassword)
{
errorProvider1.SetError(this.textBoxPassword1, "Старий пароль невірний");
return;
}
else if (oldPassword == textBoxPassword1.Text.Trim() && changePassword)
{
query.Attribute("UserName").Value = textBoxUsername.Text.Trim();
query.Attribute("Password").Value = textBoxPassword2.Text.Trim();
query.Attribute("Email").Value = textBoxEmail.Text.Trim();
}
else if (!changePassword)
{
query.Attribute("UserName").Value = textBoxUsername.Text.Trim();
query.Attribute("Email").Value = textBoxEmail.Text.Trim();
}
Variables.CurrentUserID = query.Attribute("ID").Value;
Variables.CurrentUserName = textBoxUsername.Text.Trim();
TripleDES.EncryptToFile(Variables.xDocument.ToString(SaveOptions.DisableFormatting), Variables.DBFile, TripleDES.ByteKey, TripleDES.IV);
//Variables.xDocument.Save("debug.xml");
}
#endregion
this.Close();
}
catch (Exception ex)
{
Variables.CurrentUserID = Variables.CurrentUserName = "";
StackFrame file_info = new StackFrame(true);
Messages.error(ref file_info, ex.Message, this);
}
}
}
}
Додаток 2: Головне вікно програми
Додаток 3: Форма користувача БД
Додаток 4: Форма створення нового запису в БД