Ответ
Да, активно использовал миграции EF Core для управления эволюцией схемы базы данных в процессе разработки и развертывания.
Базовый рабочий процесс:
# 1. Создание миграции после изменения модели
dotnet ef migrations add AddCustomerEmailColumn
# 2. Обновление базы данных до последней миграции
dotnet ef database update
# 3. Генерация SQL-скрипта для применения в продакшене
dotnet ef migrations script --idempotent --output migration.sql
Ключевые практики и нюансы:
-
Структура миграции: Каждая миграция содержит два основных метода в файле
<MigrationName>.Designer.cs:Up(): Применяет изменения.Down(): Откатывает изменения.
-
Кастомизация миграций: Автоматически сгенерированный код часто требует ручной доработки.
// В методе Up() сгенерированной миграции protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AddColumn<string>( name: "Email", table: "Customers", type: "nvarchar(200)", maxLength: 200, nullable: false, defaultValue: ""); // Добавляем значение по умолчанию для существующих строк // Можно добавлять индексы, внешние ключи, выполнять сырые SQL migrationBuilder.Sql("UPDATE Customers SET Email = 'temp@example.com' WHERE Email IS NULL"); } -
Безопасное развертывание в продакшене:
- Никогда не запускать
dotnet ef database updateнапрямую на продакшен-сервере. - Использовать SQL-скрипты: Генерировать скрипт (
dotnet ef migrations script) и применять его через инструменты CI/CD (например, Azure DevOps, GitHub Actions) или DBA. - Идемпотентные скрипты: Флаг
--idempotentгенерирует скрипт, который можно безопасно запускать многократно.
- Никогда не запускать
-
Работа в команде:
- Файл миграций (.cs) должен быть закоммичен в систему контроля версий.
- При конфликтах (два разработчика создали миграции с разными именами) может потребоваться сброс (
dotnet ef migrations remove) и пересоздание миграции на основе актуального состояния.
-
Откат (Rollback):
# Откат на одну миграцию назад dotnet ef database update PreviousMigrationName # Полный откат всех миграций (осторожно с данными!) dotnet ef database update 0 -
Пустые миграции: Иногда создаются для выполнения специфического SQL (например, обновления справочных данных, создания сложных индексов).
dotnet ef migrations add UpdatePostalCodes --empty
Ответ 18+ 🔞
А, миграции в EF Core, да? Ну, это ж классика, как водка с пивом — вроде и работает, но потом голова болит, если не умеешь правильно.
Смотри, я ими пользуюсь постоянно, когда базу надо менять на ходу. Процесс обычно такой, простой, как три копейки:
# 1. Накосячил в моделях — создаёшь миграцию
dotnet ef migrations add AddCustomerEmailColumn
# 2. Локально себе в базу это дело загоняешь
dotnet ef database update
# 3. А для прода — скрипт готовишь, чтобы админы не орали
dotnet ef migrations script --idempotent --output migration.sql
А теперь по пунктам, где собака зарыта и где можно на грабли наступить:
-
Что внутри. Каждая миграция — это два метода, верх и низ.
Up()— чтобы вперёд ехать, применить изменения.Down()— чтобы назад, если всё пошло по пизде и надо откатиться. Всё это в файле с дизайнером лежит. -
Ручная работа. Автомат — он тупой, как пробка. Нагенерирует код, а потом смотришь — а он тебе колонку
NOT NULLбез дефолта суёт в таблицу, где уже данные есть. Ёб твою мать, ну кто так делает? Приходится руками допиливать.protected override void Up(MigrationBuilder migrationBuilder) { // Автомат так сделал бы, и скрипт бы упал на продакшене // migrationBuilder.AddColumn<string>(name: "Email", table: "Customers", nullable: false); // А умный человек сделает вот так: migrationBuilder.AddColumn<string>( name: "Email", table: "Customers", type: "nvarchar(200)", maxLength: 200, nullable: false, defaultValue: ""); // Вот этот дефолт — спасение от криков админов // И ещё кастомный SQL на всякий пожарный migrationBuilder.Sql("UPDATE Customers SET Email = 'temp@example.com' WHERE Email IS NULL OR Email = ''"); } -
Продакшен — это святое. Запомни раз и навсегда, как «Отче наш»: НИКОГДА, БЛЯДЬ, НЕ ГОНЯЙ
dotnet ef database updateНА БОЕВОЙ БАЗЕ. Тебя просто убьют. Всё через скрипты. Флаг--idempotent— твой лучший друг, он делает скрипт, который можно хоть сто раз запустить, и хуйня не случится. Отдаёшь это дело в CI/CD или суровому дяде DBA, и спишь спокойно. -
Командная разработка. Тут весело. Все файлы миграций (.cs) — в гит, это закон. А потом случается: ты сделал миграцию
AddEmail, а твой коллега в параллельной ветке тоже сделал миграциюAddPhone. Мержите вы это, а в базе уже есть одна из них. Получается пиздец и конфликт. Часто проще старую миграцию нахуй удалить (dotnet ef migrations remove) и новую, общую, создать на актуальных моделях. -
Откатиться, если обосрался. Бывает же.
# Откатиться на одну ступеньку назад dotnet ef database update PreviousMigrationName # Откатиться в полный ноль (осторожно, данные могут пострадать!) dotnet ef database update 0 -
Пустые миграции — мощный инструмент. Иногда надо не структуру менять, а данные поправить, или сложный индекс накатить, который EF Core сам не додумается создать. Для этого и нужна пустая миграция.
dotnet ef migrations add UpdatePostalCodes --emptyОткроешь файл, и там в
Up()пишешь свой кастомный SQL, какой душе угодно. Красота.
В общем, инструмент годный, но с мозгом им пользоваться надо, а не тыкать кнопки наугад. Иначе будет тебе не миграция, а натуральная эмиграция с проекта под крики «кто это сделал?!».