Repository Pattern In MVC Application Using Entity Framework

This article explains the Repository Pattern in MVC applications using the Entity Framework.

First we need to understand what the Repository Pattern is. See the following Image.

MVC Application without Repository Pattern



MVC Application with Repository pattern



The Repository Pattern separates the data access logic and maps it to the entities in the business logic.

Now we will see the Repository Pattern with a sample application.

Open Visual Studio 2012 and go to "File" -> "New" -> "Project...".





Now Add a ADO.NET Entity Data Model to your application. Right-click on the project in the Solution Explorer then select Add -> ADO.NET Entity Data Model.















Now add a new folder to your application named DAL.

Right-click on the DAL Folder then select Add Interface -> IEmployeeRepository.cs.



Now my IEmployeeRepository.cs is as in the following:

  1. using System;    
  2. using System.Collections.Generic;    
  3. using System.Linq;    
  4. using System.Web;    
  5. using RepositoryPatternInMVCWithEntityFramework.Models;    
  6. using System.Data;    
  7.     
  8. namespace RepositoryPatternInMVCWithEntityFramework.DAL    
  9. {    
  10.    public class EmployeeRepository : IEmployeeRepository, IDisposable    
  11.    {    
  12.      private EmployeeManagementEntities context;    
  13.     
  14.      public EmployeeRepository(EmployeeManagementEntities context)    
  15.      {    
  16.        this.context = context;    
  17.      }    
  18.     
  19.      public IEnumerable<Employee> GetAllEmployee()    
  20.      {    
  21.         return context.Employee.ToList();    
  22.      }    
  23.     
  24.      public Employee GetEmployeeByID(int id)    
  25.      {    
  26.        return context.Employee.Find(id);    
  27.      }    
  28.     
  29.      public void InsertEmployee(Employee emp)    
  30.      {    
  31.        context.Employee.Add(emp);    
  32.      }    
  33.     
  34.      public void DeleteEmployee(int emp_ID)    
  35.      {    
  36.         Employee emp = context.Employee.Find(emp_ID);    
  37.         context.Employee.Remove(emp);    
  38.      }    
  39.     
  40.      public void UpdateEmployee(Employee emp)    
  41.      {    
  42.         context.Entry(emp).State = EntityState.Modified;    
  43.      }    
  44.     
  45.      public void Save()    
  46.      {    
  47.         context.SaveChanges();    
  48.      }    
  49.     
  50.      private bool disposed = false;    
  51.     
  52.      protected virtual void Dispose(bool disposing)    
  53.      {    
  54.         if (!this.disposed)    
  55.         {    
  56.            if (disposing)    
  57.            {    
  58.               context.Dispose();    
  59.            }    
  60.         }    
  61.         this.disposed = true;    
  62.      }    
  63.     
  64.      public void Dispose()    
  65.      {    
  66.          Dispose(true);    
  67.          GC.SuppressFinalize(this);    
  68.      }    
  69.    }    
  70. }    

 

Now right-click on the Controller folder in your project in the Solution Explorer then select Add New Empty Controller -> EmployeeController and provide the following code.

