Entity Framework Core Migrations

Entity Framework Core (EF Core) Migrations is a powerful feature that allows you to manage incremental changes to your database schema as your application evolves. It helps keep your code models and your database schema in sync without requiring you to manually write or deploy schema update scripts.

What are Migrations?

Migrations represent a series of actions that can be applied to transform your database schema from one version to the next. Each migration typically corresponds to a change in your EF Core model, such as adding a new entity, adding a property to an entity, or changing the data type of a property.

Core Concepts

Getting Started with Migrations

To use Migrations, you'll typically need to install the following NuGet packages:

You can install these using the .NET CLI:

dotnet add package Microsoft.EntityFrameworkCore.Tools

Enabling Migrations

Before you can create migrations, you need to tell EF Core that you want to use them. This is typically done in your DbContext class by calling the Enable-Migrations() method (in older versions) or by using the .NET CLI commands.

Creating Your First Migration

Once you have your EF Core model defined and your DbContext configured, you can create your first migration using the .NET CLI. Navigate to your project directory in the terminal and run:

dotnet ef migrations add InitialCreate

This command will generate a new migration file in a Migrations folder within your project. The InitialCreate is the name you've given to this migration. It's good practice to use descriptive names.

Note: If you get an error like "Could not find an implementation of EF Core tools", ensure you have added the Microsoft.EntityFrameworkCore.Tools NuGet package to your project.

Applying Migrations

After creating a migration, you need to apply it to your database. You can do this using the .NET CLI:

dotnet ef database update

This command will look at the Migrations folder, check the __EFMigrationsHistory table, and apply any pending migrations. If this is the first time you're running it, it will create all the tables and columns based on your EF Core model.

Viewing Generated Code

Open the generated migration file (e.g., Migrations/<timestamp>_InitialCreate.cs) to see the code EF Core generated. You can inspect and even modify this code if you need more control.


// Generated code example
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

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);
                });

            migrationBuilder.CreateTable(
                name: "Posts",
                columns: table => new
                {
                    PostId = table.Column<int>(type: "int", nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
                    Content = table.Column<string>(type: "nvarchar(max)", nullable: true),
                    BlogId = table.Column<int>(type: "int", nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Posts", x => x.PostId);
                    table.ForeignKey(
                        name: "FK_Posts_Blogs_BlogId",
                        column: x => x.BlogId,
                        principalTable: "Blogs",
                        principalColumn: "BlogId");
                });

            migrationBuilder.CreateIndex(
                name: "IX_Posts_BlogId",
                table: "Posts",
                column: "BlogId");
        }

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

            migrationBuilder.DropTable(
                name: "Blogs");
        }
    }
}
                

Managing Future Changes

As you modify your EF Core model (e.g., add a new property to an entity), you'll need to create new migrations and apply them.

  1. Make changes to your model classes.
  2. Run dotnet ef migrations add <DescriptiveName>.
  3. Review the generated migration file.
  4. Run dotnet ef database update to apply the changes to your database.

Reverting Migrations (Rolling Back)

If you need to undo a migration, you can use the --to-migration option with database update. For example, to roll back to the previous migration:

dotnet ef database update <PreviousMigrationName>

Or, to revert the last applied migration:

dotnet ef database update previous

EF Core will execute the Down() method of the migration you're rolling back from.

Generating SQL Scripts

Sometimes, you might want to generate SQL scripts for your migrations instead of applying them directly to a database. This is useful for deployment pipelines or when you need manual review of the SQL.

dotnet ef migrations script --output migrations.sql

This command generates a SQL script that contains the changes needed to bring your database up-to-date.

Tip: For more complex scenarios, consider using the --from-sql or --idempotent options with the migrations script command.

Advanced Scenarios

Seeding Data with Migrations

To seed data, you can add code to your migration's Up() method. For example:


// In your migration's Up() method
migrationBuilder.InsertData(
    table: "Roles",
    columns: new[] { "Id", "Name" },
    values: new object[,]
    {
        { 1, "Admin" },
        { 2, "User" }
    });
                

For more complex or frequent data seeding, consider using the HasData method when configuring your entities in OnModelCreating.

Conclusion

EF Core Migrations significantly simplify database schema management. By understanding its core concepts and commands, you can effectively evolve your application's database schema alongside your code, ensuring consistency and reducing manual effort.

Continue exploring the Entity Framework Core documentation to delve deeper into specific features and configurations.