Wednesday, February 22, 2012

Entity Framework Code First - Relationship between Entities III [Loading Related Entities]

This post is amongst the series of our discussions about Entity Framework Code First. As an example, we have been building on top of Institute Entities. There are two things which you might have noticed in the example that we have been following. Let me bring them up:
  1. Using virtual with associated entities in an entity's definition, e.g. for Student entity:
  2. public virtual ICollection StudentCourses { get; set; }
    public virtual Vehicle VehicleDetails { get; set; }
    public virtual Department StudentDepartment { get; set; }
    
  3. Using Include in the iterator for loading courses as follows:
  4. foreach (var course in instituteEntites.Courses
                                .Include("CourseStudents")
                                .Include("CourseStudents.VehicleDetails")
                                .Include("CourseStudents.StudentDepartment")
                                .Include("CourseOfferedAt"))
Both of these are kind of related to this discussion.

Why different data loading mechanisms for related entities?
First of all, we need to understand why we need these different mechanisms for loading data. The reason is that we want optimized database access in order to avoid unnecessary number of round trips and the amount of data loaded. We must remember that database resides in an outside system with network in between. It is an I/O operation which is costly. Entity framework must translate the relevant operations on entities to SQL statements. This feature is to guide the framework to generate more efficient SQLs.

It is to suggest to Entity framework about related entities whenever an entity is loaded. If A is an entity which has an EntityReference or an EntityCollection of another entity B. This feature allows to direct EF API if the related B's data should be loaded when A is loaded. If we need to just load A's data and loading B's data only when it is accessed first time then we need Lazy loading. If we know that we would always be needing the related B's data when A is loaded then we need Eager loading. On the other hand if we don't want to the related B's when A is loaded and request it separately if required independently or for related A's then it comes under Explicit Loading. Since EF Code First is mostly convention based, we need our POCO entities to identify these options using some conventions.

Types of Loading
Based on the above discussion it is apparent that rhere are three ways that relationship entities can load when one of the source entity is loaded. They are as follows:
  1. Explicit
  2. Lazy loading
  3. Eager loading

No Implicit Eager Loading
It must be remembered that that turning off lazy loading does not mean an implicit eager loading. There is nothing like implicit eager loading of entities in Entity Framework except for complex types. This is because all entities might be related to each other in some way or the other [Foreign key relationships in Databases]. If EF allows implicit eager loading then loading one entity would mean loading the whole database which might be very costly. Since this is implicit so the developers would have no idea what is going on behind the scenes unless SQL profiler is hooked up.

Lazy loading & Better Performance
The contrary is also not true i.e. lazy loading might or might not result in better performance. If we don't need data of related entities then the lazy loading would save us from querying additional data from the database. But if we need the navigational data then it means that there would be additional queries to the database when the navigational property is accessed. This might be unnecessary.

Proxy Is Entity Decorator
These types of loading is enabled in Entity Framework by introducing Proxies. Proxy is the implementation of Decorator Design pattern to provide additional capabilities to user defined entities. Both proxy and entity are not of certain type of abstraction but proxy does extend the entity. It inherits from the same POCO entity and creates a field for the POCO type it is decorating. Then it decorates it by adding some features. One of such feature is the loading behavior of related entities. Since Entity Framework is design with the idea of convention over configuration. Defining our POCO entities in a certain way is basically communicating to Entity framework about how we expect the property behavior in the proxy.

A public non-sealed navigation property defined as virtual in POCO entity is telling the Entity framework to enable lazy loading for the specified relationship entity. The relationship entity is not loaded when the main entity is loaded.

In the case of Student, since we have defined CourseStudents and CourseOfferedAt navigation properties as virtual. This would result in the behavior that these entities are not loaded when related Student entity is loaded. If we just load a Student entity like this, then the related Course(s) and CourseLocation(s) would not be part of the query. EF loads them lazily when required.