EmployeeController 
  1. using RepositoryPatternInMVCWithEntityFramework.DAL;    
  2. using System;    
  3. using System.Collections.Generic;    
  4. using System.Linq;    
  5. using System.Web;    
  6. using System.Web.Mvc;    
  7. using RepositoryPatternInMVCWithEntityFramework.Models;    
  8. using PagedList;    
  9. using System.Data;    
  10.     
  11. namespace RepositoryPatternInMVCWithEntityFramework.Controllers    
  12. {    
  13.    public class EmployeeController : Controller    
  14.    {    
  15.        private IEmployeeRepository employeeRepository;    
  16.     
  17.        public EmployeeController()    
  18.        {    
  19.           this.employeeRepository = new EmployeeRepository(new EmployeeManagementEntities());    
  20.        }    
  21.     
  22.        public EmployeeController(IEmployeeRepository employeeRepository)    
  23.        {    
  24.           this.employeeRepository = employeeRepository;    
  25.        }    
  26.     
  27.        public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)    
  28.        {    
  29.           ViewBag.CurrentSort = sortOrder;    
  30.           ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Emp_ID" : "";    
  31.           if (searchString != null)    
  32.           {    
  33.              page = 1;    
  34.           }    
  35.           else    
  36.           {    
  37.              searchString = currentFilter;    
  38.           }    
  39.           ViewBag.CurrentFilter = searchString;    
  40.     
  41.           var employees = from s in employeeRepository.GetAllEmployee()    
  42.           select s;    
  43.           if (!String.IsNullOrEmpty(searchString))    
  44.           {    
  45.              employees = employees.Where(s => s.Name.ToUpper().Contains(searchString.ToUpper())    
  46.              || s.Name.ToUpper().Contains(searchString.ToUpper()));    
  47.           }    
  48.           switch (sortOrder)    
  49.           {    
  50.              case "Emp ID":    
  51.                 employees = employees.OrderByDescending(s => s.Emp_ID);    
  52.              break;    
  53.              case "Name":    
  54.                 employees = employees.OrderBy(s => s.Name);    
  55.              break;    
  56.              case "State":    
  57.                 employees = employees.OrderByDescending(s => s.State);    
  58.              break;    
  59.              case "Country":    
  60.                 employees = employees.OrderByDescending(s => s.Country);    
  61.              break;    
  62.              default:    
  63.                 employees = employees.OrderBy(s => s.Emp_ID);       
  64.              break;    
  65.           }    
  66.     
  67.           int pageSize = 5;    
  68.           int pageNumber = (page ?? 1);    
  69.           return View(employees.ToPagedList(pageNumber, pageSize));    
  70.       }    
  71.     
  72.      // GET: /Employee/Details/5    
  73.     
  74.     public ViewResult Details(int id)    
  75.     {    
  76.        Employee emp = employeeRepository.GetEmployeeByID(id);    
  77.        return View(emp);    
  78.     }    
  79.        
  80.     // GET: /Employee/Create    
  81.     
  82.     public ActionResult Create()    
  83.     {    
  84.       return View();    
  85.     }    
  86.       
  87.     // POST: /Employee/Create    
  88.     
  89.     [HttpPost]    
  90.     [ValidateAntiForgeryToken]    
  91.     public ActionResult Create(    
  92.     [Bind(Include = "Name, Email, Designation,City, State, Country")]    
  93.     Employee emp)    
  94.     {    
  95.        try    
  96.        {    
  97.          if (ModelState.IsValid)    
  98.          {    
  99.             employeeRepository.InsertEmployee(emp);    
  100.             employeeRepository.Save();    
  101.             return RedirectToAction("Index");    
  102.          }    
  103.        }    
  104.       catch (Exception ex)    
  105.       {    
  106.          ModelState.AddModelError(string.Empty, "Some Error Occured.");    
  107.       }    
  108.       return View(emp);    
  109.    }    
  110.       
  111.    // GET: /Employee/Edit/5    
  112.     
  113.    public ActionResult Edit(int id)    
  114.    {    
  115.       Employee emp = employeeRepository.GetEmployeeByID(id);    
  116.       return View(emp);    
  117.    }    
  118.       
  119.    // POST: /Employee/Edit/5    
  120.     
  121.    [HttpPost]    
  122.    [ValidateAntiForgeryToken]    
  123.    public ActionResult Edit(Employee emp)    
  124.    {    
  125.       try    
  126.       {    
  127.          if (ModelState.IsValid)    
  128.             {    
  129.                employeeRepository.UpdateEmployee(emp);    
  130.                employeeRepository.Save();    
  131.                return RedirectToAction("Index");    
  132.             }    
  133.       }    
  134.       catch (Exception ex)    
  135.       {    
  136.          ModelState.AddModelError(string.Empty, "Some error Occured.");    
  137.       }    
  138.       return View(emp);    
  139.    }    
  140.       
  141.    // GET: /employee/Delete/5    
  142.     
  143.    public ActionResult Delete(bool? saveChangesError = falseint id = 0)    
  144.    {    
  145.       if (saveChangesError.GetValueOrDefault())    
  146.          {    
  147.             ViewBag.ErrorMessage = "Some Error Occured.";    
  148.          }    
  149.          Employee emp = employeeRepository.GetEmployeeByID(id);    
  150.          return View(emp);    
  151.    }    
  152.       
  153.    // POST: /Employee/Delete/5    
  154.     
  155.    [HttpPost]    
  156.    [ValidateAntiForgeryToken]    
  157.    public ActionResult Delete(int id)    
  158.    {    
  159.       try    
  160.       {    
  161.          Employee emp = employeeRepository.GetEmployeeByID(id);    
  162.          employeeRepository.DeleteEmployee(id);    
  163.          employeeRepository.Save();    
  164.       }    
  165.       catch (Exception ex)    
  166.          {    
  167.             return RedirectToAction("Delete"new { id = id, saveChangesError = true });    
  168.          }    
  169.          return RedirectToAction("Index");    
  170.    }    
  171.     
  172.    protected override void Dispose(bool disposing)    
  173.    {    
  174.       employeeRepository.Dispose();    
  175.       base.Dispose(disposing);    
  176.    }    
  177.     
  178.   }    
  179. }   
