Generic Repository Pattern in MVC Application Using Entity Framework

In my previous article I explained the Repository Pattern in MVC. Now I will explain the Generic Repository.

Repository Pattern In MVC Application Using Entity Framework

So the question is, when we have a Repository Pattern, then what is this Generic Pattern? What do we need the Generic Pattern for? The following is the answer.

It may be that our database has many tables so we need to create a repository class for each entity type. That simply means that there are many chances for repeating the code. It can be a problematic thing. Suppose we need to update two different entity types as part of the same transactions.

If every entity use a separate database context instance, one might succeed and another can fail. So to avoid this type of situation we have a Generic Repository. It is a way to ensure that all repositories use the same database context (and thus coordinates all the updates) using a unit of work class.

Unit of work is a pattern to handle transactions during data manipulation using the Repository Pattern.

Now we will learn about this by creating a MVC application as in the following:

Open Visual Studio 2010 then go to File -> New -> Project.

new project

internet application

Now create a DAL folder in your application then right-click the DAL Folder then select Add -> ADO.NET Entity Data model.

new dal folder

specify name

choose model contents

connection properties

choose data connection

tables

employee

Now suppose there is more than one entity in your database. Then you need to create an I-Repository and Repository for each and every entity and need to do the same code. To avoid this we will define a generic repository as in the following.

Right-click on the DAL Folder then select Add New Class-> GenericRepositiory.cs.

GenericRepositiory.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using GenericRepositioryPatternInMVC4.Models;  
  6. using System.Linq.Expressions;  
  7. using System.Data;  
  8. using System.Data.Entity;  
  9.   
  10. namespace GenericRepositioryPatternInMVC4.DAL  
  11. {  
  12.     public class GenericRepository<TEntity> where TEntity : class  
  13.     {  
  14.         internal EmployeeManagementEntities context;  
  15.         internal DbSet<TEntity> dbSet;  
  16.   
  17.         public GenericRepository(EmployeeManagementEntities context)  
  18.         {  
  19.             this.context = context;  
  20.             this.dbSet = context.Set<TEntity>();  
  21.         }  
  22.   
  23.         public virtual IEnumerable<TEntity> Get(  
  24.             Expression<Func<TEntity, bool>> filter = null,  
  25.             Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,  
  26.             string includeProperties = "")  
  27.         {  
  28.             IQueryable<TEntity> query = dbSet;  
  29.   
  30.             if (filter != null)  
  31.             {  
  32.                 query = query.Where(filter);  
  33.             }  
  34.   
  35.             foreach (var includeProperty in includeProperties.Split  
  36.                 (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))  
  37.             {  
  38.                 query = query.Include(includeProperty);  
  39.             }  
  40.   
  41.             if (orderBy != null)  
  42.             {  
  43.                 return orderBy(query).ToList();  
  44.             }  
  45.             else  
  46.             {  
  47.                 return query.ToList();  
  48.             }  
  49.         }  
  50.   
  51.         public virtual TEntity GetByID(object id)  
  52.         {  
  53.             return dbSet.Find(id);  
  54.         }  
  55.   
  56.         public virtual void Insert(TEntity entity)  
  57.         {  
  58.             dbSet.Add(entity);  
  59.         }  
  60.   
  61.         public virtual void Delete(object id)  
  62.         {  
  63.             TEntity entityToDelete = dbSet.Find(id);  
  64.             Delete(entityToDelete);  
  65.         }  
  66.   
  67.         public virtual void Delete(TEntity entityToDelete)  
  68.         {  
  69.             if (context.Entry(entityToDelete).State == EntityState.Detached)  
  70.             {  
  71.                 dbSet.Attach(entityToDelete);  
  72.             }  
  73.             dbSet.Remove(entityToDelete);  
  74.         }  
  75.   
  76.         public virtual void Update(TEntity entityToUpdate)  
  77.         {  
  78.             dbSet.Attach(entityToUpdate);  
  79.             context.Entry(entityToUpdate).State = EntityState.Modified;  
  80.         }  
  81.     }  
  82. }  
