Getting started with Code First Approach and Entity Framework Migrations Commands

For better understanding on Entity Framework, I recommend you to read EF Series by Anders Abel on his blog here . I learnt lot from his post about Entity Framework. You may want to follow Julie Lerman for better learning on ADO.NET Entity Framework.

In this post we will walk through basics of Entity Framework migration commands and learn about Code First Approach. Entity Framework allows you to create database from plain classes. You can model your domain into classes and subsequently database can be created or updated from the model using Entity Framework.

We model domain into classes and database gets created form model classes is known as Code First Approach. Here you can create database from plain old classes. Model classes does not have to extend any base class etc. The other two approaches are,

  1. Model First Approach
  2. Database First approach

Code First Approach in Entity Framework reduce task of modelling database on designer and working with XML etc.

Let us start rolling, suppose we need to model School database. For this we have created two POCO classes as below.


Public class School
    {
        public int Id { get; private set; }
        public string Name { get; set; }

        public Icollection<Student> Students { get; set; }

    }

    public class Student
    {
        public int Id { get; private set; }
        public string Name { get; set; }
        public string  Grade { get; set; }
    }


School and Student classes are representing School and Students real time entities respectively. Next we need to create Context class. This class must inherit DbContext class.


Public class Context : DbContext
    {
      public Context() :base()
        {

        }
        public DbSet<Student> Students { get; set; }
        public DbSet<School> Schools { get; set; }
    }


Regardless what kind of application you are working with and following Code First approach, you need to add reference of EntityFramework. You can use NuGet manager to install EntityFramework library in project you are working.

image

When you execute code, surprisingly you will find database has been created. You may wonder that where Context database (we created class Context which is inheriting DbContext class) has been created? Let us go back to context class, we have not provided any connection string in constructor. In this case database would get created in local SQL Express comes with Visual Studio. Alternatively connection string name can be provided in constructor to create database on a particular database server. Connection string can reside in configuration file. You can launch Server Explorer to view created database. Let us go ahead and examine schema of created table,

Student table is created as below,

image

And School table being created as below,

image

EF is intelligent enough to construct primary key on the column with name Id. If you don’t have Id column then EF will search for column with *Id and construct that column as primary key. For example if there is a property EmployeeId in model class then EF will construct column EmployeeId as primary key.

Other thing you may notice that for string properties EF is creating columns with type nvarchar(MAX). You may not want this and have control on size of the columns in database. This is allowed in EF using data annotations. Let’s go ahead and modify POCO classes with data annotation.


Public class School
    {
        public int Id { get; private set; }
        [Required]
        [StringLength(50)]
        public string Name { get; set; }

        public Icollection<Student> Students { get; set; }

    }

    public class Student
    {
        public int Id { get; private set; }
        [Required]
        [StringLength(50)]
        public string Name { get; set; }
        [Required]
        [StringLength(10)]
        public string  Grade { get; set; }
    }


We have put data validation annotations like Required (in db null not allowed) and StringLength. Other data validation annotations are MaxLength and MinLength.

Let’s go ahead and run again to recreate or update database schema. On running application I got following exception. Poor me,

image

EF is throwing very clear error message. We can break error in message in two parts,

  1. Model backing Context has changed
  2. It has changed since database has created

It is suggesting us to consider Code First Migration. So let’s learn Code First Migration. Before we go ahead and explore various migration techniques, let’s have a look on Database initialization strategies. There are four database initialization strategies,

  1. CreateDatabaseIfNotExist
  2. DropCreateDatabaseIfModelChanges
  3. DropCreateDatabaseAlways
  4. Cutsom DB Initalizer

All options are self-explanatory. One option is to use DropCreateDatabaseIfModelChanges database initializer to get rid of above exception. Let’s go ahead and modify Context class by adding database initializer in constructor,


public class Context : DbContext
    {
      public Context() :base()
        {

            Database.SetInitializer<Context>(new DropCreateDatabaseIfModelChanges<Context>());

        }
        public DbSet<Student> Students { get; set; }
        public DbSet<School> Schools { get; set; }
    } 


Okay so we did not get any exception and database schema has been updated as well. You may notice Name column has been updated with length 50 and Nulls are not allowed.

image

All good? Not really because we have lost all the data. Since in database initializer we have used option to drop database and create again if model changed. I am sure you don’t like this option and must be looking for some better options.

Other option is to Enable Migrations. You can enable migration by EF command. You can run EF command from Package Manager Console. Enable Migrations run command

PM> Enable-Migrations

image

I have run command to enable automatic migration. Let’s go back to solution explorer, you will find a Migration folder is being added with a class Configuration.cs . This class got a seed method. Configuration class will look like below,


internal sealed class Configuration : DbMigrationsConfiguration<SchoolDbApplication.Context>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
            ContextKey = “SchoolDbApplication.Context”;
        }

        protected override void Seed(SchoolDbApplication.Context 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. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = “Andrew Peters” },
            //      new Person { FullName = “Brice Lambson” },
            //      new Person { FullName = “Rowan Miller” }
            //    );
            //
        }
    }


As you see that,

  1. AutomaticMigrationEnabled is set to true
  2. There is Seed method which will get executed after migrating to the latest version. So if you want to have some default data after migration, you will write code in Seed method.

Let us consider another scenario that we want to add one more column in Student table and for that we need to add a property in Student class. Modified Student class will look like below,


public class Student
    {
        public int Id { get; private set; }
        [Required]
        [StringLength(50)]
        public string Name { get; set; }
        [Required]
        [StringLength(10)]
        public string  Grade { get; set; }
        [Required]
        public int Age { get; set; }
    }


I have added Age property with basic data annotation [Required]. Previously when we tried modifying class and later database we lost all the data. This time we don’t want to repeat the mistake. So after modifying model class, add a migration with a name. Let’s run a command and give a name Student_Age to newly added migration. You are allowed to give any name of your choice.

PM> Add-Migration Student_Age

image

Further if required you can change Model and include in the same migration by running the same command. Let us go ahead and explore solution explorer again. In solution explorer inside Migrations folder you will find somenumber_Student_Age.cs file. This class contains information about this particular migration. Remember that we gave name of the migration as Student_Age.

Namespace SchoolDbApplication.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class Student_Age : DbMigration
    {
        public override void Up()
        {
            AddColumn(“dbo.Students”, “Age”, c => c.Int(nullable: false));
        }
        
        public override void Down()
        {
            DropColumn(“dbo.Students”, “Age”);
        }
    }
}


There are two methods inside this class Up and Down method. In Up method a column being added to Students table whereas in Down method column is dropped. Don’t forget to run Update-database command to update model changes in database.

PM> update-database –verbose

image

This time you will find database has been updated and age column is added to Students table with no loss of data.

For complete reference of EF Migrations commands you may want to refer here

Summary

In this post we learnt Code First approach in ADO.NET Entity Framework and some of the EF commands. I left you reference to learn further on same subject also. I hope after learning this post you should able to understand what is going around various EF commands and don’t accidently delete data while updating the schema. In further posts I will talk about Custom DB Initalizer and other important bits of Entity Framework.

Happy Coding.

One response to “Getting started with Code First Approach and Entity Framework Migrations Commands”

  1. […] Getting started with Code First Approach and Entity Framework Migrations Commands. […]

Leave a comment

Create a website or blog at WordPress.com