Introduction

Entity Framework is one of the topmost rich ORM tool from Microsoft targeting .NET framework. Entity Framework can be used with different approaches like Code-First, Database First, and Model First.  Code-First and Database-First approaches are mostly used by the developers.

As this article is more on Migrations I don’t want to go into deep discussions on understanding these approaches. But, if you are interested please find the below link for understanding differences between Code-First and Database-First approaches.

EF Code-First Approach Vs Database First Approach

Understanding Migrations

Migrations in Entity Framework is a process of applying any changes done in Domain Models (code side) to the database. For example, if I have a table USER with columns User Id, First Name, Last Name in database and USER domain model (User Id, First Name, Last Name as properties) in my application. If I added another property called Middle Name in my USER domain Model, Entity Framework Migration tool will help to apply this new change (i.e., by adding new column) to the configured database.  

Migration feature can be enabled only for Code-First Approach. Earlier before Entity Framework 4.3, EF can only handle below such migrations as per requirement

  • Create Database If Not Exists using CreateDatabaseIfNotExists() method.
  • Drop Create Database If Model Changes using DropCreateDatabaseIfModelChanges() method.
  • Drop create database always using DropCreateDatabaseAlways() method.

But, with above migrations, there will be a data loss if anything exists in the database which is not mapped to any models in the application like triggers, Stored Procedures etc.., as we always drop and creates the database.

Since Entity Framework 4.3 version, Microsoft introduced a new Migration tool which identifies the changes happen since last migration and applies to the database without any data loss using Database initializer MigrateDatabasetoLatestVersion() method.

Now let’s understand the implementation of these Migrations. There are two types of Migrations one is Automatic Migrations and another is code-based Migration.  Before understanding these types let create a sample console application (name it as Migrations) for better understanding and do the following

  1. Install latest Entity Framework from NuGet Package Manager. (Ver 6.2.0 while writing this article)
  2. Create one User class with UserId, FirstName, and LastName properties and place it in Domain Model folder.
  3. Create another class called MyDBContext and inherit from DBContext class. This class will act as a DBcontext for our database operations.
  4. Add Users property which returns DBSet<User> in MyDBContext class. As this property represents the table in the database.
  5. Add connection string with your new database name (for the demo I named it as MyDatabase). Please make sure the given database doesn’t exist on the server.

Once you are done with above, following will be the solution structure  

Now we are done with the initial setup of Entity Framework with Code-First Approach (as we don’t have any physical database yet created). To enable Migrations to feature to our application either it may be Automatic or Code-Based we need to run Enable-Migrations command in the Package Manager Console (in Visual Studio, go to  Tools -> NuGet Package Manager -> Package Manager Console) as follows. 

Please make sure to select the respective project where you want to enable migrations as this will be mostly a repository project. As it will look for the class DBContext in the given project.

Once we enable Migrations it will create a new class called Configuration under Migrations folder as follows

As observed in the above screenshot, there is a method called Seed which will be called once migration process completes. If we have any base data need to be inserted or updated can be written over here. In our case, for example, if we added a new column Middle Name and once this column is added to the database I want to update it with any default value or any text based on other columns on the row.

We will write the following set of code to initialize our DBContext object and get all the users information. Note, as per our earlier we discussion, Database migrations will be performed when we do our first DB call.

class Program 
{ 
        static void Main(string[] args) 
        { 
            using (MyDBContext dbContext = new MyDBContext()) 
            { 
                var users = dbContext.Users.ToList(); 
            } 
        } 
}

All the Migration changes will be maintained in a table __MigrationHistory in the configured database.

Now, we almost enabled Migrations but before forwarding, e need to understand different types of Migrations and it all depends on which type need to go with.

Automatic Migrations

To Enable Automatic Migrations, we need to set AutomaticMigrationsEnabled property to true in the Migration generated Configuration class as follows.

internal sealed class Configuration : DbMigrationsConfiguration<MyDBContext> 
    { 
        public Configuration() 
        { 
            AutomaticMigrationsEnabled = true; 
        } 
  
        protected override void Seed(MyDBContext context) 
        { 
            //  This method will be called after migrating to the latest version. 
  
            //  You can use the DbSet<T>.AddOrUpdate() helper extension method  
            //  to avoid creating duplicate seed data. 
        } 
    }

We can even enable this feature while enabling Migrations with the following statement  

Enable-Migrations -EnableAutomaticMigrations=$true

When we enable Automatic Migrations, Framework will identify the changes happen on the database objects in the application since last migration (verified in __MigrationHistory table) and automatically applies these changes to the database.

Once you enable Automatic Migrations when we run the application for the first time. The runtime will identify the given database is not exist and creates a new database with given name in connection string will all database objects declared in MyDBContext (in our case only User table) along with an additional table __MigrationHisotry.

Code Based Migrations

Using this type of migrations, a user will push all the changes to the database manually. This is a default Migration type when we enable migrations. If we want to enable this type of migration just set AutomaticMigrationsEnabled property to false. But if the system identifies any changes in the database objects in the application and which is not pushed or migrated to the database it will generate an error and ask user to manually migrate all the changes to the database.

To migrate all the changes to the database user must execute two commands, one command to identify and prepare all the changes based on last migration and another command to update the database with all these identified changes.

Add-Migration is the command used identify and prepare all the changes based on last migration. We need to provide a unique name while executing this command as follows. 

Add-Migration "InitialDB"

In our case, I am giving InitialDB as the name. Once we run this command, Migration tool will add a new file with format YYYYMMDDHHMMSSS_<givenname>. This class will inherit DbMigration class where Migration tool is enough intelligent to identify all the changes and provide those in this file as follows  

There will be two methods one is Up() which will be called when we want to migrate changes from application to database and Down() will be called when we want to roll back to a particular version (given name). 

Update-Database command is used to send all the changes from application to database as follows 

Update-Database

If you want to roll back to a particular version we need to run following command. 

Update-Database -TargetMigration: "InitialDB"

We have many options while working with these commands as for example I can create all migrations on different project other than the project containing DBContext and domain models etc..,

Please find the complete source code of this sample console application from the below link

Source Code

Hope this article helps you to understand the concept of EF Migrations. Please send your valuable comments below.

Happy Coding 🙂