Adding Migrations On Entity Framework .NET Core

In this post we will look at adding migrations on entity framework .net core applications.

Introduction

In our previous post, we looked at how we can setup our .net core app with entity framework code first approach. We will continue with the same DbContext and User entity that was created in the previous post for this post.

In any application, the data models frequently during the development phase. So, we need to have a mechanism to update the database entities accordingly.

Updating Entities

If we take a look at the definition of the previously created User table, it should look like this:

//sql for create Users table 

CREATE TABLE `users` (
   `Id` varchar(255) NOT NULL,
   `FirstName` longtext,
   `LastName` longtext,
   `Email` longtext,
   `Password` longtext,
   `CreatedAt` datetime(6) NOT NULL,
   `UpdatedAt` datetime(6) NOT NULL,
   PRIMARY KEY (`Id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1

Since, we did not specify the data types for the columns, by default Entity Framework added default data-types for these columns.

Now, if we want to have specific data-types, we should explicitly define these properties.

One way to do so is using “Data Annotations“.

Let’s use some make use of the annotations to modify our User table.

//User.cs

using System;
using System.ComponentModel.DataAnnotations;

    public class User
    {
        [Key]
        public string Id { get; set; }

        [Required]
        [MaxLength(50)]
        public string FirstName { get; set; }
        [Required]
        [MaxLength(50)]
        public string LastName { get; set; }
        [Required]
        [MaxLength(50)]
        public string Email { get; set; }
        [Required]
        [MaxLength(50)]
        public string Password { get; set; }

        [Required]
        public DateTime CreatedAt { get; set; }
        [Required]
        public DateTime UpdatedAt { get; set; }
    }

As you can see, we have made use of annotations like [Key], [Required] and [MaxLength] here. These identifiers are used to declare a column as primary, non-nullable and specific length data-type respectively.

Running Migrations On Entity Framework

Let’s create and run the migration for User entity.

dotnet ef migrations add AddingDataTypesToUser
dotnet ef database update

Now if we take a look at our table schema, we shall see much better data types specified.

CREATE TABLE `users` (
   `Id` varchar(255) NOT NULL,
   `FirstName` varchar(50) NOT NULL,
   `LastName` varchar(50) NOT NULL,
   `Email` varchar(50) NOT NULL,
   `Password` varchar(50) NOT NULL,
   `CreatedAt` datetime(6) NOT NULL,
   `UpdatedAt` datetime(6) NOT NULL,
   PRIMARY KEY (`Id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1

Adding Foreign-key Relationships

Now that we have learnt to add migrations on an existing entity framework entity, let’s learn how we can add more entities. To complicate things a little, we will add a Foreign Key relationship as well.

Create another entity called Business such that there is a one-to-many relationship between users and businesses. Each user can have multiple businesses.

//Business.cs

public class Business
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [MaxLength(50)]
        public string Name { get; set; }

        [Required]
        public BusinessTypes BusinessType { get; set; }

        [Required]
        [DataType(DataType.Time)]
        public string OpeningTime { get; set; }

        [Required]
        [DataType(DataType.Time)]
        public string ClosingTime { get; set; }

        [Required]
        [ForeignKey("User")]
        public int CreatedBy { get; set; }
        public User User{ get; set; }

        [Required]
        public DateTime CreatedAt { get; set; }

        [Required]
        public DateTime UpdatedAt { get; set; }
    }

Here, we have made use of [ForeignKey] annotation.

Let’s create and run the migrations again:

dotnet ef migrations add AddBusiness
dotnet ef database update

Oops!

If you followed the steps above properly, you might have noticed that our Business table wasn’t created in the database.

The reason being that we forgot to add the DbSet entry in our context model. Let’s correct this by adjusting our context class.

//MyDBContext.cs

public class MyDBContext: DbContext
    {
        public MyDBContext(DbContextOptions<MyDBContext> options)
            : base(options)
        { }

        DbSet<User> Users { get; set; }
        DbSet<Business> Businesses { get; set; }
    }

Since we have already created a migration, we need to remove it first and re-create the migration.

Removing A Migration

If after adding a migration you realize that you need to make some changes on it, you can use the command below.

dotnet ef migrations remove

This will remove the latest migration that was added.

Reapply Migration

dotnet ef migrations add AddBusiness
dotnet ef database update

This will create a new table the database with the following table schema:

CREATE TABLE `businesses` (
   `Id` int(11) NOT NULL AUTO_INCREMENT,
   `Name` varchar(50) NOT NULL,
   `BusinessType` int(11) NOT NULL,
   `OpeningTime` longtext NOT NULL,
   `ClosingTime` longtext NOT NULL,
   `CreatedBy` int(11) NOT NULL,
   `CreatedAt` datetime(6) NOT NULL,
   `UpdatedAt` datetime(6) NOT NULL,
   PRIMARY KEY (`Id`),
   KEY `IX_Businesses_CreatedBy` (`CreatedBy`),
   CONSTRAINT `FK_Businesses_Users_CreatedBy` FOREIGN KEY (`CreatedBy`) REFERENCES `users` (`Id`) ON DELETE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1

Reverting A Migration After Database Update

Sometimes you might need to revert a migration after the database was already updated. In such scenario, you should re-apply the migration that you wish to revert the database to. We can make use of this command for that:

dotnet ef database update {name of migration}

Conclusion

This post covered adding column definitions, foreign key relationships and column updates on entity framework entities in .net core applications. Furthermore, we also looked at adding, removing and reverting migrations.

With this post and the previous post, we have covered most of the use case scenarios for working with Entity Framework entities.