Repository Design Pattern in MVC Architecture With Entity Framework

In this example we will first implement a sample application using pure MVC architecture and then we will see how to improve our code standards by implementing the repository design pattern.

The MVC framework is one of the common design patterns in modern web applications. It provides complete separation of concerns. But even MVC is not a silver bullet of all problems. On top of MVC we can implement various design patterns to solve the specific problem.

In this example we will first implement a sample application using pure MVC architecture and then we will see how to improve our code standards by implementing the repository design pattern. So, let's start with one example.

I will suggest you to create one MVC application. Let's create the table at first then we will set up the Entity Framework in the application. Here is the table stricture.

table

We have added the Entity Framework file (.edmx) file and the model is like this.

Framework file

Now let's implement a Company controller and implement CRUD operations. Have a look, we have messed up the database operations within the controller. Now if you decide to change it, how will you implement your data access layer? Right now, the Contact Manager application uses the Microsoft Entity Framework to access the database. However, you might decide to migrate to a new or alternative data access technology such as ADO.NET Data Services or NHibernate. However, because the data access code is not isolated from the controller code, there is no way to modify the data access code in your application without modifying other code that is not directly related to data access. Have a look at the following example.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6.   
  7. namespace MVC.Controllers  
  8. {  
  9.     public class CompanyController : Controller  
  10.     {  
  11.         efDBEntities _db = null;  
  12.         public CompanyController()  
  13.         {  
  14.             _db = new efDBEntities();  
  15.         }  
  16.   
  17.         //Read All company Information  
  18.         public string Index()  
  19.         {  
  20.             var comapny = _db.company.ToList();  
  21.             return view(comapny);  
  22.         }  
  23.   
  24.         //Create new company  
  25.         public ActionResult Create(company comp)  
  26.         {  
  27.             var InsertedCompany =  _db.company.Add(comp);  
  28.             _db.SaveChanges();  
  29.             return RedirectToAction("Index");  
  30.         }  
  31.           
  32.         //Update Exhisting company  
  33.           
  34.         public ActionResult Update( company comp)  
  35.         {  
  36.             var company = _db.company.Where(f => f.cid == comp.cid).FirstOrDefault();  
  37.             if (company != null)  
  38.             {  
  39.                 company.company_name = comp.company_name;  
  40.                 _db.SaveChanges();  
  41.                 return RedirectToAction("Index");  
  42.             }  
  43.             throw new ArgumentException();  
  44.         }             
  45.         public ActionResult Delete(Int32 ? Id)  
  46.         {  
  47.             var company = _db.company.Where(f => f.cid == 1).FirstOrDefault();  
  48.             if (company != null)  
  49.             {  
  50.                 _db.Entry(company).State = System.Data.EntityState.Deleted;  
  51.                 _db.SaveChanges();  
  52.                 return RedirectToAction("Index");  
  53.             }  
  54.             throw new ArgumentException();  
  55.         }  
  56.     }  

Ok, we understad the problem; how to solve it? The solution is the Repository Design Pattern, we will totally isolate the DB operation part into a different class and we will consume the service (yes, let's think of the class as a service class) into our actual controller class.
For that, at first we will create an interface and create a repository for CRUD operations, then we will implement the interface within the concrete class.

So, the following is the Interface implementation.

  1. public interface ICompany  
  2. {  
  3.       Boolean Create(company Company);  
  4.       company Read(int Id);  
  5.       IEnumerable<company> Read();  
  6.       Boolean Update(Int32 Id, company Company);  
  7.       Boolean Delete(int Id);  

There are five functions within this Interface that we will implement in a class shortly. Here, we have implemented an ICompany interface within a “CompanyRepositary” class. Have a look at the following example.

Repository class for CRUD operation

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5.   
  6. namespace MVC.Models  
  7. {  
  8.     public class CompanyRepositary : ICompany  
  9.     {  
  10.         efDBEntities _db = new efDBEntities();  
  11.         public Boolean Create(company Company)  
  12.         {  
  13.             if (Company != null)  
  14.             {  
  15.                 //Insert data in Batabase  
  16.                 using (var comp = new efDBEntities())  
  17.                 {  
  18.                     comp.company.Add(Company);  
  19.                     comp.SaveChanges();  
  20.                     return true;  
  21.                 }  
  22.             }  
  23.             throw new ArgumentException();  
  24.         }  
  25.         public company Read(Int32 Id)  
  26.         {  
  27.             if (Id > 0)  
  28.             {  
  29.                 //read company information  
  30.                 return _db.company.Where(f => f.cid == Id).FirstOrDefault();  
  31.             }  
  32.             throw new ArgumentException();  
  33.         }  
  34.         public IEnumerable<company> Read()  
  35.         {  
  36.             //Read All company information  
  37.             return _db.company.ToList();  
  38.         }  
  39.   
  40.         public Boolean Update(Int32 Id, company Company)  
  41.         {  
  42.             var comp = _db.company.Where(f => f.cid == Id).FirstOrDefault();  
  43.             if (comp != null)  
  44.             {  
  45.                 comp.company_name = Company.company_name;  
  46.                 _db.SaveChanges();  
  47.                 return true;  
  48.             }  
  49.             throw new ArgumentException();  
  50.         }  
  51.         public Boolean Delete(int Id)  
  52.         {  
  53.             var comp = _db.company.Where(f => f.cid == Id).FirstOrDefault();  
  54.             if (comp != null)  
  55.             {  
  56.                 return true;  
  57.             }  
  58.             throw new ArgumentException();  
  59.         }  
  60.   
  61.     }  

We will now consume the repository service within our actual controller class. Here is the controller implementation. Now, have a look that, we have totally isolated the DB operation from our controller class. So that, now the Company controller is de-coupled in nature and we have injected a dependency through the controller.

Implementation of Company repository in controller

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. using MVC.Models;  
  7.   
  8. namespace MVC.Controllers  
  9. {  
  10.     public class CompanyController : Controller  
  11.     {  
  12.         ICompany _comp = null;  
  13.  //Default Constructor  
  14.         public CompanyController() : this(new CompanyRepositary()) { }  
  15.         public CompanyController(ICompany tmpCompany)  
  16.         {  
  17.             _comp = tmpCompany;  
  18.         }  
  19.   
  20.         //Read all company information  
  21.         public ActionResult Index()  
  22.         {  
  23.             return View(_comp.Read());  
  24.         }  
  25.   
  26.         //Create new company  
  27.         [AcceptVerbs(HttpVerbs.Post)]  
  28.         public ActionResult Create([Bind(Exclude="Id")] company comp)  
  29.         {  
  30.                 if (_comp.Create(comp))  
  31.                 {  
  32.                     return RedirectToAction("Index");  
  33.                 }  
  34.                 else  
  35.                 {  
  36.                     return View();  
  37.                 }  
  38.         }  
  39.   
  40.         //Update exhisting company  
  41.         [AcceptVerbs(HttpVerbs.Put)]  
  42.         public ActionResult Update(Int32 Id, company comp)  
  43.         {  
  44.                 if (_comp.Update(Id, comp))  
  45.                 {  
  46.                     return RedirectToAction("Index");  
  47.                 }  
  48.                 else  
  49.                 {  
  50.                     return View();  
  51.                 }  
  52.         }  
  53.   
  54.         //Delete company  
  55.         [AcceptVerbs(HttpVerbs.Delete)]  
  56.         public ActionResult Delete(Int32 Id)  
  57.         {  
  58.             if (_comp.Delete(Id))  
  59.             {  
  60.                 return RedirectToAction("Index");  
  61.             }  
  62.             else  
  63.             {  
  64.                 return View();  
  65.             }  
  66.         }  
  67.   
  68.     }  

The great advantage in this de-coupled architecture is unit testing. If we create one mock repository class and inject it in a controller then we can avoid execution of the DB part at the time of unit testing. I am interested in implementing and showing it in my next article. So, please follow my next article here.