Introduction
This article will explain the repository design pattern in ASP.NET MVC. We will discuss CRUD (Create, Update, Read and Delete) operations using Repository Design Pattern in ASP.NET MVC. The Repository Design Pattern in C# is one of the most used design patterns in real-time applications.
Nowadays, most of the data-driven applications need to access the data residing in one or more other data sources. The easiest or simplest approach is to write all the data access related code in the main application itself.
Repository Design Pattern in C#
The Repository Design Pattern in C# works as a mediator between the domain and the data mapping layers using a collection-like interface for accessing the domain objects.
In other words, we can say that a Repository Design Pattern acts as a bridge between the rest of the application and the data access logic. That means a repository pattern isolates all the data access code from the rest of the application. The advantage of doing so is that if you need to make any change, then you have to do that only once in one place. Another benefit is that testing your controllers becomes easy because the testing framework needs not run against the actual database access code with a Repository Design Pattern introduced.
Let's see this with a demo application.
Step 1
Open SQL Server and create a database table to perform CRUD.
- CREATE TABLE [dbo].[Employee](
- [Id] [int] IDENTITY(1,1) NOT NULL,
- [FirstName] [nvarchar](50) NULL,
- [LastName] [nvarchar](50) NULL,
- [Age] [int] NULL,
- [Position] [nvarchar](50) NULL,
- [Office] [nvarchar](50) NULL,
- [Salary] [int] NULL,
- CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
- (
- [Id] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
-
- GO
Step 2
Open Visual Studio 2015 or a version of your choice and create a new project.
Step 3
Choose web application project and give the appropriate name to your project.
Step 4
Select "empty template", check on MVC checkbox, and click OK.
Step 5
Right-click the Models folder and add a database model. Add Entity Framework now. For that, right-click on Models folder, select Add, then select New Item.
You will get a window; from there, select Data from the left panel and choose ADO.NET Entity Data Model, give it the name EmployeeModel (this name is not mandatory, you can give any name) and click "Add".
After you click on "Add a window", the wizard will open. Choose EF Designer from the database and click "Next".
After clicking on "Next", a window will appear. Choose New Connection. Another window will appear. Add your server name - if it is local, then enter a dot (.). Choose your database and click "OK".
The connection will be added. If you wish, save the connection name as you want. You can change the name of your connection below. It will save the connection in the web config. Now, click "Next".
After clicking on Next, another window will appear. Choose the database table name as shown in the below screenshot and click "Finish".
Entity Framework gets added and the respective class gets generated under the Models folder.
Employee class
- using System.ComponentModel.DataAnnotations;
-
- namespace MvcRepositoryDesignPattern_Demo.Models
- {
- using System;
- using System.Collections.Generic;
-
- public partial class Employee
- {
- public int Id { get; set; }
-
- [Required(ErrorMessage = "Please enter first name")]
- [Display(Name="First Name")]
- public string FirstName { get; set; }
-
- [Required(ErrorMessage = "Please enter last name")]
- [Display(Name = "Last Name")]
- public string LastName { get; set; }
-
- [Required(ErrorMessage = "Please enter age")]
- public Nullable<int> Age { get; set; }
-
- [Required(ErrorMessage = "Please enter position")]
- public string Position { get; set; }
-
- [Required(ErrorMessage = "Please enter office")]
- public string Office { get; set; }
-
- [Required(ErrorMessage = "Please enter salary")]
- public Nullable<int> Salary { get; set; }
- }
- }
Step 6
Right-click on project >> “Add” a folder >> name it Repositories.
Step 7
Right-click on created Repositories folder and “Add” an interface. Name it as IEmployeeRepository.cs. Write the following code.
- using MvcRepositoryDesignPattern_Demo.Models;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace MvcRepositoryDesignPattern_Demo.Repositories
- {
- public interface IEmployeeRepository
- {
- IEnumerable<Employee> GetEmployees();
- Employee GetEmployeeById(int id);
- void NewEmployee(Employee employee);
- void UpdateEmployee(Employee employee);
- void DeleteEmployee(int id);
- void Save();
- }
- }
Step 8
Similarly, add another class and name it EmployeeRepository.cs. Write the following code in it.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using MvcRepositoryDesignPattern_Demo.Models;
- using System.Data.Entity;
-
- namespace MvcRepositoryDesignPattern_Demo.Repositories
- {
- public class EmployeeRepository : IEmployeeRepository
- {
- private readonly EmployeeContext _dbContext;
-
- public EmployeeRepository()
- {
- _dbContext = new EmployeeContext();
- }
- public EmployeeRepository(EmployeeContext context)
- {
- _dbContext = context;
- }
-
- public IEnumerable<Employee> GetEmployees()
- {
- return _dbContext.Employees.ToList();
- }
-
- public Employee GetEmployeeById(int id)
- {
- return _dbContext.Employees.Find(id);
- }
-
- public void NewEmployee(Employee employee)
- {
- _dbContext.Employees.Add(employee);
- Save();
- }
-
- public void UpdateEmployee(Employee employee)
- {
- _dbContext.Entry(employee).State = EntityState.Modified;
- }
-
- public void DeleteEmployee(int id)
- {
- var employee = _dbContext.Employees.Find(id);
- if (employee != null) _dbContext.Employees.Remove(employee);
- }
-
- public void Save()
- {
- _dbContext.SaveChanges();
- }
-
- private bool _disposed = false;
-
- protected virtual void Dispose(bool disposing)
- {
- if (!this._disposed)
- {
- if (disposing)
- {
- _dbContext.Dispose();
- }
- }
- this._disposed = true;
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
- }
Step 9
Right-click on the Controllers folder and add a new controller.
A window will appear. Choose MVC5 Controller-Empty and click "Add".
After clicking on "Add", another window will appear with DefaultController. Change the name to HomeController and click "Add". The HomeController will be added under the Controllers folder. Don’t change the Controller suffix for all controllers, change only the highlight, and instead of Default, just change Home.
The complete code for HomeController.
- using MvcRepositoryDesignPattern_Demo.Models;
- using MvcRepositoryDesignPattern_Demo.Repositories;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
-
- namespace MvcRepositoryDesignPattern_Demo.Controllers
- {
- public class HomeController : Controller
- {
- private readonly IEmployeeRepository _employeeRepository;
-
- public HomeController()
- {
- _employeeRepository = new EmployeeRepository(new EmployeeContext());
- }
-
- public HomeController(IEmployeeRepository employeeRepository)
- {
- _employeeRepository = employeeRepository;
- }
-
- public ActionResult Index()
- {
- var employee = _employeeRepository.GetEmployees();
- return View(employee);
- }
-
- public ActionResult Details(int id)
- {
- var employee= _employeeRepository.GetEmployeeById(id);
- return View(employee);
- }
-
- public ActionResult Create()
- {
- return View();
- }
-
- [HttpPost]
- [ValidateAntiForgeryToken]
- public ActionResult Create(Employee employee)
- {
- if (ModelState.IsValid)
- {
- _employeeRepository.NewEmployee(employee);
- _employeeRepository.Save();
- return RedirectToAction("Index");
- }
- return View();
- }
-
- [HttpGet]
- public ActionResult Edit(int id)
- {
- var employee = _employeeRepository.GetEmployeeById(id);
- return View(employee);
- }
-
- [HttpPost]
- public ActionResult Edit(Employee employee)
- {
- if (ModelState.IsValid)
- {
- _employeeRepository.UpdateEmployee(employee);
- _employeeRepository.Save();
- return RedirectToAction("Index", "Home");
-
- }
- else
- {
- return View(employee);
- }
- }
-
- [HttpGet]
- public ActionResult Delete(int id)
- {
- var employee=_employeeRepository.GetEmployeeById(id);
- return View(employee);
- }
-
- [HttpPost]
- public ActionResult ConfirmDelete(int id)
- {
- _employeeRepository.DeleteEmployee(id);
- _employeeRepository.Save();
- return RedirectToAction("Index","Home");
- }
- }
- }
Step 10
Right-click on the Index method in HomeController. The "Add View" window will appear with default index name checked (use a Layout page). Click on "Add.
Code for Index View -
- @model IEnumerable<MvcRepositoryDesignPattern_Demo.Models.Employee>
- @{
- ViewBag.Title = "Index";
- }
-
- <h3 class="text-center text-uppercase">List of Employee</h3>
- <p>
- @Html.ActionLink("Create New", "Create","",new {@class="btn btn-primary" })
- </p>
- <table class="table table-bordered">
- <thead>
- <tr>
- <th>@Html.DisplayNameFor(m => m.FirstName)</th>
- <th>@Html.DisplayNameFor(m => m.LastName)</th>
- <th>@Html.DisplayNameFor(m => m.Age)</th>
- <th>@Html.DisplayNameFor(m => m.Position)</th>
- <th>@Html.DisplayNameFor(m => m.Office)</th>
- <th>@Html.DisplayNameFor(m => m.Salary)</th>
- <th>Action(s)</th>
- </tr>
- </thead>
- <tbody>
- @foreach (var emp in Model)
- {
- <tr>
- <td>@emp.FirstName</td>
- <td>@emp.LastName</td>
- <td>@emp.Age</td>
- <td>@emp.Position</td>
- <td>@emp.Office</td>
- <td>@emp.Salary</td>
- <td>
- @Html.ActionLink("Details","Details",new {id=emp.Id },new {@class="btn btn-info"})
- @Html.ActionLink("Edit", "Edit", new { id = emp.Id }, new { @class = "btn btn-primary" })
- @Html.ActionLink("Delete", "Delete", new { id = emp.Id }, new { @class = "btn btn-danger" })
- </td>
- </tr>
- }
- </tbody>
- </table>
Step 11
Right-click on the Details method in HomeController. The "Add View" window will appear with default details name checked (use a Layout page). Click on "Add.
Code for Details View -
- @model MvcRepositoryDesignPattern_Demo.Models.Employee
- @{
- ViewBag.Title = "Details";
- }
-
- <div class="card" style="width:60%; margin:auto;">
- <div class="card-header bg-dark text-white">
- <h5>Employee Details</h5>
- </div>
- <div class="card-body">
- <table class="table table-borderless">
- <tr>
- <td>
- <b>@Html.DisplayNameFor(m => m.FirstName)</b>
- </td>
- <td>@Html.DisplayFor(m => m.FirstName)</td>
- <td>
- <b>@Html.DisplayNameFor(m => m.LastName)</b>
- </td>
- <td>@Html.DisplayFor(m => m.LastName)</td>
- </tr>
- <tr>
- <td>
- <b>@Html.DisplayNameFor(m => m.Age)</b>
- </td>
- <td>@Html.DisplayFor(m => m.Age)</td>
- <td>
- <b>@Html.DisplayNameFor(m => m.Position)</b>
- </td>
- <td>@Html.DisplayFor(m => m.Position)</td>
- </tr>
- <tr>
- <td>
- <b>@Html.DisplayNameFor(m => m.Office)</b>
- </td>
- <td>@Html.DisplayFor(m => m.Office)</td>
- <td>
- <b>@Html.DisplayNameFor(m => m.Salary)</b>
- </td>
- <td>@Html.DisplayFor(m => m.Salary)</td>
- </tr>
- </table>
- <p>
- @Html.ActionLink("Edit", "Edit", new { id = Model.Id },new {@class="btn btn-info"})
- @Html.ActionLink("Back to List", "Index","",new {@class="btn btn-primary"})
- </p>
- </div>
- </div>
Step 12
Right-click the Create method in HomeController. The "Add View" window will appear with default Create name checked (use a Layout page). Click on "Add.
Code for Create View.
- @model MvcRepositoryDesignPattern_Demo.Models.Employee
- @{
- ViewBag.Title = "Create";
- }
-
- <div class="card" style="width:60%; margin:auto;">
- <div class="card-header bg-dark text-white">
- <h5>Create New</h5>
- </div>
- <div class="card-body">
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
-
- <div class="row">
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.FirstName)
- @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
- @Html.ValidationMessageFor(m => m.FirstName)
- </div>
- </div>
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.LastName)
- @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" })
- @Html.ValidationMessageFor(m => m.LastName)
- </div>
- </div>
- </div>
- <div class="row">
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.Age)
- @Html.TextBoxFor(m => m.Age, new { @class = "form-control" })
- @Html.ValidationMessageFor(m => m.Age)
- </div>
- </div>
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.Position)
- @Html.TextBoxFor(m => m.Position, new { @class = "form-control" })
- @Html.ValidationMessageFor(m => m.Position)
- </div>
- </div>
- </div>
- <div class="row">
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.Office)
- @Html.TextBoxFor(m => m.Office, new { @class = "form-control" })
- @Html.ValidationMessageFor(m => m.Office)
- </div>
- </div>
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.Salary)
- @Html.TextBoxFor(m => m.Salary, new { @class = "form-control" })
- @Html.ValidationMessageFor(m => m.Salary)
- </div>
- </div>
- </div>
- <div class="form-group">
- <button type="submit" class="btn btn-primary">Submit</button>
- </div>
- }
- </div>
- </div>
Step 13
Right-click on the Edit method in HomeController. The "Add View" window will appear with the default "Edit" name checked (use a Layout page). Click on "Add.
Code for Edit View.
- @model MvcRepositoryDesignPattern_Demo.Models.Employee
- @{
- ViewBag.Title = "Edit";
- }
-
- <div class="card" style="width:60%; margin:auto;">
- <div class="card-header bg-dark text-white">
- <h3>Edit Employee</h3>
- </div>
- <div class="card-body">
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- @Html.HiddenFor(m => m.Id)
- <div class="row">
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.FirstName)
- @Html.EditorFor(m => m.FirstName, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(m => m.FirstName)
- </div>
- </div>
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.LastName)
- @Html.EditorFor(m => m.LastName, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(m => m.LastName)
- </div>
- </div>
- </div>
- <div class="row">
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.Age)
- @Html.EditorFor(m => m.Age, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(m => m.Age)
- </div>
- </div>
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.Position)
- @Html.EditorFor(m => m.Position, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(m => m.Position)
- </div>
- </div>
- </div>
- <div class="row">
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.Office)
- @Html.EditorFor(m => m.Office, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(m => m.Office)
- </div>
- </div>
- <div class="col-md-6">
- <div class="form-group">
- @Html.LabelFor(m => m.Salary)
- @Html.EditorFor(m => m.Salary, new { htmlAttributes = new { @class = "form-control" } })
- @Html.ValidationMessageFor(m => m.Salary)
- </div>
- </div>
- </div>
- <div class="form-group">
- <button type="submit" class="btn btn-primary">Update</button>
- </div>
- }
- </div>
- </div>
Step 14
Right-click on the Delete method in HomeController. The "Add View" window will appear with default Delete name checked (use a Layout page). Click on "Add.
Code for Delete View.
- @model MvcRepositoryDesignPattern_Demo.Models.Employee
-
- @{
- ViewBag.Title = "Delete";
- }
-
- <h3 class="text-center text-uppercase">Delete Employee Record</h3>
- <div class="card" style="width:50%; margin:auto;">
- <div class="card-header">
- <h3>Are you sure you want to delete this?</h3>
- </div>
- <div class="card-body">
- <div class="row">
- <div class="col-md-2">
-
- </div>
- <div class="col-md-10">
- </div>
-
- </div>
-
- <dl class="dl-horizontal">
- <dt class="col-md-2">
- @Html.DisplayNameFor(model => model.FirstName)
- </dt>
-
- <dd class="col-md-10">
- @Html.DisplayFor(model => model.FirstName)
- </dd>
-
- <dt>
- @Html.DisplayNameFor(model => model.LastName)
- </dt>
-
- <dd>
- @Html.DisplayFor(model => model.LastName)
- </dd>
-
- <dt>
- @Html.DisplayNameFor(model => model.Age)
- </dt>
-
- <dd>
- @Html.DisplayFor(model => model.Age)
- </dd>
-
- <dt>
- @Html.DisplayNameFor(model => model.Position)
- </dt>
-
- <dd>
- @Html.DisplayFor(model => model.Position)
- </dd>
-
- <dt>
- @Html.DisplayNameFor(model => model.Office)
- </dt>
-
- <dd>
- @Html.DisplayFor(model => model.Office)
- </dd>
-
- <dt>
- @Html.DisplayNameFor(model => model.Salary)
- </dt>
-
- <dd>
- @Html.DisplayFor(model => model.Salary)
- </dd>
-
- <dt>
- @Html.DisplayNameFor(model => model.Salary)
- </dt>
-
- <dd>
- @Html.DisplayFor(model => model.Salary)
- </dd>
- </dl>
- @using (Html.BeginForm())
- {
- @Html.AntiForgeryToken()
- <div class="form-actions no-color">
- <input type="submit" value="Delete" class="btn btn-danger" /> |
- @Html.ActionLink("Back to List", "Index")
- </div>
- }
- </div>
- </div>