Тема: cтворення програмного проекта простої бази даних «Учні» з даними про прізвище, ім'я, успішність, забезпечення виведення даних про учнів за зазначиними критеріями.
Мета: навчити основам роботи з базами даних SQL з використанням мови програмування C#.
Учні повинні знати:
Учні повинні мати уявлення про можливості комплексу C# з SQLight.
Учні повинні вміти:
Обладнання: комп'ютери зі встановленими ОС, середовищем MonoDevelop і переглядач баз даних для SQLite (DB Browser for SQLite).
Структура уроку
Примітка. Цей урок проводять лише після успішного опанування матеріалом уроків щодо вивчення SQL і виконання усіх його практичних завдань.
Хід уроку
1. Організаційний момент
Вітання з класом. Перевірка присутності і готовності учнів до уроку.
2. Актуалізація опорних знань
Дати відповідь на питання і порівняти з очікуваним.
Під'єднання бази даних MySQL/MariaDB у програмі мовою C# здійснюють за допомогою спеціального приєднувача (connector) — див опис встановлення й використання.
Компіляцію такої програми Program.cs здійснюють вказівкою терміналу:
mcs -r:System.dll -r:System.Data.dll -r:MySql.Data.dll Program.cs
Розглянемо випадок, коли попередньо виконано такі вказівки MySQL.
SET collation_connection = 'utf8_unicode_ci'; CREATE DATABASE school; ALTER DATABASE school CHARACTER SET utf8 COLLATE utf8_unicode_ci; USE school; SOURCE structure.sql; SOURCE data.sql;
Примітка. Дія всіх вказівок з CHARACTER SET utf8 COLLATE utf8_unicode_ci спрямована на уникнення винятків, породжених конфліктами різних схем упорядкування й порівняння.
У цьому випадку програма мовою C# може мати такий вигляд
using System; using System.Data; using System.Data.SqlClient; public class Test { public static void Main(string[] args) { string connectionString = "Server=localhost; UID=root; Password=; Database=school"; // Адреса сервера Користувач Пароль База даних IDbConnection сonnection; using (сonnection = new SqlConnection(connectionString)) { try { сonnection.Open(); Console.WriteLine("OK2"); using (IDbCommand dbcmd = сonnection.CreateCommand()) { dbcmd.CommandText = "SELECT * FROM pupils WHERE form = '11Б';"; using (IDataReader reader = dbcmd.ExecuteReader()) { while(reader.Read()) Console.WriteLine (reader["sename"]+" "+reader["name"]+" "+ reader["form"] +" "+reader["no"]); } } } catch(Exception e) { Console.WriteLine(e.Message); } } } }
з таким виведенням у консоль.
ЛИСЕНКО ДМИТРО 11Б 113 РУДЕНКО ОЛЕГ 11Б 114 САВЧЕНКО ВАЛЕРІЙ 11Б 115 ПЕТРЕНКО ЛЕОНІД 11Б 116 ШУЛЬГА ГАЛИНА 11Б 117 РАДЧЕНКО ТЕТЯНА 11Б 118 КОРОЛЬ НАДІЯ 11Б 119 ОСТАПЕНКО ЛЮДМИЛА 11Б 120
У момент створення даної розробки на ПК з використанням ОС Linux Mint 20.3 Una Mate при дотриманні усіх рекомендацій програма не могла виявити сервер MySQL чи MariaDB, який у цей час був працездатний. У мережі є публікації зі скаргами на такі випадки без порад, як подолати проблеми. Тому у розробці використано SQLite.
SQLite — полегшена система керування реляційними базами даних у вигляді бібліотеки на основі стандарту SQL-92.
Початковий код SQLite поширюють як суспільне надбання (анґлійською public domain). Його можна використовувати без обмежень та безоплатно з будь-якою метою.
Фінансову підтримку розробників SQLite здійснює спеціально створений консорціум, до якого входять такі компанії, як Adobe, Oracle, Mozilla, Nokia, Bentley[en] і Bloomberg. З 2018 року SQLite, як й JSON та CSV, рекомендований Бібліотекою Конгресу США формат зберігання структурованого набору даних.
Особливістю SQLite є те, що вона не використовує парадигму клієнт-сервер. Рушій SQLite не є окремим процесом, з яким взаємодіє застосунок, а надає бібліотеку, з якою програма компілюється і рушій стає складовою частиною програми. Таким чином, як протокол обміну використовуються виклики функцій бібліотеки SQLite. Такий підхід зменшує накладні витрати, час відгуку і спрощує програму. SQLite зберігає всю базу даних (включаючи визначення, таблиці, індекси і дані) в єдиному стандартному файлі на тому комп'ютері, на якому виконують застосунок. Кілька процесів або потоків можуть одночасно без жодних проблем читати дані з однієї бази. Запис у базу можна здійснити лише в тому випадку, коли жодних інших запитів у цей час не обслуговують. Інакше спроба запису закінчується невдачею з поверненням у програму коду помилки. Іншим варіантом розвитку подій є автоматичне повторення спроб запису протягом заданого інтервалу часу.
Запит до бази даних SQLite здійснюють з використанням класу SqliteCommand, що є втіленням інтерфейсу System.Data.IDbCommand. Для створення об'єкта SqliteCommand використовують один з таких конструкторів (у дужках вказано типи відповідних параметрів):
SqliteCommand();
SqliteCommand(String) — створює вказівку з даним виконуваним виразом SQL;
SqliteCommand(String, SqliteConnection) — створює вказівку з даними виконуваним виразом SQL і підключенням до бази даних;
SqliteCommand(String, SqliteConnection, SqliteTransaction) — створює вказівку з даними виконуваним виразом SQL, підключенням до бази даних і застосовуваною транзакцією.
Властивості SqliteCommand
CommandText — виконувана вказівка SQL;
CommandTimeout — значення часового інтервалу в секундах, після якого SqliteCommand припиняє спроби виконати команду. Як усталено дорівнює 30 секунд. Значення 0 представляє відсутності інтервалу;
Parameters — параметри вказівки;
Connection — використане підключення SqliteConnection.
ExecuteNonQuery — повертає кількість змінених записів. Прийнятний для виразів INSERT, UPDATE, DELETE, CREATE;
ExecuteReader — повертає лічені з таблиці рядки. Прийнятний для виразу SELECT;
ExecuteScalar — повертає одне скалярне значення. Прийнятний для виразу SELECT у парі з однією із вбудованих функцій SQL (Min, Max, Sum, Count тощо).
При наявності у поточній теці бази даних school.db (такої самої, що вже була розглянута на уроці, присвяченому MySQL/MariaDB), створеної за вказівками, записаними у файлах structure.txt і data.txt, програма з таким кодом
using System; using System.IO; using System.Data; using Mono.Data.Sqlite; public class Example { public static void Main() { string db = "URI=file:school.db"; // Адреса БД у поточній теці SqliteConnection connection = new SqliteConnection(db);// Оголошення зв'язку з БД connection.Open(); // Відкриття зв'язку з БД SqliteCommand command = connection.CreateCommand(); // Створення вказівки запиту command.CommandText = "SELECT * FROM pupils WHERE form = '11Б';"; // Текст запиту try { IDataReader reader = command.ExecuteReader(); while (reader.Read()) System.Console.WriteLine("{0} {1} {2} {3}", reader.GetString(0), reader.GetString(1), reader.GetString(2), reader.GetString(3)); reader.Dispose(); // Очищення пам'яті } catch (Exception e) {System.Console.WriteLine(e.Message);} command.Dispose(); // Очищення пам'яті connection.Close(); } }
здійснить таке виведення у консоль.
ЛИСЕНКО ДМИТРО 11Б 113 РУДЕНКО ОЛЕГ 11Б 114 САВЧЕНКО ВАЛЕРІЙ 11Б 115 ПЕТРЕНКО ЛЕОНІД 11Б 116 ШУЛЬГА ГАЛИНА 11Б 117 РАДЧЕНКО ТЕТЯНА 11Б 118 КОРОЛЬ НАДІЯ 11Б 119 ОСТАПЕНКО ЛЮДМИЛА 11Б 120
Компіляцію програми Program.cs можна виконати такою вказівкою терміналу
csc Program.cs -r:System.Data.dll -r:Mono.Data.Sqlite.dll
Примітка
Не всі структури мови SQL прийнятні для SQLite. Це стосується, наприклад, типу Enum та прикінцевих вказівок файлу structure.sql. Порівняйте з файлом structure.txt, вказівки якого прийнятні для SQLite.
IDataReader можна замінити на SqliteDataReader.
Метод ExecuteReader класу SqliteCommand повертає об'єкт SqliteDataReader, який використовують для читання даних.
Основні властивості класу SqliteDataReader
Основні методи класу SqliteDataReader
Read() — зчитує наступний рядок в отриманому наборі;
Get*(Int32) — повертає значення стовпця зі вказаним номером. Нумерацію починають з нуля. Замість зірочки пишуть відповідний тип даних. Є опис анґлійською. Невідповідність типу даних призводить до виключення.
Close() — закриває об'єкт SqliteDataReader.
4. Інструктаж з ТБ
5. Закріплення вивченого матеріалу
На початку виконання завдань поточна тека не має не містити бази даних school.db. При виконанні завдань використати демонстраційні розв'язання a, b, c завдань уроку 1 щодо SQL.
Завдання 1. Створити програму мовою C#, яка засобами SQLite:
створить базу даних school.db — достатньо відкрити зв'язок з БД;
виконає запити створення структури й наповнення таблиць бази даних school згідно з вказівками, записаними у файлах structure.txt і data.txt теки проєкту.
Створену базу даних відкрити у середовищі переглядача баз даних для SQLite (DB Browser for SQLite) і отримати вікно такого вигляду.
Примітка. Вказівка SOURCE не є вказівкою SQL, тому нею скористатися буде неможливо. Згадані вище файли потрібно опрацювати: склеювати рядки в один до появи першої крапки з комою, після чого здійснювати запит, використавши створений рядок.
Порівняти з очікуваними кодом.
Завдання 2. Створити програму мовою C#, яка засобами SQLite:
отримає перелік усіх наявних таблиць створеної бази даних school.db вказівкою
SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;
замість SHOW TABLES, якої немає в SQLite;
для кожної таблиці виведе у консоль назви цих таблиць і результати запиту щодо їхньої структури у вигляді таблиці:
запит здійснювати вказівкою: PRAGMA table_info(назва_таблиці);
System.Console.WriteLine("\n"+tab[j]+"\n"+ "┌──────────┬──────────────┬─────────────────────┬─────────┬─────────┬─────────────┐\n"+ "│column id │ name │ type │ notnull │ default │ primary key │\n"+ "├──────────┼──────────────┼─────────────────────┼─────────┼─────────┼─────────────┤");
Console.WriteLine("│ {0} │ {1} │ {2} │ {3} │ {4} │ {5} │", reader_.GetInt32(0), Fill(reader_.GetString(1),12), Fill(reader_.GetString(2),19), Fill(reader_.GetBoolean(3).ToString(),7), Fill(reader_.GetValue(4).ToString(),7),Fill(reader_.GetBoolean(5).ToString(),11));Тут:
reader_ — представник IDataReader — відповідь на запит про структуру таблиці;
Fill — функція, що повертає результат дописування пробілів до першого аргумента з метою отримати рядок довжини, що дорівнює значенню другого параметра;
Console.WriteLine ("└──────────┴──────────────┴─────────────────────┴─────────┴─────────┴─────────────┘");
Порівняти з очікуваними виведенням і кодом.
Завдання 3. Використовуючи попередньо апробований код SQL, створити програму мовою C# для виведення у консоль у вигляді асоціативних масивів таких даних:
всі поля з таблиці pupils про учнів 11Б класу (поле form);
всі поля з таблиці classroom про аудиторії корпусу A (птоле building, латиниця), ємність яких (поле capacity) менше 24 і більше від 16 (2 варіанти);
з таблиці pupils про прізвище (поле sename) та ім'я (поле name) усіх тих записів, у яких прізвище закінчується на 'УК';
з таблиці pupils про прізвище (поле sename) та ім'я (поле name) усіх тих записів, у яких ім'я (поле name) 'Андрій' або 'Григорій';
з таблиці pupils про загальну кількість учнів;
з таблиці teachers про категорії (поле quality) та кількість учителів цієї категорії;
з таблиці teachers про категорії (поле quality) та кількість учителів цієї категорії, що перевищує 1;
з таблиці marks про прізвище (поле sename) й оцінку (поле mark) за день 2020-09-24 у порядку зростання оцінки;
з таблиці marks про прізвище (поле sename) й оцінку (поле mark) за день 2020-09-24 у порядку спадання оцінки;
з таблиці marks про прізвище (поле sename) й оцінку (поле mark) за день 2020-09-24 у порядку спадання оцінки лише тих, хто посів 4, 5 і 6 місце у цьому списку з підписами стовпчиків 'Прізвище' й 'Оцінка';
з таблиці courses список всіх дисциплін (поле course) і відповідну інформацію про кафедри з таблиці department у режимах;
Виконати запити й порівняти з очікуваними виведенням і кодом мовою C#. Порівняти результати виведення незаповнених комірок MySQL і SQLite.
Завдання 4. Використовуючи попередньо апробований код SQL, створити програму мовою C# для такого:
створити віртуальну таблицю own_view усіх полів усіх записів таблиці marks, у яких оцінка (поле mark) менша ніж 7;
вивести у консоль у вигляді асоціативних масивів даних own_view.
Виконати запити й порівняти з очікуваними виведенням і кодом.
Завдання 5. Використовуючи попередньо апробований код SQL, створити програму мовою C# для такого:
Виконати запити й порівняти з очікуваними виведенням і кодом.
6. Підбиття підсумків уроку
Дати відповідь на запитання і порівняти з очікуваним.
Виставлення оцінок.
7. Домашнє завдання
У разі потреби доробити завдання. Вивчити систаксис під'єднання бази даних і здійснення запиту мовою SQL з програми мовою C#. Написати програму мовою C#, яка зчитуватиме з клавіатури й виконуватиме запити SQL до тих пір, поки не буде введено порожній рядок.
Текст упорядкував Олександр Рудик.