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.
Now create a DAL folder in your application then right-click the DAL Folder then select Add -> ADO.NET Entity Data model.
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
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using GenericRepositioryPatternInMVC4.Models;
- using System.Linq.Expressions;
- using System.Data;
- using System.Data.Entity;
-
- namespace GenericRepositioryPatternInMVC4.DAL
- {
- public class GenericRepository<TEntity> where TEntity : class
- {
- internal EmployeeManagementEntities context;
- internal DbSet<TEntity> dbSet;
-
- public GenericRepository(EmployeeManagementEntities context)
- {
- this.context = context;
- this.dbSet = context.Set<TEntity>();
- }
-
- public virtual IEnumerable<TEntity> Get(
- Expression<Func<TEntity, bool>> filter = null,
- Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
- string includeProperties = "")
- {
- IQueryable<TEntity> query = dbSet;
-
- if (filter != null)
- {
- query = query.Where(filter);
- }
-
- foreach (var includeProperty in includeProperties.Split
- (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
- {
- query = query.Include(includeProperty);
- }
-
- if (orderBy != null)
- {
- return orderBy(query).ToList();
- }
- else
- {
- return query.ToList();
- }
- }
-
- public virtual TEntity GetByID(object id)
- {
- return dbSet.Find(id);
- }
-
- public virtual void Insert(TEntity entity)
- {
- dbSet.Add(entity);
- }
-
- public virtual void Delete(object id)
- {
- TEntity entityToDelete = dbSet.Find(id);
- Delete(entityToDelete);
- }
-
- public virtual void Delete(TEntity entityToDelete)
- {
- if (context.Entry(entityToDelete).State == EntityState.Detached)
- {
- dbSet.Attach(entityToDelete);
- }
- dbSet.Remove(entityToDelete);
- }
-
- public virtual void Update(TEntity entityToUpdate)
- {
- dbSet.Attach(entityToUpdate);
- context.Entry(entityToUpdate).State = EntityState.Modified;
- }
- }
- }
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
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
-
- namespace GenericRepositioryPatternInMVC4.DAL
- {
- public class UnitOfWork : IDisposable
- {
- private EmployeeManagementEntities context = new EmployeeManagementEntities();
-
- private GenericRepository<Employee> employeeRepository;
-
- public GenericRepository<Employee> EmployeeRepository
- {
- get
- {
- if (this.employeeRepository == null)
- {
- this.employeeRepository = new GenericRepository<Employee>(context);
- }
- return employeeRepository;
- }
- }
-
- public void Save()
- {
- context.SaveChanges();
- }
-
- private bool disposed = false;
-
- protected virtual void Dispose(bool disposing)
- {
- if (!this.disposed)
- {
- if (disposing)
- {
- context.Dispose();
- }
- }
- this.disposed = true;
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
- }
Now add a Controller named Employee:
Now EmployeeController is:
Now the following are the Views.
Index.cshtml
- @model IEnumerable<GenericRepositioryPatternInMVC4.DAL.Employee>
- @{
- ViewBag.Title = "Generic Repository Pattern In MVC4";
- }
- <p>
- @Html.ActionLink("Add New Employee", "Create")
- </p>
- <table>
- <tr>
- <th>
- @Html.DisplayNameFor(model => model.Emp_ID)
- </th>
- <th>
- @Html.DisplayNameFor(model => model.Name)
- </th>
- <th>
- @Html.DisplayNameFor(model => model.Email)
- </th>
- <th>
- @Html.DisplayNameFor(model => model.Designation)
- </th>
- <th>
- @Html.DisplayNameFor(model => model.City)
- </th>
- <th>
- @Html.DisplayNameFor(model => model.State)
- </th>
- <th>
- @Html.DisplayNameFor(model => model.Country)
- </th>
- <th></th>
- </tr>
- @foreach (var item in Model)
- {
- <tr>
- <td>
- @Html.DisplayFor(modelItem => item.Emp_ID)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.Name)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.Email)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.Designation)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.City)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.State)
- </td>
- <td>
- @Html.DisplayFor(modelItem => item.Country)
- </td>
- <td>
- @Html.ActionLink("Edit", "Edit", new { id=item.Emp_ID }) |
- @Html.ActionLink("Details", "Details", new { id=item.Emp_ID }) |
- @Html.ActionLink("Delete", "Delete", new { id=item.Emp_ID })
- </td>
- </tr>
- }
- </table>
Details.cshtml
- @model GenericRepositioryPatternInMVC4.DAL.Employee
- <table>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Emp_ID)</td>
- <td>@Html.DisplayFor(model => model.Emp_ID)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Name)</td>
- <td>@Html.DisplayFor(model => model.Name)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Email)</td>
- <td>@Html.DisplayFor(model => model.Email)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Designation)</td>
- <td>@Html.DisplayFor(model => model.Designation)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.City)</td>
- <td>@Html.DisplayFor(model => model.City)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.State)</td>
- <td>@Html.DisplayFor(model => model.State)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Country)</td>
- <td>@Html.DisplayFor(model => model.Country)</td>
- </tr>
- <tr style="padding: 25px;">
- <td></td>
- <td>@Html.ActionLink("Edit", "Edit", new { id = Model.Emp_ID }) |
- @Html.ActionLink("Back to List", "Index")</td>
- </tr>
- </table>
Create.cshtml
- @model GenericRepositioryPatternInMVC4.DAL.Employee
-
- <script src="~/Scripts/jquery-1.7.1.min.js"></script>
- <script src="~/Scripts/jquery.validate.min.js"></script>
- <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
-
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- @Html.ValidationSummary(true)
-
- <fieldset>
- <legend>Employee</legend>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Emp_ID)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Emp_ID)
- @Html.ValidationMessageFor(model => model.Emp_ID)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Name)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Name)
- @Html.ValidationMessageFor(model => model.Name)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Email)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Email)
- @Html.ValidationMessageFor(model => model.Email)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Designation)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Designation)
- @Html.ValidationMessageFor(model => model.Designation)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.City)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.City)
- @Html.ValidationMessageFor(model => model.City)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.State)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.State)
- @Html.ValidationMessageFor(model => model.State)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Country)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Country)
- @Html.ValidationMessageFor(model => model.Country)
- </div>
-
- <p>
- <input type="submit" value="Create" />
- </p>
- </fieldset>
- }
-
- <div>
- @Html.ActionLink("Back to List", "Index")
- </div>
Edit.cshtml
- @model GenericRepositioryPatternInMVC4.DAL.Employee
-
- <script src="~/Scripts/jquery-1.7.1.min.js"></script>
- <script src="~/Scripts/jquery.validate.min.js"></script>
- <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
-
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- @Html.ValidationSummary(true)
-
- <fieldset>
- <legend>Employee</legend>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Emp_ID)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Emp_ID)
- @Html.ValidationMessageFor(model => model.Emp_ID)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Name)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Name)
- @Html.ValidationMessageFor(model => model.Name)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Email)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Email)
- @Html.ValidationMessageFor(model => model.Email)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Designation)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Designation)
- @Html.ValidationMessageFor(model => model.Designation)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.City)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.City)
- @Html.ValidationMessageFor(model => model.City)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.State)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.State)
- @Html.ValidationMessageFor(model => model.State)
- </div>
-
- <div class="editor-label">
- @Html.LabelFor(model => model.Country)
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Country)
- @Html.ValidationMessageFor(model => model.Country)
- </div>
-
- <p>
- <input type="submit" value="Save" />
- </p>
- </fieldset>
- }
-
- <div>
- @Html.ActionLink("Back to List", "Index")
- </div>
Delete.cshtml
- @model GenericRepositioryPatternInMVC4.DAL.Employee
-
- <h3>Are you sure you want to delete this?</h3>
- <table>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Emp_ID)</td>
- <td>@Html.DisplayFor(model => model.Emp_ID)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Name)</td>
- <td>@Html.DisplayFor(model => model.Name)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Email)</td>
- <td>@Html.DisplayFor(model => model.Email)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Designation)</td>
- <td>@Html.DisplayFor(model => model.Designation)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.City)</td>
- <td>@Html.DisplayFor(model => model.City)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.State)</td>
- <td>@Html.DisplayFor(model => model.State)</td>
- </tr>
- <tr>
- <td>@Html.DisplayNameFor(model => model.Country)</td>
- <td>@Html.DisplayFor(model => model.Country)</td>
- </tr>
-
- </table>
-
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- <p>
- <input type="submit" value="Delete" /> |
- @Html.ActionLink("Back to List", "Index")
- </p>
- }
Now run the application.
Add a new Employee.
Click on Details.
Click on Edit.
Click on 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.