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
- Model Snapshot: EF Core takes a snapshot of your model after you create a migration. This snapshot is used to compare against your current model to determine what changes need to be made.
- Migration Files: Each migration is generated as a C# file containing two methods:
Up()
andDown()
.Up()
: Contains the code to apply the changes of the migration to the database.Down()
: Contains the code to reverse the changes of the migration. This is used when you need to roll back a migration.
- Migrations History Table: EF Core creates a table in your database (by default named
__EFMigrationsHistory
) to keep track of which migrations have been applied.
Getting Started with Migrations
To use Migrations, you'll typically need to install the following NuGet packages:
Microsoft.EntityFrameworkCore.Tools
: Provides the command-line tools for managing migrations.
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.
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.
- Make changes to your model classes.
- Run
dotnet ef migrations add <DescriptiveName>
. - Review the generated migration file.
- 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.
--from-sql
or --idempotent
options with the migrations script
command.
Advanced Scenarios
- Custom Migrations: You can write custom SQL directly within your migration files using
migrationBuilder.Sql()
. - Seeding Data: Migrations can be used to seed initial data into your database.
- Multiple Databases: EF Core Migrations can be configured to work with multiple databases within the same application.
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.