Что такое миграции (Migrations) в Entity Framework Core?

Ответ

Миграции в EF Core — это система контроля версий для схемы базы данных. Она позволяет синхронизировать модель данных в коде (ваши классы-сущности DbContext и DbSet) со структурой реальной реляционной базы данных, применяя изменения инкрементально и сохраняя существующие данные.

Основной рабочий процесс:

  1. Изменение модели: Вы редактируете классы сущностей или DbContext.
  2. Создание миграции: Выполняете команду, которая сравнивает текущую модель с предыдущим состоянием и генерирует код для применения изменений к БД.
    dotnet ef migrations add AddDescriptionToProduct
  3. Проверка и применение: Сгенерированный код миграции (файлы в папке Migrations/) можно отредактировать, а затем применить к базе данных.
    dotnet ef database update

Структура сгенерированной миграции:

public partial class AddDescriptionToProduct : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        // Код для применения изменений
        migrationBuilder.AddColumn<string>(
            name: "Description",
            table: "Products",
            type: "nvarchar(max)",
            nullable: true);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        // Код для отката изменений (противоположность Up)
        migrationBuilder.DropColumn(
            name: "Description",
            table: "Products");
    }
}

Практические рекомендации:

  • Именование: Давайте миграциям осмысленные имена, отражающие суть изменения (например, AddEmailToUser, CreateOrderTable).
  • Ручная правка: Сгенерированный код Up/Down можно и иногда нужно редактировать вручную для сложных операций (например, переноса данных, добавления индексов).
  • Продакшен: В рабочих средах миграции часто применяются как часть пайплайна CI/CD, а не вручную. Для этого используется команда ef через CLI или метод context.Database.Migrate() при старте приложения.
  • SQL-скрипты: Можно сгенерировать SQL-скрипт для ручного применения DBA:
    dotnet ef migrations script --output migration.sql
  • Подход Code-First: Миграции — это краеугольный камень подхода Code-First, когда структура БД определяется и управляется из кода приложения.

Ответ 18+ 🔞

Давай разберём эту тему про миграции в EF Core, а то некоторые думают, что это какая-то магия, а на деле всё просто, как три копейки.

Представь, ты пишешь код, у тебя там класс Product с парой полей. Потом начальству приспичило, и надо добавить поле Description. Ты в коде его добавил, а база данных-то про это не знает, она как была с двумя колонками, так и осталась. Вот тут-то миграции и выручают — это такой способ сказать базе: «Слышь, дружище, нам тут новое поле подвезли, подвинься».

Как это работает, по шагам:

  1. Накосячил в коде. Ну, то есть, изменил модель. Добавил свойство, новую сущность, связь какую-нибудь.

  2. Создаёшь миграцию. Ты пишешь в консоли волшебную команду, типа:

    dotnet ef migrations add ДобавилОписаниеДляТовара

    EF Core берёт, смотрит, чем твоя текущая модель отличается от того, что было в прошлой миграции, и генерирует два метода: Up (чтобы накатить изменения) и Down (чтобы откатить, если всё пошло по пизде).

  3. Смотришь, что нагенерировалось. Открываешь файл в папке Migrations и видишь что-то вроде:

    public partial class ДобавилОписаниеДляТовара : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            // Вот что сделает базу новой
            migrationBuilder.AddColumn<string>(
                name: "Description",
                table: "Products",
                nullable: true); // Может быть null, потому что в старой базе его не было, а данные-то уже есть
        }
    
        protected override void Down(MigrationBuilder migrationBuilder)
        {
            // А вот это откатит всё назад, если чё
            migrationBuilder.DropColumn(
                name: "Description",
                table: "Products");
        }
    }

    Иногда сгенерированный код — полная хуйня, особенно если переименовывал что-то. Его можно и нужно править руками! Главное, чтобы Up и Down были зеркальными.

  4. Накатываешь на базу. Ещё одна команда:

    dotnet ef database update

    И всё, база обновилась. Данные старые на месте, новое поле добавилось. Красота.

Жизненные советы, чтобы не обжечься:

  • Имя миграции — это не просто текст. Пиши так, чтобы через полгода, глядя на список, было понятно, что там творилось. AddDescriptionToProduct — отлично. Migration001 — пиздец как нет.
  • Продакшен — это не твой комп. На рабочем сервере ты не будешь вручную команды вбивать. Обычно это делают через скрипты в CI/CD пайплайне или вызывают DbContext.Database.Migrate() при старте приложения. Но будь осторожен, это оружие массового поражения, если накатывать бездумно.
  • Нужен чистый SQL для DBA? Без проблем:
    dotnet ef migrations script --output migration.sql

    Получишь скрипт, который можно отдать администратору, а он посмотрит на тебя, как на идиота, но применит.

  • Суть подхода (Code-First): Твои классы в C# — это единственный источник правды. База данных — это просто отражение этих классов, которое можно и нужно пересоздать или обновить в любой момент. Миграции — это и есть инструмент для этого обновления, а не какая-то отдельная ебучка с SQL-скриптами вручную.

Короче, миграции — это твой лучший друг, если ты не хочешь вручную сравнивать модели и писать тонны ALTER TABLE. Используй, но с головой. И всегда проверяй, что там сгенерировалось, особенно перед тем, как заливать в прод.