Saturday, December 29, 2018

.NET - Code First Approach in Entity Framework


Objective:

The objective of this tutorial is to explain the code first approach that Microsoft’s Entity Framework provides.  We’ll go step by step to explore the code first approach via which we can access database and data using entity framework in our application.

Pre-requisites:
Ensure that the following softwares are already installed:
1) Visual Studio
2) .NET Framework (version 4.6 or higher)
3) SQL Server
4) SQL Server Management Studio

Entity Framework:
  • Microsoft Entity Framework is an ORM (Object-relational mapping). 
  • Being an ORM,  Entity Framework is a data access framework provided by Microsoft that helps to establish a relation between objects and data structure in the application. 
  • It is built over traditional ADO.NET and acts as a wrapper over ADO.NET and is an enhancement over ADO.NET that provides the data access in a more automated way, thereby, reducing a developer’s effort to struggle with connections, data readers, or datasets.
  • It is an abstraction over all those and is more powerful with the offerings it makes. A developer can have more control over what data he needs, in which form and how much.
  • A developer having no database development background can leverage Entity framework along with LINQ capabilities to write an optimized query to perform DB operations

Entity Framework Approaches:

It is very common to know the three approaches that Microsoft Entity Framework provides. The three approaches are as follows:

Model First,
Database First, and
Code First

Model First:
  • The Model-First approach says that we have a model with all kinds of entities and relations/associations using which we can generate a database that will eventually have entities and properties converted into database tables and the columns and associations and relations would be converted into foreign keys respectively
Database First:
  • The Database-First approach says that we already have an existing database and we need to access that database in our application. 
  • We can create an entity data model along with its relationship directly from the database with just a few clicks and start accessing the database from our code. 
  • All the entities, i.e., classes, would be generated by EF that could be used in the application's data access layer to participate in DB operation queries.
Code First:
  • The Code-First approach is the recommended approach with EF, especially when you are starting the development of an application from scratch. 
  • You can define the POCO classes in advance and their relationships and envision how your database structure and data model may look like by just defining the structure in the code. 
  • Entity Framework, at last, will take all the responsibility to generate a database for you for your POCO classes and for the data model and will take care of transactions, history, and migrations.
In this tutorial, we are going to look at the Code First approach.

Code First Example:

1. Open Visual Studio, click File --> New --> Project

2.  Select Console App (.NET Framework) and enter name EF_CF (or some name of your preference) and hit OK button. 


3. This will give you Program.cs and a Main() method inside that.

4. We’ll create our model classes now, i.e., POCO (Plain Old CLR Object) classes. Let’s say we have to create an application where there would be database operations for an employee and an employee would be allocated to some department. So, A department can have multiple employees and an employee will have only one department. So, we’ll create the first two entities, Employee, and Add a new class to the project named Employee and add two simple properties to it i.e. EmployeeId and EmployeeName.





5. Similarly, add a new class named Department and add properties DepartmentId, DepartmentName, and DepartmentDescription as shown below.


6. Since an employee belongs to one department, each employee would have a related department to it, so add a new property named DepartmentId to the Employee class.


7. Now, it is time to add EntityFramework to our project. Open the Package Manager console, select the default project (EF_CF) as your current console application, and install the Entity Framework using the following command:
 Install-Package EntityFramework



8. Add a new class named CodeFirstContext to the project which inherits from DbContext class of namespace System.Data.Entity as shown in the following image. Now add two DbSet properties named Employees and Departments as shown in the following.


Both DbContext and DbSet are required in creating and dealing with database operations, and make us far abstracted, providing ease of use to us.

When we are working with DbContext, we are in real working with entity sets. DbSet represents a typed entity set that is used to perform create, read, update, and delete operations. We are not creating DbSet objects and using them independently. DbSet can be only used with DbContext.

9. Let’s try to make our implementation a more abstract and instead of accessing dbContext directly from the controller, let’s abstract it in a class named DataAccessHelper. This class will act as a helper class for all our database operations. So, add a new class named DataAccessHelper to the project.

10. Create a read-only instance of the DB context class and add few methods like FetchEmployees() to get employees details, FetchDepartments() to fetch department details. One method each to add employee and add a department. You can add more methods to your will like the update and delete operations. For now, we’ll stick to these four methods.


The code may look like as shown below,

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace EF_CF  
  8. {  
  9.     public class DataAccessHelper  
  10.     {  
  11.         readonly CodeFirstContext _dbContext = new CodeFirstContext();  
  12.   
  13.         public List<Employee> FetchEmployees()  
  14.         {  
  15.             return _dbContext.Employees.ToList();  
  16.         }  
  17.   
  18.         public List<Department> FetchDepartments()  
  19.         {  
  20.             return _dbContext.Departments.ToList();  
  21.         }  
  22.   
  23.         public int AddEmployee(Employee employee)  
  24.         {  
  25.             _dbContext.Employees.Add(employee);  
  26.             _dbContext.SaveChanges();  
  27.             return employee.EmployeeId;  
  28.         }  
  29.   
  30.         public int AddDepartment(Department department)  
  31.         {  
  32.             _dbContext.Departments.Add(department);  
  33.             _dbContext.SaveChanges();  
  34.             return department.DepartmentId;  
  35.         }  
  36.     }  
  37. }  

