Thursday, January 19, 2012

Entity Framework 4.2 Code First

This is a series of post in which we will be discussion about the Entity Framework Code First. In this post we will be discussing how we can create a simple database oriented application using Entity Framework 4.2 released Nov, 2011. This post assumes that you have SQL Server Express installed on your machine with its Database engine and Management Studio.

Let's create a console application, named EFCodeFirstDatabaseCreation. In order to use the features of Entity framework, we need to add EntityFramework Nuget to the project. [Introduction to Nuget]


In this example, we would consider a simple application to maintain data about students. We would seed testing data using initializing code. We would be querying this data using Entity Framework Code First. Let's first define Student entity. As we can see this is a simple POCO (Plain Old CLR Object) based class with a few auto-implemented properties. Most certainly, we don't need to inherit it from any special class.
namespace EFCodeFirstDatabaseCreation.Entities
{
    class Student
    {
        public int StudentId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int GradePointAverage { get; set; }
        public bool IsOutStanding { get; set; }
    }
}


Now we need to define the DbContext for querying the entities from Database. Here Entities are defined in terms of DbSetbased properties. We can query the database using these properties. It also supports insert / update and delete operations on these entities.
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Data.Entity;

    class InstituteEntities : DbContext
    {
        public DbSet<Student> Students { get; set; }
    }
}


Now we need to insert seed data to the database. The initializer can inherit from one of the following:
  1. DropCreateDatabaseAlways<T;Context>
  2. DropCreateDatabaseIfModelChanges<T;Context>
  3. CreateDatabaseIfNotExists<T;Context>

All of the above three initializers are basically the implementation of IDatabaseInitializer<T;Context>. Basically Code First supports automatic creation / updates of the Database based on POCO entities. These implementations specify what circumstances should cause creation of a new Database. By default the name of the database would be based on the name of class inheriting from DbContext and its namespace. e.g. for our case it is EFCodeFirstDatabaseCreation.Entities.InstituteEntities. We can specify a different name by causing the relevant constructor of DbContext (base class) to be used. So if we just update the code as following then the name of created database would be InstituteDB.
public InstituteEntities()
    : base("InstituteDB")
{ }

As discussed above, we add InstituteDatabaseInitializer to the project. As you can see we are adding four students to the database. It seems all four of them are outstanding :). Calling base class's seed method would cause data to be pushed to the database saving the changes in the entities.
namespace EFCodeFirstDatabaseCreation
{
    using EFCodeFirstDatabaseCreation.Entities;
    using System.Data.Entity;

    class InstituteDatabaseInitializer : DropCreateDatabaseAlways<InstituteEntities>
    {
        protected override void Seed(InstituteEntities context)
        {

            Student student1 = new Student()
            {
                FirstName = "Muhammad",
                LastName = "Siddiqi",
                IsOutStanding = true,
                GradePointAverage = 3
            };


            Student student2 = new Student()
            {
                FirstName = "Chattan",
                LastName = "Shah",
                IsOutStanding = true,
                GradePointAverage = 4
            };

            Student student3 = new Student()
            {
                FirstName = "Imran",
                LastName = "Ashraf",
                IsOutStanding = true,
                GradePointAverage = 4
            };

            Student student4 = new Student()
            {
                FirstName = "Jawad",
                LastName = "Qureshi",
                IsOutStanding = true,
                GradePointAverage = 4
            };

            context.Students.Add(student1);
            context.Students.Add(student2);
            context.Students.Add(student3);
            context.Students.Add(student4);

            base.Seed(context);
        }
    }

}

Now we just need to query the database after seed data is inserted. We can use this data for our testing. Just first initilze the database using the InstituteDatabaseInitializer defined above. Then we are just printing student's data to the console.
namespace EFCodeFirstDatabaseCreation
{
    using System.Linq;
    using EFCodeFirstDatabaseCreation.Entities;
    using System.Data.Entity;
    using System;

    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer<InstituteEntities>(new InstituteDatabaseInitializer());
 
            InstituteEntities instituteEntites = new InstituteEntities();
            var students = instituteEntites.Students.ToList<Student>();

            foreach (var student in students)
            { 
                Console.WriteLine(
                            string.Format("Name : {0} {1}, GPA : {2}", 
                                       student.FirstName,
                                       student.LastName,
                                       student.GradePointAverage));                                       
            }

            Console.ReadLine();
        }
    }
}
When we run the application, it shows the following output. This shows that the correct seed data is inserted to the database.


The interesting thing to notice is that we are not specifying any connection string anywhere in the application and yet we are able to run the application without any issues. This is only possible if you have local SQL Express installed on the development machine, otherwise, we can specify the connection string in the app.config. We can also access the same database using a query tool. In the following, we are connecting this using SQL Management studio and querying the student's data. Notice the same data as seeded by the application.


Download :