Now we will define a Unit Of Work. Right-click on the the DAL Folder then seelct Add New Class.

Here we will define all our Repositories like the following.

UnitOfWork.cs

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5.   
  6. namespace GenericRepositioryPatternInMVC4.DAL  
  7. {  
  8.     public class UnitOfWork : IDisposable  
  9.     {  
  10.         private EmployeeManagementEntities context = new EmployeeManagementEntities();  
  11.   
  12.         private GenericRepository<Employee> employeeRepository;  
  13.            
  14.         public GenericRepository<Employee> EmployeeRepository  
  15.         {  
  16.             get  
  17.             {  
  18.                 if (this.employeeRepository == null)  
  19.                 {  
  20.                     this.employeeRepository = new GenericRepository<Employee>(context);  
  21.                 }  
  22.                 return employeeRepository;  
  23.             }  
  24.         }  
  25.          
  26.         public void Save()  
  27.         {  
  28.             context.SaveChanges();  
  29.         }  
  30.   
  31.         private bool disposed = false;  
  32.   
  33.         protected virtual void Dispose(bool disposing)  
  34.         {  
  35.             if (!this.disposed)  
  36.             {  
  37.                 if (disposing)  
  38.                 {  
  39.                     context.Dispose();  
  40.                 }  
  41.             }  
  42.             this.disposed = true;  
  43.         }  
  44.   
  45.         public void Dispose()  
  46.         {  
  47.             Dispose(true);  
  48.             GC.SuppressFinalize(this);  
  49.         }  
  50.     }  
  51. }  

Now add a Controller named Employee:

add controller

controller name

Now EmployeeController is:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. using GenericRepositioryPatternInMVC4.Models;  
  7. using GenericRepositioryPatternInMVC4.DAL;  
  8. using System.Data;  
  9.   
  10. namespace GenericRepositioryPatternInMVC4.Controllers  
  11. {  
  12.     public class EmployeeController : Controller  
  13.     {  
  14.         private UnitOfWork unitOfWork = new UnitOfWork();  
  15.   
  16.         //  
  17.         // GET: /Employee/  
  18.   
  19.         public ViewResult Index()  
  20.         {  
  21.             var employee = unitOfWork.EmployeeRepository.Get();  
  22.             return View(employee.ToList());  
  23.         }  
  24.   
  25.         //  
  26.         // GET: /employee/Details/5  
  27.   
  28.         public ViewResult Details(int id)  
  29.         {  
  30.             Employee employee = unitOfWork.EmployeeRepository.GetByID(id);  
  31.             return View(employee);  
  32.         }  
  33.   
  34.         //  
  35.         // GET: /employee/Create  
  36.   
  37.         public ActionResult Create()  
  38.         {  
  39.             return View();  
  40.         }  
  41.   
  42.         [HttpPost]  
  43.         [ValidateAntiForgeryToken]  
  44.         public ActionResult Create(Employee employee)  
  45.         {  
  46.             try  
  47.             {  
  48.                 if (ModelState.IsValid)  
  49.                 {  
  50.                     unitOfWork.EmployeeRepository.Insert(employee);  
  51.                     unitOfWork.Save();  
  52.                     return RedirectToAction("Index");  
  53.                 }  
  54.             }  
  55.             catch (Exception ex)  
  56.             {  
  57.   
  58.                 ModelState.AddModelError("""Some Error Occurred.");  
  59.             }  
  60.             return View(employee);  
  61.         }  
  62.   
  63.         public ActionResult Edit(int id)  
  64.         {  
  65.             Employee employee = unitOfWork.EmployeeRepository.GetByID(id);  
  66.             return View(employee);  
  67.         }  
  68.   
  69.         [HttpPost]  
  70.         [ValidateAntiForgeryToken]  
  71.         public ActionResult Edit(Employee employee)  
  72.         {  
  73.             try  
  74.             {  
  75.                 if (ModelState.IsValid)  
  76.                 {  
  77.                     unitOfWork.EmployeeRepository.Update(employee);  
  78.                     unitOfWork.Save();  
  79.                     return RedirectToAction("Index");  
  80.                 }  
  81.             }  
  82.             catch (Exception ex)  
  83.             {  
  84.   
  85.                 ModelState.AddModelError("""Some Error Occurred");  
  86.             }  
  87.             return View(employee);  
  88.         }  
  89.   
  90.   
  91.         //  
  92.         // GET: /employee/Delete/5  
  93.   
  94.         public ActionResult Delete(int id)  
  95.         {  
  96.             Employee employee = unitOfWork.EmployeeRepository.GetByID(id);  
  97.             return View(employee);  
  98.         }  
  99.   
  100.         //  
  101.         // POST: /employee/Delete/5  
  102.   
  103.         [HttpPost, ActionName("Delete")]  
  104.         [ValidateAntiForgeryToken]  
  105.         public ActionResult DeleteConfirmed(int id)  
  106.         {  
  107.             Employee employee = unitOfWork.EmployeeRepository.GetByID(id);  
  108.             unitOfWork.EmployeeRepository.Delete(id);  
  109.             unitOfWork.Save();  
  110.             return RedirectToAction("Index");  
  111.         }  
  112.   
  113.         protected override void Dispose(bool disposing)  
  114.         {  
  115.             unitOfWork.Dispose();  
  116.             base.Dispose(disposing);  
  117.         }  
  118.     }  
  119. }  
Now the following are the Views.

Index.cshtml

  1. @model IEnumerable<GenericRepositioryPatternInMVC4.DAL.Employee>  
  2. @{  
  3.     ViewBag.Title = "Generic Repository Pattern In MVC4";  
  4. }   
  5. <p>  
  6.     @Html.ActionLink("Add New Employee", "Create")  
  7. </p>  
  8. <table>  
  9.     <tr>  
  10.         <th>  
  11.             @Html.DisplayNameFor(model => model.Emp_ID)  
  12.         </th>  
  13.         <th>  
  14.             @Html.DisplayNameFor(model => model.Name)  
  15.         </th>  
  16.         <th>  
  17.             @Html.DisplayNameFor(model => model.Email)  
  18.         </th>  
  19.         <th>  
  20.             @Html.DisplayNameFor(model => model.Designation)  
  21.         </th>  
  22.         <th>  
  23.             @Html.DisplayNameFor(model => model.City)  
  24.         </th>  
  25.         <th>  
  26.             @Html.DisplayNameFor(model => model.State)  
  27.         </th>  
  28.         <th>  
  29.             @Html.DisplayNameFor(model => model.Country)  
  30.         </th>  
  31.         <th></th>  
  32.     </tr>  
  33. @foreach (var item in Model) 
  34. {  
  35.     <tr>  
  36.         <td>  
  37.             @Html.DisplayFor(modelItem => item.Emp_ID)  
  38.         </td>  
  39.         <td>  
  40.             @Html.DisplayFor(modelItem => item.Name)  
  41.         </td>  
  42.         <td>  
  43.             @Html.DisplayFor(modelItem => item.Email)  
  44.         </td>  
  45.         <td>  
  46.             @Html.DisplayFor(modelItem => item.Designation)  
  47.         </td>  
  48.         <td>  
  49.             @Html.DisplayFor(modelItem => item.City)  
  50.         </td>  
  51.         <td>  
  52.             @Html.DisplayFor(modelItem => item.State)  
  53.         </td>  
  54.         <td>  
  55.             @Html.DisplayFor(modelItem => item.Country)  
  56.         </td>  
  57.         <td>  
  58.             @Html.ActionLink("Edit", "Edit", new { id=item.Emp_ID  }) |  
  59.             @Html.ActionLink("Details", "Details", new { id=item.Emp_ID  }) |  
  60.             @Html.ActionLink("Delete", "Delete", new {  id=item.Emp_ID  })  
  61.         </td>  
  62.     </tr>  
  63. }  
  64. </table>  
Details.cshtml
  1. @model GenericRepositioryPatternInMVC4.DAL.Employee  
  2. <table>  
  3.     <tr>  
  4.         <td>@Html.DisplayNameFor(model => model.Emp_ID)</td>  
  5.         <td>@Html.DisplayFor(model => model.Emp_ID)</td>  
  6.     </tr>  
  7.     <tr>  
  8.         <td>@Html.DisplayNameFor(model => model.Name)</td>  
  9.         <td>@Html.DisplayFor(model => model.Name)</td>  
  10.     </tr>  
  11.     <tr>  
  12.         <td>@Html.DisplayNameFor(model => model.Email)</td>  
  13.         <td>@Html.DisplayFor(model => model.Email)</td>  
  14.     </tr>  
  15.     <tr>  
  16.         <td>@Html.DisplayNameFor(model => model.Designation)</td>  
  17.         <td>@Html.DisplayFor(model => model.Designation)</td>  
  18.     </tr>  
  19.     <tr>  
  20.         <td>@Html.DisplayNameFor(model => model.City)</td>  
  21.         <td>@Html.DisplayFor(model => model.City)</td>  
  22.     </tr>  
  23.     <tr>  
  24.         <td>@Html.DisplayNameFor(model => model.State)</td>  
  25.         <td>@Html.DisplayFor(model => model.State)</td>  
  26.     </tr>  
  27.     <tr>  
  28.         <td>@Html.DisplayNameFor(model => model.Country)</td>  
  29.         <td>@Html.DisplayFor(model => model.Country)</td>  
  30.     </tr>  
  31.     <tr style="padding: 25px;">  
  32.         <td></td>  
  33.         <td>@Html.ActionLink("Edit", "Edit", new { id = Model.Emp_ID }) |  
  34.     @Html.ActionLink("Back to List", "Index")</td>  
  35.     </tr>  
  36. </table>  
Create.cshtml
  1. @model GenericRepositioryPatternInMVC4.DAL.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.Emp_ID)  
  17.         </div>  
  18.         <div class="editor-field">  
  19.             @Html.EditorFor(model => model.Emp_ID)  
  20.             @Html.ValidationMessageFor(model => model.Emp_ID)  
  21.         </div>  
  22.   
  23.         <div class="editor-label">  
  24.             @Html.LabelFor(model => model.Name)  
  25.         </div>  
  26.         <div class="editor-field">  
  27.             @Html.EditorFor(model => model.Name)  
  28.             @Html.ValidationMessageFor(model => model.Name)  
  29.         </div>  
  30.   
  31.         <div class="editor-label">  
  32.             @Html.LabelFor(model => model.Email)  
  33.         </div>  
  34.         <div class="editor-field">  
  35.             @Html.EditorFor(model => model.Email)  
  36.             @Html.ValidationMessageFor(model => model.Email)  
  37.         </div>  
  38.   
  39.         <div class="editor-label">  
  40.             @Html.LabelFor(model => model.Designation)  
  41.         </div>  
  42.         <div class="editor-field">  
  43.             @Html.EditorFor(model => model.Designation)  
  44.             @Html.ValidationMessageFor(model => model.Designation)  
  45.         </div>  
  46.   
  47.         <div class="editor-label">  
  48.             @Html.LabelFor(model => model.City)  
  49.         </div>  
  50.         <div class="editor-field">  
  51.             @Html.EditorFor(model => model.City)  
  52.             @Html.ValidationMessageFor(model => model.City)  
  53.         </div>  
  54.   
  55.         <div class="editor-label">  
  56.             @Html.LabelFor(model => model.State)  
  57.         </div>  
  58.         <div class="editor-field">  
  59.             @Html.EditorFor(model => model.State)  
  60.             @Html.ValidationMessageFor(model => model.State)  
  61.         </div>  
  62.   
  63.         <div class="editor-label">  
  64.             @Html.LabelFor(model => model.Country)  
  65.         </div>  
  66.         <div class="editor-field">  
  67.             @Html.EditorFor(model => model.Country)  
  68.             @Html.ValidationMessageFor(model => model.Country)  
  69.         </div>  
  70.   
  71.         <p>  
  72.             <input type="submit" value="Create" />  
  73.         </p>  
  74.     </fieldset>  
  75. }  
  76.   
  77. <div>  
  78.     @Html.ActionLink("Back to List", "Index")  
  79. </div>  
Edit.cshtml
  1. @model GenericRepositioryPatternInMVC4.DAL.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.Emp_ID)  
  17.         </div>  
  18.         <div class="editor-field">  
  19.             @Html.EditorFor(model => model.Emp_ID)  
  20.             @Html.ValidationMessageFor(model => model.Emp_ID)  
  21.         </div>  
  22.   
  23.         <div class="editor-label">  
  24.             @Html.LabelFor(model => model.Name)  
  25.         </div>  
  26.         <div class="editor-field">  
  27.             @Html.EditorFor(model => model.Name)  
  28.             @Html.ValidationMessageFor(model => model.Name)  
  29.         </div>  
  30.   
  31.         <div class="editor-label">  
  32.             @Html.LabelFor(model => model.Email)  
  33.         </div>  
  34.         <div class="editor-field">  
  35.             @Html.EditorFor(model => model.Email)  
  36.             @Html.ValidationMessageFor(model => model.Email)  
  37.         </div>  
  38.   
  39.         <div class="editor-label">  
  40.             @Html.LabelFor(model => model.Designation)  
  41.         </div>  
  42.         <div class="editor-field">  
  43.             @Html.EditorFor(model => model.Designation)  
  44.             @Html.ValidationMessageFor(model => model.Designation)  
  45.         </div>  
  46.   
  47.         <div class="editor-label">  
  48.             @Html.LabelFor(model => model.City)  
  49.         </div>  
  50.         <div class="editor-field">  
  51.             @Html.EditorFor(model => model.City)  
  52.             @Html.ValidationMessageFor(model => model.City)  
  53.         </div>  
  54.   
  55.         <div class="editor-label">  
  56.             @Html.LabelFor(model => model.State)  
  57.         </div>  
  58.         <div class="editor-field">  
  59.             @Html.EditorFor(model => model.State)  
  60.             @Html.ValidationMessageFor(model => model.State)  
  61.         </div>  
  62.   
  63.         <div class="editor-label">  
  64.             @Html.LabelFor(model => model.Country)  
  65.         </div>  
  66.         <div class="editor-field">  
  67.             @Html.EditorFor(model => model.Country)  
  68.             @Html.ValidationMessageFor(model => model.Country)  
  69.         </div>  
  70.   
  71.         <p>  
  72.             <input type="submit" value="Save" />  
  73.         </p>  
  74.     </fieldset>  
  75. }  
  76.   
  77. <div>  
  78.     @Html.ActionLink("Back to List", "Index")  
  79. </div>  
Delete.cshtml
  1. @model GenericRepositioryPatternInMVC4.DAL.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.    
  34. </table>  
  35.   
  36. @using (Html.BeginForm())   
  37. {  
  38.      @Html.AntiForgeryToken()  
  39.     <p>  
  40.         <input type="submit" value="Delete" /> |  
  41.         @Html.ActionLink("Back to List", "Index")  
  42.     </p>  
  43. }  

 Now run the application.

run app

Add a new Employee.

emp id

Click on Details.

details

Click on Edit.

edit

Click on Delete.

delete

Here you can see in the controller we are calling UnitOfWork and have mapped our repository with a Generic Repository. So there is no need to write code again and again.

Enjoy Generic Repositories.