As a consumer of the Object Relational Mapping [ORM] tool we don't want our entities to be adulterated by inheriting from the types provided by Entity Framework. It used to be EntityObject in earlier version of Entity Framework. We also don't want to decorate it with certain attributes which makes us bind to a particular ORM tool. Entity framework still supports it by reusing some attributes provided by Data annotations library and some custom attributes developed for Entity Framework team at Microsoft. In order to understand various loading options of related entities we need to understand the concept of proxies in Entity Framework. We need to understand how it adds certain features of our entities without modifying them. The various features of proxies includes lazy loading and change tracking of entity's data. This makes it very clear that lazy loading is just a decoration of our entities provided by adding a proxy, so if we disable creation of proxy, no lazy loading is available. This is exactly what happens.
this.Configuration.LazyLoadingEnabled = false;
Additionally, the POCO classes must be designed such that they support proxy creation and lazy loading.The requirements include POCO entity must be defined as public and navigation property should support late binding by being virtual. The details can be found here.
http://msdn.microsoft.com/en-us/library/gg715126%28v=vs.103%29.aspx

The proxies created by entity framework for our entities is certainly the decoration of these entities. This adds the feature of lazy loading and change tracking to the entity. This is added without modifying the entity which is based on OPEN / CLOSE principle. The proxy can be used wherever the original entity is expected. This is based on LISKOV Substitution principle. Remember that Entity framework is smart enough to recognize the need of proxy creation. If the entity is defined in such a way that creating it would not add any value i.e. change tracking or lazy loading then EF would not create a proxy and work with the entity type itself. Proxy creation can also be disabled by DbContext which would also result in use of entity types directly.

Choice of Loading option and its Consequences
Generally the settings for lazy loading is specified in the constructor of sub-type of DbContext. In the following example, we are turning on the lazy loading for all entities. This would be the default behavior of entities which they can override.

class InstituteEntities : DbContext
{
     //...
     public InstituteEntities()
     {
        this.Configuration.LazyLoadingEnabled = true;          
     }
     //...
}

Now individual entities can override this behavior for their navigational properties as follows:
  1. Defining a navigational property as virtual would cause lazy loading of the navigational entity.
  2. Defining a navigational property as non-virtual would not cause lazy loading. Now this may be loaded explicitly by using Load method on EntityCollection / EntityReference, or using Include method and specifying query path.
On the other hand, if we define the DbContext not to support lazy loading then we can not override this behavior if they need lazy loading of related entities. So the best option is to support lazy loading and eagerly / explicitly loading whenever required so that you could save extra cost of additional database queries to the database. In order to support lazy loading, the cost is the creation of proxies by the framework.
Disabling lazy loading will not support deferred loading of entities when they are needed using related entities. Now the only options remaining are explicit and eager loading. Both of them are specified through code.
Eager Loading

How to make a decision?
The decision between the pattern for loading related entities should be a deliberate one. This is because it would impact the overall performance of the system. Consider the difference as to be the two different concepts of locality of references. As we know there are two ideas for locality of reference, they are:
  1. Temporal Locality
  2. Spatial Locality
The whole caching idea is based on these two ideas of locality of reference. Based on the first one, there are more chances that the data accessed once would be needed again. So instead of bringing that data again, it should be stored in a readily available storage. The latter suggests that there are certain requirement of data for each different process. so if some data is accessed, then there are more probability that some data in the neighborhood would be required next so bring that in some readily available storage and make it available if needed. The usage of either or both depends on your implementation of caching. The eager loading is based on spatial locality. If we need data of an entity then there is higher probability that the data of related entities would also be needed. Database access is basically requesting data from an external system called DBMS [DataBase Management System] which is obviously a costly operation. If you think that your data requirement would be based on spatial locality and your data access requirements suggest the requirement of data access of related entities is more probable then use Eager Loading, otherwise, use implicit or lazy loading.