Now add a View. Right-click on the Index Action Method and select Add view.

Index.cshtml
 
  1. @using PagedList.Mvc;    
  2.     
  3. @model PagedList.IPagedList<RepositoryPatternInMVCWithEntityFramework.Employee>    
  4. <link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />    
  5.     
  6. @{     
  7. ViewBag.Title = "Employee Management System";     
  8. }    
  9.     
  10. <h2>Employee Management System</h2>    
  11.     
  12.     
  13. @using (Html.BeginForm("Index", "Employee", FormMethod.Get))    
  14. {     
  15.    <p style="background-color:red; color:white; font-size:16pt; padding:10px;">    
  16.    Search Employee By Name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)    
  17.    <input type="submit" value="Search" />    
  18.    @Html.ActionLink("Add New Employee", "Create")    
  19.    </p>     
  20. }    
  21. <table style="background-color:white;">    
  22.   <tr>    
  23.      <th></th>    
  24.      <th style="width: 100px;">    
  25.         @Html.ActionLink("Emp ID", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })    
  26.      </th>    
  27.      <th>    
  28.         @Html.ActionLink("Name", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })    
  29.      </th>    
  30.        <th>Email    
  31.      </th>    
  32.      <th>Designation    
  33.      </th>    
  34.        <th>City    
  35.      </th>    
  36.      <th>    
  37.         @Html.ActionLink("State", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })    
  38.      </th>    
  39.      <th>    
  40.         @Html.ActionLink("Country", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })    
  41.      </th>    
  42.      <th style="width: 150px;"></th>    
  43.   </tr>    
  44.     
  45.   @foreach (var item in Model)    
  46.   {     
  47.     <tr>    
  48.     <td></td>    
  49.     <td>    
  50.        @Html.DisplayFor(modelItem => item.Emp_ID)    
  51.     </td>    
  52.     <td style="width:130px;">    
  53.        @Html.DisplayFor(modelItem => item.Name)    
  54.     </td>    
  55.     <td>    
  56.        @Html.DisplayFor(modelItem => item.Email)    
  57.     </td>    
  58.     <td style="width:140px;">    
  59.        @Html.DisplayFor(modelItem => item.Designation)    
  60.     </td>    
  61.     <td style="width:120px;">    
  62.        @Html.DisplayFor(modelItem => item.City)    
  63.     </td>    
  64.     <td style="width:120px;">    
  65.        @Html.DisplayFor(modelItem => item.State)    
  66.     </td>    
  67.     <td>    
  68.        @Html.DisplayFor(modelItem => item.Country)    
  69.     </td>    
  70.     <td style="width:270px;">    
  71.        @Html.ActionLink("Edit", "Edit", new { id = item.Emp_ID }) |     
  72.        @Html.ActionLink("Details", "Details", new { id = item.Emp_ID }) |     
  73.        @Html.ActionLink("Delete", "Delete", new { id = item.Emp_ID })    
  74.     </td>    
  75.   </tr>     
  76.  }    
  77.     
  78. </table>    
  79. <br />    
  80. <div style="background-color:orange; padding-left:15px; padding-top:10px;">    
  81.    Showing Records @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount    
  82.     @Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort,currentFilter = ViewBag.CurrentFilter }))    
  83. </div>    
