Przeglądaj źródła

миграции

Евгений Колесников 4 miesięcy temu
rodzic
commit
dc10c988f7
3 zmienionych plików z 237 dodań i 4 usunięć
  1. 1 1
      articles/api_asp_net_core.md
  2. 230 0
      articles/migrations.md
  3. 6 3
      readme.md

+ 1 - 1
articles/api_asp_net_core.md

@@ -1,6 +1,6 @@
 Предыдущая лекция |  | Следующая лекция
 :----------------:|:----------:|:----------------:
-[Вывод списка материалов продукта. CRUD материалов продукта](./cs_product_material.md) | [Содержание](../readme.md#разработка-своего-api) | [Авторизация и аутентификация. Методы авторизации. Basic-авторизация.](./api_auth.md)
+[Вывод списка материалов продукта. CRUD материалов продукта](./cs_product_material.md) | [Содержание](../readme.md#разработка-api) | [Авторизация и аутентификация. Методы авторизации. Basic-авторизация.](./api_auth.md)
 
 # API. REST API. Создание сервера ASP.NET Core.
 

+ 230 - 0
articles/migrations.md

@@ -0,0 +1,230 @@
+# Системы миграции данных
+
+Модель данных в процессе разработки имеет свойство изменяться, и в какой-то момент она перестает соответствовать базе данных. Функция **системы миграции** сводится к тому, чтобы синхронизировать структуру БД с моделью данных в приложении без потери существующих данных.
+
+Не помню, затрагивали ли мы этот момент при выборе фреймворка для работы с БД, на всякий случай расскажу еще раз.
+
+Существует два варианта синхронизации модели и базы:
+
+- __Code First__ - "сначала код", то есть мы описываем модель и структура базы данных меняется в соответствии с моделью (мы этот подход не используем, он применяется в __Entity Framework__)
+- __DB First__ - "база данных первична", то есть мы сначала меняем структуру базы данных и только потом приводим модель в соответствие с ней. Это как раз наш случай.
+
+Для того, чтобы структура базы данных менялась в нужных версиях приложений (раньше в принципе можно, но точно не позже) существуют __системы миграции__, рассмотрим наиболее популярные:
+
+>Взято [отсюда](https://habr.com/ru/companies/crosstech/articles/453930/)
+
+- EF Core Migrations
+
+    Как видно по названию, является частью __Entity Framework__. Нативный инструмент, работающий из коробки без каких-либо плясок с бубном. Большое количество документации, официальной и не очень, простота и т.д. 
+
+    Имеет смысл, если используется __Entity Framework__.
+
+- RoundhousE
+
+    Этот инструмент управления миграциями, распространяемый под лицензией Apache 2.0, работает на движке T-SQL миграций (то есть для миграции пишутся DDL-скрипты).
+
+- ThinkingHome.Migrator
+
+    Инструмент для версионной миграции схемы базы данных под платформу .NET Core, распространяемый под лицензией MIT.
+
+    В целом, проект выглядит перспективным, особенно если развивался бы.
+
+- Fluent Migrator
+
+    Наиболее популярный инструмент миграций, имеющий большую армию поклонников. Распространяется под лицензией Apache 2.0. Как указано в описании, является платформой миграции для .NET, аналогичная Ruby on Rails Migrations. Изменения схемы БД описываются в классах на C#.
+
+    Мне он не понравился из-за того, что нужно писать классы для миграций, а это так называемые "проектные знания", которыми не охота вас загружать
+
+- DBup
+
+    DbUp – это библиотека на .NET, которая помогает накатывать изменения на сервер SQL. Она отслеживает, какие скрипты изменений уже выполнены, и запускает те, которые необходимы для обновления БД. Библиотека выросла из проекта опенсорсного движка блогов на ASP.NET и существует под лицензией MIT, а код лежит на GitHub’е. Миграции описываются с помощью T-SQL.
+
+    ИМХО идеальный вариант для наших ПЕТ- проектов: не нужно изучение лишних сущностей, как в _Fluent Migrator_, достаточно знания SQL
+
+## Добавление возможности миграции в АПИ
+
+В десктопном приложении использовать миграции можно, но не нужно - нет гарантии, что не запустятся одновременно две копии программы. Правильнее миграции накатывать либо администратору БД (скрипты мы в любом случае будем писать), либо при запуске новой версии АПИ (этот вариант предпочтительнее, так как исключается человеческий фактор - миграция применится в тот момент, когда она нужна)
+
+[Делал по этому туториалу](https://medium.com/@niteshsinghal85/dbup-postgresql-dapper-in-asp-net-core-c3be6c580c54)
+
+1. В проекте с АПИ созадем каталог `migrations`, где будем хранить скрипты для миграции
+1. В настройках проекта (файл `*.csproj`) укажем, чтобы все SQL-файлы из этого каталога включались в исполняемый файл
+
+    ```xml
+    <ItemGroup>
+        ...
+        <EmbeddedResource Include="migrations/*.sql" />
+    </ItemGroup>
+    ```
+
+1. Создадим файл для миграции `migrations/agent_type.sql`
+
+    >Вообще миграции предназначены для изменения структуры БД, но никто не запрещает нам выполнять и DML- скрипты, например, для заполнения словарей
+
+    ```sql
+    insert into AgentType values
+        (1, "индивидуальный предприниматель"),
+        (2, "Общество с ограниченной ответственностью");   
+    ```
+
+1. Устанавливаем библиотеку `DBup`
+
+    Можно через __Nuget__, а можно и в консоли:
+
+    ```sh
+    dotnet add package dbup-mysql
+    ```
+
+1. Дописываем в __начало__ нашего `Program.cs` код для накатывания миграций
+
+    ```cs
+    // проверяет наличие возможности подключения к БД
+    EnsureDatabase.For.MySqlDatabase(connectionString);
+
+    // подгатавливает миграцию
+    // куда и что будем накатывать
+    var upgrader = DeployChanges.To
+        .MySqlDatabase(connectionString)
+        .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
+        .LogToConsole()
+        .Build();
+
+    // запуск миграции
+    var result = upgrader.PerformUpgrade();
+
+    // проверка результата миграции
+    if (!result.Successful)
+    {
+        throw new Exception("Не смог сделать миграцию");
+    }
+    ```
+
+    Если все сделали правильно, то в консоли увидите примерно такие логи
+
+    ```
+    2025-09-18 10:31:43 +03:00 [INF] Beginning database upgrade
+    2025-09-18 10:31:43 +03:00 [INF] Checking whether journal table exists
+    2025-09-18 10:31:43 +03:00 [INF] Journal table does not exist
+    2025-09-18 10:31:43 +03:00 [INF] Executing Database Server script 'api_cs.migrations.agent_type.sql'
+    2025-09-18 10:31:43 +03:00 [INF] Checking whether journal table exists
+    2025-09-18 10:31:43 +03:00 [INF] Creating the `schemaversions` table
+    2025-09-18 10:31:44 +03:00 [INF] The `schemaversions` table has been created
+    2025-09-18 10:31:44 +03:00 [INF] Upgrade successful
+    ```
+
+    А в базе добавится таблица `shemaversions`, в которой хранится какие миграции и когда применялись (чтобы повторно не накатить уже выполненную миграцию)
+
+## DDL- запросы для изменения структуры базы данных
+
+Вообще с DDL мы еще не работали (базу разворачивали из готового скрипта), напомню какие команды относятся к DDL:
+
+* **CREATE** – используется для создания объектов базы данных;
+* **ALTER** – используется для изменения объектов базы данных;
+* **DROP** – используется для удаления объектов базы данных.
+
+### Добавление таблиц
+
+В принципе структуру запроса можно и не запоминать - вы всегда можете в _MySQL Workbench_ или _DBeaver_ получить DDL скрипт для существующей таблицы, например `AgentType`:
+
+```sql
+CREATE TABLE `AgentType` (
+  `ID` int NOT NULL AUTO_INCREMENT,
+  `Title` varchar(50) NOT NULL,
+  `Image` varchar(100) DEFAULT NULL,
+  PRIMARY KEY (`ID`)
+)
+```
+
+Думаю тут все более менее очевидно - задается название таблицы и описываются ее поля
+
+- параметр `NOT NULL` означает, что поле обязательное
+- параметр `DEFAULT <value>` задает значение по-умолчанию
+
+Рассмотрим DDL скрипт таблицы `Agent` - тут у нас появляются внешние ключи:
+
+```sql
+CREATE TABLE `Agent` (
+  `ID` int NOT NULL AUTO_INCREMENT,
+  `Title` varchar(150) NOT NULL,
+  `AgentTypeID` int NOT NULL,
+  `Address` varchar(300) DEFAULT NULL,
+  `INN` varchar(12) NOT NULL,
+  `KPP` varchar(9) DEFAULT NULL,
+  `DirectorName` varchar(100) DEFAULT NULL,
+  `Phone` varchar(20) NOT NULL,
+  `Email` varchar(255) DEFAULT NULL,
+  `Logo` varchar(100) DEFAULT NULL,
+  `Priority` int NOT NULL,
+  PRIMARY KEY (`ID`),
+  CONSTRAINT `FK_Agent_AgentType` FOREIGN KEY (`AgentTypeID`) REFERENCES `AgentType` (`ID`)
+);
+```
+
+- поле для внешнего ключа (`AgentTypeID`) создается как обычно
+- и записывается ограничение (`CONSTRAINT`), в котором мы описываем, что поле является внешним ключем (``FOREIGN KEY (`AgentTypeID`)``) и ссылается на таблицу и поле в ней (``REFERENCES `AgentType` (`ID`)``)
+
+### Изменение полей существующей таблицы
+
+#### Добавление поля
+
+```sql
+ALTER TABLE table_name
+ADD COLUMN new_column_name data_type [constraints];
+```
+
+#### Переименовывание поля
+
+* универсальный вариант, меняющий и название поля и его тип
+
+    ```sql
+    ALTER TABLE имя_таблицы
+    CHANGE старое_имя новое_имя ТИП_ДАННЫХ;
+    ```
+
+* простой вариант, меняющий только название поля
+
+    ```sql
+    ALTER TABLE имя_таблицы
+    RENAME COLUMN старое_имя TO новое_имя;
+    ```
+
+#### Удаление поля
+
+```sql
+ALTER TABLE table_name
+DROP COLUMN column_name;
+```
+
+#### Изменение типа данных или ограничений поля
+
+```sql
+ALTER TABLE table_name
+MODIFY COLUMN column_name new_data_type [new_constraints];
+```
+
+#### Добавление внешнего ключа
+
+```sql
+ALTER TABLE table_name
+ADD CONSTRAINT fk_name
+FOREIGN KEY (column_name)
+REFERENCES parent_table (parent_column_name);
+```
+
+#### Удаление поля
+
+```sql
+ALTER TABLE table_name DROP COLUMN column_name;
+```
+
+### Удаление таблицы
+
+>Тут надо быть аккуратным, если на эту таблицу есть ссылки из других таблиц, то запрос выдаст ошибку
+
+```sql
+DROP TABLE table_name;
+```
+
+## Задание
+
+Добавить в тестовый проект (Продукты и материалы) систему миграции и какой-нибудь скрипт, меняющий __структуру__ базы данных

+ 6 - 3
readme.md

@@ -118,7 +118,7 @@ http://sergeyteplyakov.blogspot.com/2014/01/microsoft-fakes-state-verification.h
 
   - [Разработка API](#разработка-своего-api)
 
-  - [Введение в WEB-разработку](#введение-в-web-разработку)
+  - [Введение в WEB-разработку](#практика-1-введение-в-web-разработку)
 
   <!-- - [Документирование ИС](#документирование-ис) -->
 
@@ -309,19 +309,22 @@ https://office-menu.ru/uroki-sql Уроки SQL
 1. [Создание Wireframe для своей предметной области](./articles/lab_wireframe.md)
 1. [Разработка десктопного приложения для администрирования базы данных своей предметной области](./articles/lab_desktop.md)
 
-### Разработка своего API.
+### Разработка API.
 
 1. [API. REST API. Создание сервера ASP.NET Core. Swagger.](./articles/api_asp_net_core.md)
 
 1. [Авторизация и аутентификация. Методы авторизации. Basic-авторизация.](./articles/api_auth.md)
 
+1. [Системы миграции данных.](./articles/migrations.md)
+
 1. [HTTP запросы в C#.](./articles/cs_http.md)
 
+### Разработка веб приложений (ASP.NET)
+
 ### Разработка мобильных приложений (MAUI)
 
 1. [Что такое MAUI, создание мобильного приложения для Android используя VSC](./articles/cs_maui.md)
 
-### Разработка веб- приложений (ASP.NET)
 
 <!-- **Лабораторные работы** -->