Entity Definition
Let's see what changes in Student entity would be needed to support lazy loading. First we have changed the access modifier to public. Additionally we have three related entities of Student. They are StudentCourse, VehicleDetails and StudentDepartment of type Course, Vehicle and Department respectively. Here VehicleDetails and StudentDepartment are defined as virtual to support lazy loading.
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;

    public 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; }
        
        //no lazy loading
        public ICollection<Course> StudentCourses { get; set; }
        
        //support lazy loading
        public virtual Vehicle VehicleDetails { get; set; }
        public virtual Department StudentDepartment { get; set; }
    }
}
Similarly, Course entity is also updated as follows:
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;

    public class Course
    {
        public int CourseId { get; set; }
        public string CourseName { get; set; }

        //no lazy loading
        public ICollection<Student> CourseStudents { get; set; }
        
        //support lazy loading
        public virtual ICollection<CourseLocation> CourseOfferedAt { get; set; }
    }
}

Let's see how LocationAddress is defined. Since this is a ComplexType, it does not support lazy loading.
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;

    public class CourseLocation
    {
        public int CourseLocationId { get; set; }
        public string LocationName { get; set; }
        public LocationAddress Address { get; set; }
        public virtual ICollection<Course> CoursesOffered { get; set; }
    }

    public class LocationAddress
    {
        public string StreetAddress { get; set; }
        public string Apartment { get; set; }
        public string City { get; set; }
        public string StateProvince { get; set; }
        public string ZipCode { get; set; }
    }
}

Explicit Loading
Explicit loading would result in fetching the required entity's data from database if required. We can use Load method on an EntityReference or EntityCollection. ObjectContext's Load property can also be used for the same purpose.
private static void PrintStudentNames()
{
    using (var context = new InstituteEntities())
    {
        //explicit loading of all students
        context.Students.Load();
        foreach (var student in context.Students)
        {
            Console.WriteLine("Student Name: {0}", student.FirstName);
        }
    }
}
Let's see another example of Explicit loading. Here we are doing conditional explicit loading of students belonging only to a particular department.
private static void PrintDepartmentAndStudentsDetails()
{
    using (var context = new InstituteEntities())
    {
        //Explicit loading with query 
        foreach (var department in context.Departments)
        {
            Console.WriteLine(string.Format("Department Name: {0}", department.DepartmentName));
            context.Entry<Department>(department)
                .Collection(d => d.Students)
                .Query()
                .Where(s => s.StudentDepartment.DepartmentId == department.DepartmentId)
                .Load();

            foreach (var student in department.Students)
            {
                Console.WriteLine(string.Format("         Student: {0}", student.FirstName));
            }
        }

    }
}
In the following example, we are using Linq to Entities to query Department and its related Students entities. Here stds is of type DbQuery.
private static void PrintStudentAndTheirDepartments()
{
    using (var context = new InstituteEntities())
    {
        //Loading using Linq to Entities
        var stds = from d in context.Departments
                   from st in d.Students
                   select new { d.DepartmentName, st.FirstName };

        foreach (var s in stds)
        {
            Console.WriteLine(
                string.Format("Department: {0}, Student: {1}",
                    s.DepartmentName, s.FirstName));
        }
    }
}
Here DbQuery is the same class as the parent type for DbSet used with DbContext.


We can use an iterator to go through the items. It is defined as follows:


Lazy Loading Students
In the following example, we are getting any arbitrary department returned. We are then querying for all the students in the department and printing their details.
private static void LazyPrintStudentNames()
{
    using (var context = new InstituteEntities())
    {
        var firstDepartment = context.Departments.First<Department>();

        //lazy loading of all students
        foreach (var student in firstDepartment.Students)
        {
            Console.WriteLine("Student Name: {0}", student.FirstName);
        }
    }
}
Eager Loading
In Entity Framework Code First, Eager Loading is supported by using Include. It, not only supports, loading the direct relationship entities but we can traverse the hierarchy of relationship. See how we are loading the vehicle details of all the students for all departments. We can also ensure type safety by using expressions. Here we are loading Students data using that.
private static void PrintInstituteDetails()
{
    using (var context = new InstituteEntities())
    {
        //Eager loading of Vehicle and Studentsinformation
        foreach (var department in context.Departments
                                           .Include(d => d.Students)
                                           .Include("Students.VehicleDetails"))
        {
            Console.WriteLine(
                string.Format("Department Name: {0}", 
                        department.DepartmentName));

            foreach (var student in department.Students)
            {
                Console.WriteLine(
                    string.Format("***Student: {0}", student.FirstName));
                if (student.VehicleDetails != null)
                {
                    //Explicit loading using Load
                    context.Entry<Student>(student)
                        .Collection<Course>(s => s.StudentCourses)
                        .Load();

                    foreach (var c in student.StudentCourses)
                    {
                        Console.WriteLine("*********Course Name: {0}", c.CourseName);

                        //loading navigation property to a complex type
                        Console.WriteLine(
                            string.Format("Also offered at city: {0}", 
                            c.CourseOfferedAt.First<CourseLocation>().Address.City));
                    }
                }
            }
        }
    }
}

It must be remembered that complex types are always loaded in eager fashion. We don't need to use an Include for them as this is the default behavior of EF Code First. In the above example LocationAddress is a complex type. It is defined as complex type based on convention. We don't need to use complex type attribute if we are following the conventions.
public static void Main(string[] args)
{
    Database.SetInitializer<InstituteEntities>(new InstituteDatabaseInitializer());

    //Lazy loading
    LazyPrintStudentNames();

    //Linq to Entities
    PrintStudentAndTheirDepartments();

    //Explicit Loading
    PrintStudentNames();

    //Explicit loading with query
    PrintDepartmentAndStudentsDetails();

    //Explicit, Eager and Lazy Loading
    PrintInstituteDetails();

    Console.ReadLine();
}

All of these methods can be called in the Main method as follows:

You can see the definition of InstituteDatabaseInitializer in the attached code as this would not add any value to this discussion. When we run this we get the following output:


Download Code

Sunday, February 12, 2012

Entity Framework Code First - Relationship between Entities II

This is part of the series of discussions about entity framework. In the last post, we touched the basics about relationship between entities. We discussed how the relational database concepts of different relationship types can be mapped to object oriented entities. We are progressively working on an Institute scenario discussing the various entity framework features.

In this post we will be adding on to the previous post by discussing the relationship between entities further. We will discuss how we can define one-to-many relationships. In the previous post we defined a relationship between Departments and Students entities. This relationship was defined such that a student might not belong to a department. If we look at the database table created, we see that there is a foreign key added in the Students table. It is allowing null values so a student can exist without belonging to any department.


In order to change the relationship to one-to-many, we need to specify it when the model is being built. We can do it by overriding OnModelCreating method of InstituteEntities (DbContext). Here we are specifying that it is mandatory for a student to belong to a department. Entity framework would not allow a student to be saved to the database without belonging to a department.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Student>().HasRequired(s => s.StudentDepartment);
}
This would result in generating the Students table as follows:


So the similar Id has been generated to hold foreign key for department but it is now specified as not null which changes the relationship to one-to-many from previous zero-to-many relationship. Basically EF Code First uses conventions for keys, either primary or foreign keys. Just adding a non-nullable primitive key for holding Department table's foreign key would update the table definition to have a non-nullable foreign key. If we keep the name as DepartmentId then based on convention based approach, the run-time would realize that this is to hold foreign key of Department and would make it non-nullable. Let us update Student's entity as follows:
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;

    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; }
        
        //Foreign key of Department
        public int DepartmentId { get; set; }

        public virtual ICollection<Course> StudentCourses { get; set; }
        public virtual Vehicle VehicleDetails { get; set; }
        public virtual Department StudentDepartment { get; set; }
    }
}
Just updating the above code would result in the updated Student's table in database as follows:


Please note that the name of foreign key is updated to be DepartmentId. It has also been updated as non-null. This would stop us from adding student without specifying department information. If we had needed the foreign key to be picked up based on convention but we still needed to keep the relationship as zero-to-many then we could just use a nullable type and framework would take care of that. Let's update DepartmentId as nullable int [int?] in Student table as follows:
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;

    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; }
        
        //Foreign key of Department
        public int? DepartmentId { get; set; }

        public virtual ICollection<Course> StudentCourses { get; set; }
        public virtual Vehicle VehicleDetails { get; set; }
        public virtual Department StudentDepartment { get; set; }
    }
}
This would result in the following Student's table in the database.


If we had used a name for Department's Id which is not based on convention then the framework obviously would not recognize the significance and would treat that field as just entity's property and would just create a column for the field in the database table. Let us update DepartmentId as DepartmentInfoId.
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;

    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; }
        
        //Foreign key of Department
        public int DepartmentInfoId { get; set; }

        public virtual ICollection<Course> StudentCourses { get; set; }
        public virtual Vehicle VehicleDetails { get; set; }
        public virtual Department StudentDepartment { get; set; }
    }
}
Now run the application. You can notice that the Student's table is created as follows:


Since the new key is not based on EF convention, the framework has not recognized it. In order to help the framework, we can specify this in OnModelCreating method of the DbContext as follows:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Student>().HasRequired(s => s.StudentDepartment)
                                  .WithMany(d => d.Students)
                                  .HasForeignKey(s => s.DepartmentInfoId);
}
Now the framework would realize that the DepartmentInfoId should be used to define foreign key relationship between Student and Department.


If we had needed a zero-to-many relationship, we would need to update DepartmentInfoId to allow null values.
//Foreign key of Department
public int? DepartmentInfoId { get; set; }
We also need to update OnModelCreating method in InstituteEntities as follows:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Student>().HasOptional(s => s.StudentDepartment)
                                  .WithMany(d => d.Students)
                                  .HasForeignKey(s => s.DepartmentInfoId);
}
The framework would still use DepartmentInfoId as Foreign key for Department table in Student table. It would just allow null for this allowing zero-to-many relationship.


Please remember that this would only be possible if we define DepartmentInfoId as nullable [int?]. If we just change it as follows then model validation would fail. Let us do that and change Student POCO as follows:
//Foreign key of Department
public int DepartmentInfoId { get; set; }
Now we run the application and see it crashing.


Download Code

Saturday, February 11, 2012

Entity Framework Code First - Relationship between Entities

This is the second post of our discussion about Entity Framework Code First. In this post we will be discussing how we can create relationship between two entities. Keeping to the code first ideology, code first entities would still be based on simple POCO classes. The relationship between entities are used by entity framework libraries to build the model and hence generate database if required.

As an example, we would be developing on top of our previous example. We have simply discussed how to create a simple application with Entity Framework Code First with one simple entity. Let's now expand this example by introducing courses in our institute. Students are assigned to these courses. Any number of students can be assigned to a course. These courses are offered at different campuses of the institute. The locations have physical presence and have a specific name. Since institute's parking space is limited so each student is allowed to register one vehicle. Each student belongs to a certain department.

Based on the above requirements, we can create following entities in our system.

  1. Student
  2. Vehicle
  3. Course
  4. CourseLocation
  5. Department

These are not stand alone entities but the requirements suggest that there are relationships between these entities.

  1. One-to-One: Since a Student is allowed to register only one vehicle, there is one-to-one relationship between the two.
  2. One-to-Many: A Department can enroll any number of students but a student only belongs to a single department. In this post, we will keep it simple by defining a zero-to-many relationship but we will see how we can fix it in the next post.
  3. Many-to-Many: Any number of students can be enrolled in a course. Similarly, a student can be enrolled in multiple courses. Likewise, a course can be offered at multiple locations and a location can host multiple courses.

Entities

Now let us define our entities. You can see that these are POCO based. They would definitely be backed by database objects when the application is running. But for a simple example, like this, we don't need to worry about that. And this is why Code First is great.

Student

namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;

    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; }

        public virtual ICollection<Course> StudentCourses { get; set; }
        public virtual Vehicle VehicleDetails { get; set; }
        public virtual Department StudentDepartment { get; set; }
    }
}

Vehicle

namespace EFCodeFirstDatabaseCreation.Entities
{
    class Vehicle
    {
        public int VehicleId { get; set; }
        public string Year { get; set; }
        public string Make { get; set; }
        public string Model { get; set; }
    }
}
Course
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;

    class Course
    {
        public int CourseId { get; set; }
        public string CourseName { get; set; }
        public ICollection<Student> CourseStudents { get; set; }
        public virtual ICollection<CourseLocation> CourseOfferedAt { get; set; }
    }
}
Department
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;

    class Department
    {
        public int DepartmentId { get; set; }
        public string DepartmentName { get; set; }
        public virtual ICollection<Student> Students { get; set; }
    }
}
CourseLocation
namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;

    class CourseLocation
    {
        public int CourseLocationId { get; set; }
        public string LocationName { get; set; }
        public virtual LocationAddress Address { get; set; }
        public virtual ICollection<Course> CoursesOffered { get; set; }
    }

    [ComplexType]
    class LocationAddress
    {
        public string StreetAddress { get; set; }
        public string Apartment { get; set; }
        public string City { get; set; }
        public string StateProvince { get; set; }
        public string ZipCode { get; set; }
    }
}

Defining InstituteEntities [DbContext]

Now we need to define the DbContext to query these entities from the database. As you can see we don't need to add all the entities details in the DbContext. We only need to add those entities which are to be accessed directly using the DbContext instance. The other entities which have a relationship with these entities would still have a corresponding table in the database. It is just that they would be accessed to their corresponding relationship tables starting from the DbContext type.

namespace EFCodeFirstDatabaseCreation.Entities
{
    using System.Data.Entity;

    class InstituteEntities : DbContext
    {
        public DbSet<Student> Students { get; set; }
        public DbSet<Course> Courses { get; set; }
        public DbSet<Department> Departments { get; set; }       
    }
}

Initializing Entities with Data

Let us initialize these entities with some data. Remember that this would result in actual data inserted in the tables mapped to these entities by Entity Framework.

namespace EFCodeFirstDatabaseCreation
{
    using EFCodeFirstDatabaseCreation.Entities;
    using System.Data.Entity;
    using System.Collections.Generic;

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

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

            Vehicle vehicle = new Vehicle() { VehicleId = 1, Make = "Bugatti", Model = "", Year = "2012" };
            
            Department department1 = 
                new Department() { DepartmentId = 1, DepartmentName = "Computer Systems Engineering", Students = new List<Student>() };
            Department department2 = 
                new Department() { DepartmentId = 2, DepartmentName = "Electrical Engineering", Students = new List<Student>() };

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

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

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

            CourseLocation courseLocation1 =
                new CourseLocation()
                    {
                        LocationName = "Karachi Campus",
                        Address = new LocationAddress() 
                                        {
                                            StreetAddress = "XYZ I.I. Chundrigar Road",
                                            City = "Karachi",
                                            StateProvince = "Sindh",
                                            ZipCode = "YYYYY"
                                        }
                    };

            CourseLocation courseLocation2 =
                new CourseLocation()
                {
                    LocationName = "Manhattan Campus",
                    Address = new LocationAddress()
                    {
                        StreetAddress = "6th Street",
                        City = "New York City",
                        StateProvince = "New York",
                        ZipCode = "ZZZZZ"
                    }
                };