Here I am using PagedList. You can add the reference of PagedList by right-clicking on the project in the Solution Explorer and selecting Manage NuGet Packages.





Now add a Detail View by right-clicking on the Details Action method. (Make it Strongly Typed View with class Employee and Scaffold template Details.)

Details.cshtml
  1. @model RepositoryPatternInMVCWithEntityFramework.Employee  
  2.   
  3. <h2>Employee Details</h2>  
  4.   
  5. <table>  
  6. <tr>  
  7. <td>@Html.DisplayNameFor(model => model.Emp_ID)</td>  
  8. <td>@Html.DisplayFor(model => model.Emp_ID)</td>  
  9. </tr>  
  10. <tr>  
  11. <td>@Html.DisplayNameFor(model => model.Name)</td>  
  12. <td>@Html.DisplayFor(model => model.Name)</td>  
  13. </tr>  
  14. <tr>  
  15. <td>@Html.DisplayNameFor(model => model.Email)</td>  
  16. <td>@Html.DisplayFor(model => model.Email)</td>  
  17. </tr>  
  18. <tr>  
  19. <td>@Html.DisplayNameFor(model => model.Designation)</td>  
  20. <td>@Html.DisplayFor(model => model.Designation)</td>  
  21. </tr>  
  22. <tr>  
  23. <td>@Html.DisplayNameFor(model => model.City)</td>  
  24. <td>@Html.DisplayFor(model => model.City)</td>  
  25. </tr>  
  26. <tr>  
  27. <td>@Html.DisplayNameFor(model => model.State)</td>  
  28. <td>@Html.DisplayFor(model => model.State)</td>  
  29. </tr>  
  30. <tr>  
  31. <td>@Html.DisplayNameFor(model => model.Country)</td>  
  32. <td>@Html.DisplayFor(model => model.Country)</td>  
  33. </tr>  
  34. <tr style="background-color: orange; padding: 25px;">  
  35. <td></td>  
  36. <td>@Html.ActionLink("Edit", "Edit", new { id = Model.Emp_ID }) |  
  37. @Html.ActionLink("Back to List", "Index")</td>  
  38.   
  39. </tr>  
  40. </table>  
Now create a View by right-clicking on the Create Action Method.

