Search⌘ K
AI Features

Introduction to Migrations

Explore how Entity Framework Core migrations enable you to update and maintain your database schema using code-first workflows. Understand creating, applying, and reviewing migrations, including the role of migration files and the EFMigrationsHistory table to track changes effectively.

Overview

In real-world projects, data models get updated as features get implemented. New entities or properties get added and removed. Migrations provide a means to update the database schema and keep it in sync with the model. This approach is known as the Code First workflow because the EF Core model is the source of truth.

Note: The commands in this lesson generate code and files. Through the terminal, we can navigate to these files by using relevant Linux commands such as ls to view a list of files and directories, cd to change directories, and cat to view file contents. A SPA widget showing the updated project with the generated files is also available. Also, note that EF Core uses a timestamp within the generated file names. We represent these names with xxx.

Creating and applying migrations

A migration is a point-in-time snapshot of the data model. EF Core generates migration source files based on the differences between shots.

Note: It’s good practice to keep the changes between migrations small. This practice helps to keep track of the changes during development, prevents mistakes, and makes it easier to reverse those changes.

To demonstrate migrations, we’ll be working with the C# project below:

{
    "version": "0.2.0",
    "configurations": [
        {
            // Use IntelliSense to find out which attributes exist for C# debugging
            // Use hover for the description of the existing attributes
            // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
            "name": ".NET Core Launch (console)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            // If you have changed target frameworks, make sure to update the program path.
            "program": "${workspaceFolder}/bin/Debug/net6.0/CodeFirst.dll",
            "args": [],
            "cwd": "${workspaceFolder}",
            // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
            "console": "internalConsole",
            "stopAtEntry": false
        },
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach"
        }
    ]
}
Project using the Code First workflow

To add a migration, click the “Run” button on the code widget above. Then, to create a migration named InitialMigration, execute the command below in the terminal:

C#
dotnet ef migrations add InitialMigration

Note: It’s good practice to use meaningful names as migration names. This practice makes it easier to understand the migration history when reviewing later.

We apply this migration to the database by using the command below:

C#
dotnet ef database update

Next, let’s run some SQLite commands to review the content of the database. The command below opens the SQLite prompt and connects to the database:

C#
sqlite3 output/Artists.db

Now let’s display all the tables created in the database with the command below:

Shell
.tables

A snippet from the output is below:

Shell
sqlite> .tables
AlbumTags Employees Tags
Albums Studios __EFMigrationsHistory
sqlite>

Notice the __EFMigrationsHistory table amongst the listed tables. EF Core uses this table to keep track of applied migrations.

Next, quit the SQLite prompt by executing the command below:

C#
.quit

The updated project is below:

{
    "version": "0.2.0",
    "configurations": [
        {
            // Use IntelliSense to find out which attributes exist for C# debugging
            // Use hover for the description of the existing attributes
            // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
            "name": ".NET Core Launch (console)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            // If you have changed target frameworks, make sure to update the program path.
            "program": "${workspaceFolder}/bin/Debug/net6.0/CodeFirst.dll",
            "args": [],
            "cwd": "${workspaceFolder}",
            // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
            "console": "internalConsole",
            "stopAtEntry": false
        },
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach"
        }
    ]
}
Project with InitialMigration files

Note that this project has a context class named ArtistsContext in the Data directory, as well as entity types located in the Entities directory. The entities are:

  • Employee: Represents the music artists’ names and ages
  • Studio: Represents the studio addresses where the music artists work
  • Album: Represents the albums released by music artists.
  • Tag: Represents categories of albums

Reviewing the migrations

Notice in the updated project, captioned “Project with InitialMigration files,” that the Migrations directory houses the migration source files. We review these files below:

  • xxx_InitialMigration.cs: This is the main migration file which contains two methods: Up and Down. The Up method contains all the operations necessary to apply changes to the database. The Down method contains the operations required to roll back those changes.
  • xxx_InitialMigration.Designer.cs: This is a metadata file used by EF Core.
  • ArtistsContextModelSnapshot.cs: This file is created at the first migration and gets updated at every migration. It provides a snapshot of the current model and determines what changes exist before adding another migration.

The xxx_InitialMigration.cs file uses methods to build objects:

  • Lines 11–101 of xxx_InitialMigration.cs use the CreateTable method of the MigrationBuilder class to build CreateTableOperation objects. These objects create the relevant tables when the migration is applied.

  • Lines 103–117 of xxx_InitialMigration.cs use the CreateIndex method of the MigrationBuilder class to build CreateIndexOperation objects. These objects create the relevant indexes when the migration is applied.

It is worth noting the order of table creation. EF Core creates the parent tables before the child ones. For example, the Studios table gets created after the Employees table because it is a child of the Employees table.

Reviewing the database update

After executing the dotnet ef database update command, EF Core performs the following actions:

  • It creates the database (if it did not exist) referenced in the OnConfiguring method of the ArtistsContext.
  • It applies the operations specified in xxx_InitialMigration.cs. This includes creating the entities specified in ArtistsContext.cs as tables.
  • It creates a table named _EFMigrationsHistory (if it did not exist) in the database. EF Core uses this table to keep track of applied migrations.