Summary: in this tutorial, you’ll learn about how to use the EF Core migrations to synchronize the changes of models to the database.
EF Core Migration flow
In practice, the database schema will evolve with new requirements. For example, you may want to create a new table or modify an existing table by adding or removing columns.
Typically, you have to do all of these tasks manually by executing SQL commands in the database.
Fortunately, the EF Core migration feature makes this flow easier by allowing you to make the changes in the models, generate the script based on the changes, and apply them to the database.
Here’s the migration flow:
- First, create or modify entity models in C#.
- Second, run a migration command to generate a migration file or script based on the model changes.
- Third, apply the migration to the database to update the database schema.
Note that before running the migration commands, you need to install the Microsoft.EntityFrameworkCore.Tools
package from NuGet Package.
Running EF Core migration commands
Once having the packaged install, you’re ready to explore the migration commands.
Help command
To view all available commands, you execute the following help command in the Package Manager Console (PMC):
get-help entityframework
Code language: JavaScript (javascript)
It’ll show the following output (excerpt):
The Get-Help
command shows all the commands available in Entity Framework Core. To get help on a specific command, you pass that command to the Get-Help
command like this:
Get-Help command
For example, you can use the Get-Help
command to display the help for the Add-Migration
command:
get-help add-migration
Code language: JavaScript (javascript)
Output:
Adding the first migration
To create a migration, you use the Add-Migration
command. The minimal requirement of the Add-Migration
command is a migration name.
For example, the following creates a new migration called Initial
:
Add-Migration Initial
Code language: plaintext (plaintext)
The command will return the following output, indicating that the migration has been created successfully:
Build started...
Build succeeded.
To undo this action, use Remove-Migration.
Code language: plaintext (plaintext)
If you view the HR project, you’ll see the Migrations
directory created. The Migrations
directory has two files:
20230608062832_Initial.cs
– it starts with a timestamp and is followed by the migration name. The migration file defines a partial class that extends the Migration
class. Typically, the class name is the same as the migration name, which is Initial
in this example.
The Initial
class has two methods Up()
and Down()
.
- The
Up()
method usesMigrationBuilder
to create and manage database objects such as creating tables and adding/ removing columns based on the model. - The
Down()
method reverses theUp()
method. If theUp()
method creates a table, then theDown()
method will drop it.
EF Core uses the Up()
method to apply a migration and the Down()
method to reverse it.
HRContextModelSnapshot.cs
– EF Core will use the snapshot file during the subsequent migrations. More specifically, EF Core will use the snapshot file to compare the current state of the models with the previous snapshot and generate the migration scripts to update the database schema accordingly.
Note that the files in the Migrations
directory can be a part of the source control like git. It means that you can manage their versions that are synchronized with the code base.
EF Core uses the following mapping conventions for naming tables and columns:
- DBSet names are the table names.
- Class property names are column names.
Applying a migration
To apply a migration to the database, you use the Update-Database
command. It’ll do the following:
- Reads migration file.
- Generates SQL in memory.
- Creates the database if it doesn’t exist.
- Runs SQL on the database.
To generate SQL script file only, you use the Script-Migration
command:
- Reads migration file.
- Generates SQL in memory.
- Displays SQL in the editor.
- Uses parameters to target file names etc.
It’s recommended to use the Update-Database
command in the development database while using Script-Migration
in the production database.
We’ll run the Script-Migration
command first to preview the generated SQL script:
Script-Migration
It’ll display the following SQL code in the Visual Studio Editor:
IF OBJECT_ID(N'[__EFMigrationsHistory]') IS NULL
BEGIN
CREATE TABLE [__EFMigrationsHistory] (
[MigrationId] nvarchar(150) NOT NULL,
[ProductVersion] nvarchar(32) NOT NULL,
CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
);
END;
GO
BEGIN TRANSACTION;
GO
CREATE TABLE [Departments] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Departments] PRIMARY KEY ([Id])
);
GO
CREATE TABLE [Employees] (
[Id] int NOT NULL IDENTITY,
[FirstName] nvarchar(max) NOT NULL,
[LastName] nvarchar(max) NOT NULL,
[JoinedDate] datetime2 NOT NULL,
[DepartmentId] int NULL,
CONSTRAINT [PK_Employees] PRIMARY KEY ([Id]),
CONSTRAINT [FK_Employees_Departments_DepartmentId] FOREIGN KEY ([DepartmentId]) REFERENCES [Departments] ([Id])
);
GO
CREATE INDEX [IX_Employees_DepartmentId] ON [Employees] ([DepartmentId]);
GO
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20230608062832_Initial', N'7.0.5');
GO
COMMIT;
GO
Code language: SQL (Structured Query Language) (sql)
Note that before applying the migration to the database, we need to delete the existing HR database created in the previous tutorial.
Now, you can apply the migrations to create a new database and table by executing the following command in the PMC:
Update-Database
Code language: plaintext (plaintext)
EF Core will create the HR database and the following tables:
__EFMigrationsHistory
– stores migration that has been applied to the database so that the database schema stays in sync with the models.Departments
– maps to theDepartment
model class.Employees
– maps to theEmployee
model class.
The following shows the contents of the __EFMigrationHistory
table:
Creating a new migration
Suppose you need a property called DateOfBirth
to the Employee
class and synchronize it to the database. To do that, you follow these steps:
First, define the DateOfBirth
property in the Employee
class:
namespace HR;
public class Employee
{
public int Id { get; set; }
public required string FirstName { get; set; }
public required string LastName { get; set; }
public required DateTime DateOfBirth { get;set; }
public required DateTime JoinedDate { get; set; }
public Department? Department { get; set; }
}
Code language: C# (cs)
Second, create a new migration by using the Add-Migration
command:
Add-Migration EmployeeDOB
Code language: plaintext (plaintext)
Output:
Build started...
Build succeeded.
To undo this action, use Remove-Migration.
Code language: plaintext (plaintext)
The command creates a new migration file in the Migrations
directory:
20230608063613_EmployeeDOB.cs
Code language: plaintext (plaintext)
Note that your timestamp will be different. Here’s the content of the file:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace HR.Migrations
{
/// <inheritdoc />
public partial class EmployeeDOB : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "DateOfBirth",
table: "Employees",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DateOfBirth",
table: "Employees");
}
}
}
Code language: C# (cs)
The Up()
method adds a new column to the Employees
table while the Down()
method drops the column from it.
Third, run the Update-Database
command to apply the migration to the database:
Update-Database
Code language: plaintext (plaintext)
It’ll synchronize the changes to the database. If you view the Employees
table, you’ll see the new DateOfBirth
column:
Summary
- Use EF Core migration flow to apply changes from models to the database.
- Use the
Add-Migration
command to create a new migration. - Use the
Update-Database
command to apply a migration to the database. - Use the
Script-Migration
command to generate an SQL script file.