Create.cshtml
  1. @model RepositoryPatternInMVCWithEntityFramework.Employee  
  2.   
  3. <script src="~/Scripts/jquery-1.7.1.min.js"></script>  
  4. <script src="~/Scripts/jquery.validate.min.js"></script>  
  5. <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>  
  6.   
  7. @using (Html.BeginForm())  
  8. {  
  9.    @Html.AntiForgeryToken()  
  10.    @Html.ValidationSummary(true)  
  11.   
  12.    <fieldset>  
  13.    <legend>Employee</legend>  
  14.   
  15.    <div class="editor-label">  
  16.       @Html.LabelFor(model => model.Name)  
  17.    </div>  
  18.    <div class="editor-field">  
  19.       @Html.EditorFor(model => model.Name)  
  20.       @Html.ValidationMessageFor(model => model.Name)  
  21.    </div>  
  22.   
  23.    <div class="editor-label">  
  24.       @Html.LabelFor(model => model.Email)  
  25.    </div>  
  26.    <div class="editor-field">  
  27.       @Html.EditorFor(model => model.Email)  
  28.       @Html.ValidationMessageFor(model => model.Email)  
  29.    </div>  
  30.   
  31.    <div class="editor-label">  
  32.       @Html.LabelFor(model => model.Designation)  
  33.    </div>  
  34.    <div class="editor-field">  
  35.       @Html.EditorFor(model => model.Designation)  
  36.       @Html.ValidationMessageFor(model => model.Designation)  
  37.    </div>  
  38.   
  39.    <div class="editor-label">  
  40.       @Html.LabelFor(model => model.City)  
  41.    </div>  
  42.    <div class="editor-field">  
  43.       @Html.EditorFor(model => model.City)  
  44.       @Html.ValidationMessageFor(model => model.City)  
  45.    </div>  
  46.   
  47.    <div class="editor-label">  
  48.       @Html.LabelFor(model => model.State)  
  49.    </div>  
  50.    <div class="editor-field">  
  51.       @Html.EditorFor(model => model.State)  
  52.       @Html.ValidationMessageFor(model => model.State)  
  53.    </div>  
  54.   
  55.    <div class="editor-label">  
  56.       @Html.LabelFor(model => model.Country)  
  57.    </div>  
  58.    <div class="editor-field">  
  59.       @Html.EditorFor(model => model.Country)  
  60.       @Html.ValidationMessageFor(model => model.Country)  
  61.    </div>  
  62.   
  63.    <p>  
  64.    <input type="submit" value="Create" />  
  65.    </p>  
  66.    </fieldset>  
  67. }  
  68.   
  69. <div>  
  70.    @Html.ActionLink("Back to List", "Index")  
  71. </div>  
Now add an Edit View by right-clicking on the Edit Action Method.

Edit.cshtml
  1. @model RepositoryPatternInMVCWithEntityFramework.Employee    
  2.     
  3. <script src="~/Scripts/jquery-1.7.1.min.js"></script>    
  4. <script src="~/Scripts/jquery.validate.min.js"></script>    
  5. <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>    
  6. <h2>Edit Employee information</h2>    
  7.     
  8. @using (Html.BeginForm())    
  9. {    
  10.   @Html.AntiForgeryToken()    
  11.     
  12.   @Html.ValidationSummary(true)    
  13.     
  14.   <table>    
  15.    <tr>    
  16.    <td>@Html.LabelFor(model => model.Emp_ID)</td>    
  17.    <td>    
  18.        @Html.EditorFor(model => model.Emp_ID, new { disabled = "disabled", @readonly = "readonly" })    
  19.     
  20.        @Html.ValidationMessageFor(model => model.Emp_ID)</td>    
  21.    </tr>    
  22.     
  23.    <tr>    
  24.    <td>@Html.LabelFor(model => model.Name)    
  25.    </td>    
  26.    <td>@Html.EditorFor(model => model.Name)    
  27.        @Html.ValidationMessageFor(model => model.Name)</td>    
  28.    </tr>    
  29.     
  30.    <tr>    
  31.    <td>@Html.LabelFor(model => model.Email)</td>    
  32.    <td>    
  33.       @Html.EditorFor(model => model.Email)    
  34.       @Html.ValidationMessageFor(model => model.Email)</td>    
  35.    </tr>    
  36.    <tr>    
  37.    <td>@Html.LabelFor(model => model.Designation)</td>    
  38.    <td>    
  39.        @Html.EditorFor(model => model.Designation)    
  40.        @Html.ValidationMessageFor(model => model.Designation)    
  41.    </td>    
  42.    </tr>    
  43.    <tr>    
  44.    <td>@Html.LabelFor(model => model.City)</td>    
  45.    <td>    
  46.       @Html.EditorFor(model => model.City)    
  47.       @Html.ValidationMessageFor(model => model.City)</td>    
  48.    </tr>    
  49.    <tr>    
  50.    <td>@Html.LabelFor(model => model.State)</td>    
  51.    <td>@Html.EditorFor(model => model.State)    
  52.        @Html.ValidationMessageFor(model => model.State)</td>    
  53.    </tr>    
  54.    <tr>    
  55.    <td>@Html.LabelFor(model => model.Country)</td>    
  56.    <td>    
  57.        @Html.EditorFor(model => model.Country)    
  58.        @Html.ValidationMessageFor(model => model.Country)</td>    
  59.    </tr>    
  60.    <tr style="background-color: orange; padding: 25px;">    
  61.    <td></td>    
  62.    <td>    
  63.    <input type="submit" value="Save" />    
  64.        @Html.ActionLink("Back to List", "Index")    
  65.    </td>    
  66.    </tr>    
  67.   </table>     
  68. }    