11. Let’s add the concept of navigation property now. Navigation properties are those properties of the class through which one can access related entities via the Entity Framework while fetching data. So while fetching Employee data we may need to fetch the details of its related Departments and while fetching Department data we may need to fetch the details of associated employees with that. Navigation properties are added as virtual properties in the entity. So, in Employee class, add a property for Departments returning a single Department entity and make it virtual. Similarly, in Department class, add a property named Employees returning the collection of Employee entity and make that virtual too.


Following is the code for the Employee and the Department model,

Employee.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace EF_CF  
  8. {  
  9.     public class Employee  
  10.     {  
  11.         public int EmployeeId { get; set; }  
  12.         public string EmployeeName { get; set; }  
  13.         public int DepartmentId { get; set; }  
  14.   
  15.         public virtual Department Departments { get; set; }  
  16.     }  
  17. }  

Department.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Security.Policy;  
  5. using System.Text;  
  6. using System.Threading.Tasks;  
  7.   
  8. namespace EF_CF  
  9. {  
  10.     public class Department  
  11.     {  
  12.         public int DepartmentId { get; set; }  
  13.         public string DepartmentName { get; set; }  
  14.         public string DepartmentDescription { get; set; }  
  15.   
  16.         public virtual ICollection<Employee> Employees { get; set; }  
  17.     }  
  18.  

12. Let’s write some code to perform database operations with our code. So, in the Main() method of Program.cs class add the following sample test code,

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace EF_CF  
  8. {  
  9.     class Program  
  10.     {  
  11.         static void Main(string[] args)  
  12.         {  
  13.             Department department = new Department  
  14.             {  
  15.                 DepartmentName = "Technology",  
  16.                 Employees = new List<Employee>  
  17.                 {  
  18.                     new Employee() {EmployeeName = "Jack"},  
  19.                     new Employee() {EmployeeName = "Kim"},  
  20.                     new Employee() {EmployeeName = "Shen"}  
  21.                 }  
  22.             };  
  23.             DataAccessHelper dbHelper = new DataAccessHelper();  
  24.             dbHelper.AddDepartment(department);  
  25.             var addedDepartment = dbHelper.FetchDepartments().FirstOrDefault();  
  26.             if (addedDepartment != null)  
  27.             {  
  28.                 Console.WriteLine("Department Name is: " + addedDepartment.DepartmentName + Environment.NewLine);  
  29.                 Console.WriteLine("Department Employees are: " + Environment.NewLine);  
  30.   
  31.                 foreach (var addedDepartmentEmployee in addedDepartment.Employees)  
  32.                 {  
  33.                     Console.WriteLine(addedDepartmentEmployee.EmployeeName + Environment.NewLine);  
  34.                 }  
  35.   
  36.                 Console.ReadLine();  
  37.             }  
  38.         }  
  39.     }  
  40. }  
In the above code of Main() method, we are trying to create an object of Department class and add a list of Employees to the Employees property of that class. Create an instance of the dbHelper class and invoke the method AddDepartment, passing the department entity object to that method to add the new department.

Just after adding the department, we are fetching the newly added department and just to make sure that the department and its related employees got added successfully to the database. So, we’ll fetch the departments and on the console, print the department name and its related employees. But how will all this be done, we do not have a database yet.

13. Not to worry, let’s see how we can make sure that we get the DB created from our code. First like we saw earlier, our context class name should be the same as our connection string name or vice versa. So, add a connection string having the same name as DB context class in the App.config file as shown below.


<connectionStrings>
    <add name="CodeFirstContext" 
         connectionString="data source=.\SQLEXPRESS;initial catalog=codefirstdb;integrated security=SSPI"
         providerName="System.Data.SqlClient"/>
  </connectionStrings>


Job done! Entity Framework will take care of the rest of the pending work of creating a database. We just run the application and now, DB context class is first used to perform a DB operation, we get our database created.

14. Run the application (with F5 command). Now go to the database server and see we got the database created with the same name that we supplied in the connection string. We have Departments and Employees table and a table named __MigrationHistory to track the history of code first migrations performed on this database.


We see that we also got one Department added in the database having the name ”Technology” that we used in the code.

And, got our employee's table filled with three rows having three employees with department id 1 i.e. the id of the newly added department. And so our code first approach worked as well.


When console window appears we see the details of the department and added employees in that window, so our fetch operations also work fine.


That's all I want to cover. Hope this tutorial was useful.

1 comment: