C# tutorials > Frameworks and Libraries > Entity Framework Core (EF Core) > Migrations (creating, applying, reverting)

Migrations (creating, applying, reverting)

This tutorial explains how to use Entity Framework Core Migrations to manage your database schema. We will cover creating, applying, and reverting migrations, ensuring your database stays in sync with your application's data model.

Introduction to EF Core Migrations

EF Core Migrations provide a way to evolve your database schema alongside your Entity Framework Core model. Migrations track changes you make to your model and allow you to apply those changes to your database in a controlled and predictable way. This is essential for version control and maintaining consistency between your application's code and the database schema. Without migrations, you would have to manually alter the database schema every time you made changes to your data model, a process that is both tedious and error-prone.

Prerequisites

Before you begin, ensure you have the following:

  • .NET SDK installed.
  • A C# project using Entity Framework Core.
  • The Microsoft.EntityFrameworkCore.Tools package installed as a NuGet package. This package provides the CLI tools necessary for working with migrations. Install it via the Package Manager Console or the .NET CLI. For example: dotnet add package Microsoft.EntityFrameworkCore.Tools

Creating a Migration

To create a migration, use the dotnet ef migrations add command. Replace InitialCreate with a descriptive name for your migration. This name will help you identify the purpose of the migration later. For example, if you added a new table called `Products`, you might name your migration `AddProductsTable`.

This command scaffolds the necessary code to update the database schema to match your current model. It generates two files: a .cs file containing the migration code and a .Designer.cs file with metadata about the migration.

dotnet ef migrations add InitialCreate

Understanding the Migration Code

The generated migration class contains two methods:

  • Up(): This method contains the code to apply the changes to the database (e.g., creating tables, adding columns).
  • Down(): This method contains the code to revert the changes made by the Up() method (e.g., dropping tables, removing columns). This is used when you want to roll back a migration.

The MigrationBuilder class provides methods for performing various database schema operations. Examine the code generated to understand how the schema is being modified.

using Microsoft.EntityFrameworkCore.Migrations;

namespace YourProject.Migrations
{
    public partial class InitialCreate : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Blogs",
                columns: table => new
                {
                    BlogId = table.Column<int>(type: "int", nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    Url = table.Column<string>(type: "nvarchar(max)", nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Blogs", x => x.BlogId);
                });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Blogs");
        }
    }
}

Applying Migrations

To apply the migrations to your database, use the dotnet ef database update command. This command reads the migration history and applies any pending migrations in order.

Optionally, you can specify a target migration to update to. For example, dotnet ef database update MigrationName will update the database to the 'MigrationName' migration.

This command updates the database schema to match the latest version of your model.

dotnet ef database update

Reverting Migrations

To revert a migration (or a series of migrations), use the dotnet ef database update command and specify the target migration to revert to. For example, if you want to revert the last migration, specify the name of the migration *before* the last one.

If you want to revert all migrations, you can update to the initial migration (typically named '0'). If there are no migrations defined, updating to the initial migration is the same as dropping the database.

Reverting migrations rolls back the changes made to the database schema, bringing it back to a previous state.

dotnet ef database update PreviousMigrationName

Concepts Behind the Snippet

The core concept is managing database schema changes using code. Instead of manually altering tables and columns, EF Core Migrations automate this process, ensuring consistency and allowing for version control of your database structure. This is based on the principle of Infrastructure as Code.

Real-Life Use Case Section

Imagine you're building an e-commerce platform. Initially, you have a simple `Products` table with `Name`, `Description`, and `Price` columns. Later, you decide to add a `Category` column. Using EF Core Migrations, you can create a migration that adds the `Category` column to the `Products` table, ensuring that all existing and future databases have the correct schema. If you later need to revert that change (perhaps due to an error), you can revert the migration, removing the `Category` column.

Best Practices

Here are some best practices for using EF Core Migrations:

  • Name your migrations descriptively. This will make it easier to understand the purpose of each migration.
  • Test your migrations thoroughly. Apply migrations to a development or staging database before applying them to production.
  • Use idempotent migrations. Ensure that running a migration multiple times has the same effect as running it once.
  • Consider using database transactions. Wrap your migrations in transactions to ensure that they are either fully applied or fully rolled back.

Interview Tip

Be prepared to discuss the benefits of using EF Core Migrations, such as version control, automation, and consistency. Also, be ready to explain the difference between the Up() and Down() methods and how they are used.

When to Use Them

Use EF Core Migrations whenever you need to make changes to your database schema. This includes adding tables, columns, indexes, and other database objects. Migrations are particularly useful in team environments where multiple developers are working on the same database.

Memory Footprint

The memory footprint of migrations themselves is generally small. However, keep in mind that applying migrations can involve significant database operations, such as creating indexes or altering large tables, which can consume significant memory resources on the database server.

Alternatives

Alternatives to EF Core Migrations include:

  • Manually writing SQL scripts. This approach gives you more control but is more error-prone and less maintainable.
  • Database compare tools. These tools compare the schema of two databases and generate SQL scripts to synchronize them.
  • Using a database-first approach. This involves generating your EF Core model from an existing database schema, instead of defining the model in code.

Pros

Advantages of using EF Core Migrations:

  • Version control of database schema.
  • Automation of schema changes.
  • Consistency between application code and database schema.
  • Easy rollback of changes.

Cons

Disadvantages of using EF Core Migrations:

  • Can be complex for large and complex schemas.
  • May require careful planning to avoid data loss during migrations.
  • Requires careful testing to ensure that migrations work correctly.

FAQ

  • How do I resolve conflicts when merging migration branches?

    Conflicts in migration files typically occur when multiple developers have made schema changes that affect the same database objects. You'll need to manually resolve the conflicts in the Up() and Down() methods, ensuring that the resulting code is correct and consistent. Test the merged migration thoroughly before applying it to a database.

  • How can I customize the database schema generated by migrations?

    You can customize the schema by using data annotations or the fluent API in your EF Core model. For example, you can specify the table name, column types, and indexes. These configurations will be reflected in the generated migration code.

  • What happens if a migration fails?

    If a migration fails, the database will be left in an inconsistent state. Ideally, migrations should be wrapped in transactions, so a failure automatically rolls back all changes. If that is not the case, you'll need to manually revert the migration to restore the database to a consistent state. Carefully examine the error messages and logs to determine the cause of the failure.