Now add a Delete View by right-clicking on the Delete Action Method.

Delete.cshtml
  1. @model RepositoryPatternInMVCWithEntityFramework.Employee    
  2.     
  3. <h3>Are you sure you want to delete this?</h3>    
  4. <table>    
  5.   <tr>    
  6.   <td>@Html.DisplayNameFor(model => model.Emp_ID)</td>    
  7.   <td>@Html.DisplayFor(model => model.Emp_ID)</td>    
  8.   </tr>    
  9.   <tr>    
  10.   <td>@Html.DisplayNameFor(model => model.Name)</td>    
  11.   <td>@Html.DisplayFor(model => model.Name)</td>    
  12.   </tr>    
  13.   <tr>    
  14.   <td>@Html.DisplayNameFor(model => model.Email)</td>    
  15.   <td>@Html.DisplayFor(model => model.Email)</td>    
  16.   </tr>    
  17.   <tr>    
  18.   <td>@Html.DisplayNameFor(model => model.Designation)</td>    
  19.   <td>@Html.DisplayFor(model => model.Designation)</td>    
  20.   </tr>    
  21.   <tr>    
  22.   <td>@Html.DisplayNameFor(model => model.City)</td>    
  23.   <td>@Html.DisplayFor(model => model.City)</td>    
  24.   </tr>    
  25.   <tr>    
  26.   <td>@Html.DisplayNameFor(model => model.State)</td>    
  27.   <td>@Html.DisplayFor(model => model.State)</td>    
  28.   </tr>    
  29.   <tr>    
  30.   <td>@Html.DisplayNameFor(model => model.Country)</td>    
  31.   <td>@Html.DisplayFor(model => model.Country)</td>    
  32.   </tr>    
  33. </table>    
  34.   
  35. @using (Html.BeginForm())    
  36. {    
  37.   @Html.AntiForgeryToken()    
  38.     
  39.   <table>    
  40.     <tr style="background-color: orange; padding: 25px;">    
  41.     <td></td>    
  42.     <td>    
  43.     <input type="submit" value="Delete" />    
  44.     
  45.     @Html.ActionLink("Back to List", "Index")    
  46.     </td>    
  47.     
  48.     </tr>    
  49.   </table>     
  50. }   
Now run the application.

Showing All Records with Paging and Sorting.


Now go to page 3 .


Now do a search.


Now click on Add New Employer.


Now click on any of the records Edit button.


Now click on Details.


Now click on the Delete option.


To perform CRUD operations you will see that we are not calling the DB method directly here. We are using the Repository Pattern.

For this application my Employee Table in design mode is:



The following is the script of my table:
  1. CREATE TABLE [dbo].[Employee](  
  2. [Emp_ID] [int] IDENTITY(1,1) NOT NULL,  
  3. [Name] [varchar](50) NULL,  
  4. [Email] [varchar](500) NULL,  
  5. [Designation] [varchar](50) NULL,  
  6. [City] [varchar](50) NULL,  
  7. [State] [varchar](50) NULL,  
  8. [Country] [varchar](50) NULL,  
  9. CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED   
  10. (  
  11.    [Emp_ID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
  12.    ON [PRIMARY]) ON [PRIMARY]  
  13.   
  14. GO  
  15.   
  16. SET ANSI_PADDING OFF  
  17. GO  
The following is the data in my table:



Enjoy programming.

Next I will write about the Generic Repository Pattern.