            Course course1 = new Course()
                                    {
                                        CourseName = "Engineering Mechanics",
                                        CourseStudents = new List<Student> { student1, student2 },
                                        CourseOfferedAt = new List<CourseLocation> {courseLocation1, courseLocation2 }
                                    };


            Course course2 = new Course()
                                    {
                                        CourseName = "Fault Tolerence & Reliable System Design",
                                        CourseStudents = new List<Student> { student3, student4 },
                                        CourseOfferedAt = new List<CourseLocation>{courseLocation1}
                                    };

            Student student5 = new Student()
                                    {
                                        FirstName = "Ali",
                                        LastName = "Khan",
                                        GradePointAverage = 3,
                                        IsOutStanding = true
                                    };

            course1.CourseStudents.Add(student5);
            
            department1.Students.Add(student1);
            department1.Students.Add(student2);
            department1.Students.Add(student3);

            department2.Students.Add(student4);
            department2.Students.Add(student5);

            context.Courses.Add(course1);
            context.Courses.Add(course2);
            
            context.Departments.Add(department1);
            context.Departments.Add(department2);

            base.Seed(context);
        }
    }
}

Test Code:

Now let us write some test code to see if the entities are generated as expected. The code below would also test if the data has been inserted in those entities. Here we are setting database initializer for InstituteEntities. Then we are just writing the data to the console testing if the entities are initialized properly.

namespace EFCodeFirstDatabaseCreation
{
    using System.Linq;
    using EFCodeFirstDatabaseCreation.Entities;
    using System.Data.Entity;
    using System;

    class Program
    {
        static void Main(string[] args)
        {
            //Initialize Database entities
            Database.SetInitializer<InstituteEntities>(new InstituteDatabaseInitializer());

            InstituteEntities instituteEntites = new InstituteEntities();
           
            foreach (var course in instituteEntites.Courses
                                        .Include("CourseStudents")
                                        .Include("CourseStudents.VehicleDetails")
                                        .Include("CourseStudents.StudentDepartment")
                                        .Include("CourseOfferedAt"))
            {
                string location = course.CourseOfferedAt == null ? string.Empty :
                    string.Join(", ", course.CourseOfferedAt.Select(l => l.LocationName).ToArray<string>());
                
                Console.WriteLine("***************************");
                Console.WriteLine("Course : {0}, Offered At: {1}", course.CourseName, location);

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

                    Console.WriteLine("   Department : {0}", student.StudentDepartment.DepartmentName);

                    if (student.VehicleDetails != null)
                    {
                        Console.WriteLine("   Vehicle: {0} {1} {2}",
                            student.VehicleDetails.Year, student.VehicleDetails.Make, student.VehicleDetails.Model);
                    }
                }
                
                Console.WriteLine("***************************");
            }

            Console.ReadLine();
        }
    }
}

Database Relationship:

You might be wondering how these relationships are created in the database.

One-to-One & One-to-Many:

These types of relationship result in adding the foreign key on one of these entities. In our case, the relationship between Vehicle and Student is one-to-one. A student is supposed to register only one vehicle in the system. On the other hand, the relationship between Department and Student is One-to-Many as a department could have more than student.

Many-to-Many

This is similar to generating Database from and Entity Relationship Diagram. This results in adding a relationship table in the Database. In our case the relationship between Student & Courses is many-to-many. This would result in generating a new table in database containing primary keys of both the entities. For our case, the name of this table is CourseStudents. Similarly, a course can be offered at multiple locations i.e. the relationship between Course and CourseLocation is also many-to-many. This results in creating CourseLocationCourses table in Database.

Complex Type

A complex type is represented in the database by adding all properties of complex type to the entity itself. By default, the names of these properties are preceded by the name of variant used for ComplexType instance in the entity.

Output:

When we run the project, it runs in the following output.

Download Code: