Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое миграция в контексте C# Backend (Entity Framework Core)
Миграция (Migration) в контексте разработки на C# с использованием Entity Framework Core (EF Core) — это система контроля версий для схемы базы данных. Она позволяет синхронизировать модель данных в коде (классы сущностей, DbContext) с реальной структурой реляционной базы данных, применяя изменения инкрементально, безопасно и воспроизводимо.
Основная цель — автоматизировать процесс изменения структуры БД (создание/удаление таблиц, столбцов, индексов, ключей) при развитии приложения, избегая ручного написания SQL-скриптов и обеспечивая согласованность на всех этапах (разработка, тестирование, продакшен).
Из чего состоит миграция (структура и компоненты)
1. Класс миграции (Файл с расширением .cs)
Это основной C# класс, генерируемый EF Core, который содержит логику применения изменений к БД и их отката.
public partial class AddProductTable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
// Операции для применения миграции (вперёд)
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(maxLength: 100, nullable: false),
Price = table.Column<decimal>(nullable: false),
CreatedDate = table.Column<DateTime>(nullable: false, defaultValueSql: "GETUTCDATE()")
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Products_Name",
table: "Products",
column: "Name",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// Операции для отката миграции (назад) - обратные действиям из Up
migrationBuilder.DropTable(name: "Products");
}
}
- Метод
Up(MigrationBuilder migrationBuilder): Содержит операции для применения миграции (переход на новую версию схемы). Здесь описывается создание таблиц, добавление столбцов и т.д. - Метод
Down(MigrationBuilder migrationBuilder): Содержит обратные операции для отката миграции (возврат к предыдущей версии схемы). Должен быть строго противоположнымUp.
2. Файл ресурсов (.resx)
Сопутствующий файл, который хранит метаданные и SQL-скрипты в бинарном виде. Он используется EF Core для внутренней работы, чтобы гарантировать корректное применение миграций, особенно при использовании разных поставщиков баз данных (SQL Server, PostgreSQL, SQLite).
3. Моментальный снимок модели (Model Snapshot) - [YourDbContext]ModelSnapshot.cs
Это файл, который хранит полное текущее состояние модели данных (сущности, связи, конфигурации) на момент последней созданной миграции. Он служит эталоном для сравнения при генерации следующей миграции. EF Core сравнивает текущее состояние модели (из DbContext и конфигураций) с этим снимком, чтобы определить, какие изменения нужно инкапсулировать в новую миграцию.
[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
// Здесь полностью описана актуальная модель на момент миграции
modelBuilder.Entity("Product", b =>
{
b.Property<int>("Id").ValueGeneratedOnAdd();
b.Property<string>("Name").HasMaxLength(100);
// ... и т.д.
});
}
}
4. Таблица __EFMigrationsHistory в целевой базе данных
Это служебная таблица, которая автоматически создаётся EF Core в целевой БД при первом применении миграции. Она является журналом всех применённых миграций.
- Структура:
* `MigrationId` (string) — уникальный идентификатор миграции (обычно включает временную метку и имя, например, `20240515120000_AddProductTable`).
* `ProductVersion` (string) — версия EF Core, использованная для создания миграции.
- Назначение: При выполнении команды обновления БД (
Update-Database) EF Core сверяет список миграций из кода с записями в этой таблице и применяет только те, которых ещё нет в истории. Это предотвращает повторное выполнение одних и тех же изменений.
Жизненный цикл и ключевые команды
- Создание миграции:
dotnet ef migrations add AddProductTable
* Сравнивает текущую модель с `ModelSnapshot`.
* Генерирует новые файлы: `[timestamp]_AddProductTable.cs`, `.resx`.
* Обновляет `ModelSnapshot.cs`.
- Применение миграции к БД:
* **Через код (в рантайме)**: Использование `context.Database.Migrate()` при старте приложения (осторожно в продакшене!).
* **Через CLI**: `dotnet ef database update`
* **Генерация SQL-скрипта**: `dotnet ef migrations script` — для проверки и ручного применения в продакшене (рекомендуемый подход).
- Удаление/откат:
* `dotnet ef migrations remove` — удаляет последнюю НЕприменённую миграцию из кода.
* `dotnet ef database update PreviousMigrationName` — откатывает БД к указанной версии, выполняя методы `Down`.
Важные принципы и best practices
- Идемпотентность: Современные миграции EF Core стремятся быть идемпотентными (их можно применить несколько раз без изменения результата), особенно при генерации SQL-скриптов.
- Детерминированность: Миграции должны быть воспроизводимы и давать одинаковый результат на разных средах.
- Строгий порядок: Миграции применяются строго в хронологическом порядке, определённом по timestamp в имени файла.
- Неизменяемость: Применённую и закоммиченную в репозиторий миграцию нельзя изменять. Все новые изменения требуют создания новой миграции. Изменение существующей может привести к рассогласованию состояния между средами и поломке процесса обновления.
- Безопасность данных: Миграции, изменяющие или удаляющие данные (например,
DROP COLUMN), требуют особой осторожности. Часто такие изменения разбивают на две миграции: первая добавляет новый столбец и переносит/конвертирует данные, вторая — удаляет старый.
Таким образом, миграция в EF Core — это не просто SQL-скрипт, а связный набор артефактов (код, снимок модели, журнал в БД), образующий надёжную систему управления эволюцией схемы базы данных, которая интегрирована в процесс разработки на C# и .NET.