articles

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

Anonymous User17489 02-Feb-2015

Hi everyone in this article introduces the repository pattern in MVC applications. We are developing an application for a UserDetails entity on which we can perform Create, Read, Update and Delete operations. To keep the article simple and make it easy to understand the repository pattern, we use a single UserDetail entity in the application.

Description:

The repository pattern is intended to create an abstraction layer between the data access layer and the business logic layer of an application. It is a data access pattern that prompts a more loosely coupled approach to data access. We create the data access logic in a separate class, or set of classes called a repository with the responsibility of persisting the application's business model.

Repository Pattern:

Very few authors explain the concept and jump directly over the practical implementation of the pattern. So, first, let us understand what is repository pattern? Why should we use it?

In simple terms, a repository basically works as a mediator between our business logic layer and our data access layer of the application. Sometimes, it would be troublesome to expose the data access mechanism directly to the business logic layer, it may result in redundant code for accessing data for similar entities or it may result in a code that is hard to test or understand. To overcome these kinds of issues, and to write an Interface is driven and test-driven code to access data, we use the Repository Pattern. The repository makes queries to the data source for the data, thereafter maps the data from the data source to a business entity/domain object, finally and persists the changes in the business entity to the data source. According to MSDN, a repository separates the business logic from the interactions with the underlying data source or Web service. The separation between the data and business tiers has three benefits:

  1. It centralizes the data logic or Web service access logic.
  2. It provides a substitution point for the unit tests.
  3. It provides a flexible architecture that can be adapted as the overall design of the application evolves.

When we use Entity Framework, as we did in our last application created, we were calling the Entity Framework class object in the controller class for accessing the entity classes. Now we can say that that system was somewhat a tightly coupled system. To overcome this situation, as we discussed, we’ll implement the Repository Pattern. In Repository, we write our whole business logic of CRUD operations with the help of Entity Framework classes, which will not only result in meaningful test-driven code but will also reduce our controller code of accessing data.

Step 1: Firstly you create a table in the database for data operation

CREATE TABLE UserDetails
(
       Id INT IDENTITY(1,1)PRIMARY KEY,
       Name VARCHAR(100),
       EmailId VARCHAR(150),
       City VARCHAR(100),
       PhoneNo VARCHAR(15),
       PinCode VARCHAR(7)
)
 

Creating Repository:

Creating a Repository is not as tough as it sounds to be, once you implement this on your own, you’ll love it.

Step 2: Open visual studio >> File >> New Project >> ASP.NET MVC 4 Web Application

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

Give the application name and click ok. After click ok open a window and select application type Empty.

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

Now our application is set up successfully.

Step 3: install entity framework from Manage NuGet Packages

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

Step 4: Adding EDM file

For data I am selecting ADO.Net Entity Data Model, you can select several other available options.)

Step5: Create a folder named Repository and add an Interface to that folder named IUserDetailRepository, this interface we derive from the IDisposable type of interface.

We’ll declare methods for CRUD operations on UserDetail entity class over here, you can choose the names of the method as per your choice, but those should be easy to understand and follow.

Like I used in the below code of my interface:

using RepositoryPattern.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace RepositoryPattern.Repository
{
    interface IUserDetailRepository:IDisposable
    {
        IEnumerable<UserDetail> GetAll();
        UserDetail GetById(int id);
        void Add(UserDetail model);
        void Update(UserDetail model);
        void Delete(int id);
        void Save();
    }
}

Step 6: Now add a class UserDetailRepository this class implements the IUserDetailRepository interface, but with the help of Entity Framework. Now here comes the use of our DBContext class MyDBEntities we already have this class in our existing solution, so we don’t have touch this class, simply write our business logic in the interface methods implemented in UserDetailRepository class.

Like I used in the below code of my class which implements the interface:

using RepositoryPattern.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace RepositoryPattern.Repository
{
    public class UserDetailRepository : IUserDetailRepository
    {
        MyDBEntities context;
        public UserDetailRepository(MyDBEntities context)
        {
            this.context = context;
        }
        public IEnumerable<UserDetail> GetAll()
        {
            return this.context.UserDetails.ToList();
        }
        public UserDetail GetById(int id)
        {
            return context.UserDetails.FirstOrDefault(x => x.Id == id);
        }
        public void Add(UserDetail model)
        {
            context.Entry(model).State = System.Data.Entity.EntityState.Added;
        }
        public void Update(UserDetail model)
        {
            context.Entry(model).State = System.Data.Entity.EntityState.Modified;
        }
        public void Delete(int id)
        {
            UserDetail model = context.UserDetails.FirstOrDefault(x => x.Id == id);
            context.Entry(model).State = System.Data.Entity.EntityState.Deleted;
        }
        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);
        }
    }
}

Step 7: Now add HomeController inside the Controller folder and work with Controller.

This is needless to explain how you’ll call repository inside the controller, as you now

know how to treat our controller, but still, let's do it for once.

Go to the controller, declare the IUserDetailRepository reference, and in the constructor initialize the object with UserDetailRepository class, passing MyDBEntities object to the constructor as parameter we defined in UserDetailRepository class.

using RepositoryPattern.Models;

using RepositoryPattern.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace RepositoryPattern.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        UserDetailRepository userRepository;
        public HomeController()
        {
            this.userRepository = new UserDetailRepository(new MyDBEntities());
        }

        public ActionResult Index()
        {
            var test = userRepository.GetAll();
            return View(test);
        }
        public ActionResult Add()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Add(UserDetail model)
        {
            if (ModelState.IsValid)
            {
                userRepository.Add(model);
                userRepository.Save();
            }
            return RedirectToAction("Index");
        }
        public ActionResult Delete(int id)
        {
            this.userRepository.Delete(id);
            userRepository.Save();
            return RedirectToAction("Index");
        }
        public ActionResult Update(int id)
        {
            return View(this.userRepository.GetById(id));
        }
        [HttpPost]
        public ActionResult Update(UserDetail model)
        {
            this.userRepository.Update(model);
            userRepository.Save();
            return RedirectToAction("Index");
        }

    }
}

Step 8: Now add three-view for New User, Update And Index, and download

bootstrap.min.css file for good look and feel.

Index.cshtml:
@model IList<RepositoryPattern.Models.UserDetail>
@{
    ViewBag.Title = "Index";
}
<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<div class="clearfix">&nbsp;</div>
<div class="clearfix">&nbsp;</div>
<div class="container">
    <div class="table-responsive">
        <table class="table table-bordered table-striped">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Email ID</th>
                    <th>City</th>
                    <th>Phone No</th>
                    <th>Pin Code</th>
                    <th>Delete</th>
                    <th>Update</th>
                </tr>
            </thead>
            <tbody>
                @if (Model != null)
                {
                    foreach (var item in Model)
                    {
                    <tr>
                        <td>@item.Id</td>
                        <td>@item.Name</td>
                        <td>@item.EmailId</td>
                        <td>@item.City</td>
                        <td>@item.PhoneNo</td>
                        <td>@item.PinCode</td>
                        <td>@Html.ActionLink("Delete", "Delete", "Home", new { id = @item.Id }, null)</td>                         <td>@Html.ActionLink("Update", "Update", "Home", new { id = @item.Id }, null)</td>                     </tr>
                    }
                }
            </tbody>
        </table>
    </div>
    <div class="clearfix">&nbsp;</div>
    @Html.ActionLink("New user", "Add", "Home")
</div>

 Add.cshtml:

@model RepositoryPattern.Models.UserDetail
@{
    ViewBag.Title = "Add";
}
<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<div class="clearfix">&nbsp;</div>
<div class="clearfix">&nbsp;</div>
<div class="container">
    <div class="table-responsive col-md-6 col-md-offset-3">
        <table class="table table-bordered table-striped">
            <tbody>
                @using (Html.BeginForm("Add", "Home", FormMethod.Post))
                {
                    <tr>
                        <td class="col-md-4">Name</td>
                        <td class="col-md-8">@Html.TextBoxFor(m=>m.Name)</td>
                    </tr>
                    <tr>
                        <td class="col-md-4">Email ID</td>
                        <td class="col-md-8">@Html.TextBoxFor(m=>m.EmailId)</td>
                    </tr>
                    <tr>
                        <td class="col-md-4">City</td>
                        <td class="col-md-8">@Html.TextBoxFor(m=>m.City)</td>
                    </tr>
                    <tr>
                        <td class="col-md-4">Phone No</td>
                        <td class="col-md-8">@Html.TextBoxFor(m=>m.PhoneNo)</td>
                    </tr>
                    <tr>
                        <td class="col-md-4">Pin Code</td>
                        <td class="col-md-8">@Html.TextBoxFor(m=>m.PinCode)</td>
                    </tr>
                    <tr>
                        <td class="text-right" colspan="2"><input type="submit" value="Save" class="btn btn-primary" /></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    <div class="clearfix">&nbsp;</div>
    @Html.ActionLink("Home", "Index", "Home")
</div>

 Update.cshtml: 

@model RepositoryPattern.Models.UserDetail
@{
    ViewBag.Title = "Update";
}

<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<div class="clearfix">&nbsp;</div>
<div class="clearfix">&nbsp;</div>
<div class="container">
    <div class="table-responsive">
        <table class="table table-bordered table-striped">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Email ID</th>
                    <th>City</th>                     <th>Phone No</th>
                    <th>Pin Code</th>
                    <th>Update</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    @using (Html.BeginForm("Update","Home",FormMethod.Post))
                    {
                        <td>@Html.TextBoxFor(m => m.Name)</td>
                        <td>@Html.TextBoxFor(m => m.EmailId)</td>
                        <td>@Html.TextBoxFor(m => m.City)</td>
                        <td>@Html.TextBoxFor(m => m.PhoneNo)</td>
                        <td>@Html.TextBoxFor(m => m.PinCode)</td>
                        <td><input type="submit" value="Update" class="btn btn-primary" /></td>
                    }
                </tr>
            </tbody>
        </table>
    </div>
</div>

 Now run our application and look like this 

Output:

1.    When our table Is empty.

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

2.       When clicking on New user 

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

3.       When clicking on the update link

 

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

And change something in this sample I  have change Name Manoj Pandey and click the update button

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.


4.       When clicking on Delete link In this sample, I have deleted Manoj Pandey record

Crud Operations Using Generic Repository Pattern in ASP.NET MVC 4.

Now we will convert the above Repository to Generic Repository:

Although the above example works great, it has a drawback. It expects you to have a separate repository for each entity in the application.

For example, UserDetailRepository for UserDetail entity, EmployeeRepository for Employee entity and so on.

This can be too much work, especially if all the repositories are doing the same kind of operations (typical CRUD as in our example).

Wouldn't it be nice to create a generic repository that can be used with any entity? Let's attempt to do just that.

Add the following interface to the ASP.NET MVC project:

Now change interface name IUserDetailRepository to IRepository and write below code:

using RepositryPattern.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace RepositryPattern.Repository
{
    interface IRepository<T> : IDisposable where T:class
    {
        IEnumerable<T> GetAll();
        T GetById(object Id);
        void Add(T model);
        void Update(T model);
        void Delete(object id);
        void Save();
    }
}

 The IRepository interface is a generic interface that defines the same set of methods as before.

Notice that this time instead of the UserDetail entity it uses T everywhere. Also notice that GetByID() and Delete() methods now accept object parameter instead of string.

This is necessary because different tables may have different types of primary keys (UserDetails table has a string primary key whereas Employees table has an integer primary key).

Now, add a class to the ASP.NET MVC project that implements an IRepository interface. This class is shown below: 

Now change class name UserDetailRepository to Repository and write below code:

using RepositryPattern.Models;

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace RepositryPattern.Repository
{
    public class Repository<T> : IRepository<T> where T : class
    {
        MyDBEntities context = null;
        private DbSet<T> entities = null;
        public Repository(MyDBEntities context)
        {
            this.context = context;
            entities = context.Set<T>();
        }
        public IEnumerable<T> GetAll()
        {
            return this.entities.ToList();
        }
        public T GetById(object id)
        {
            return this.entities.Find(id);
        }
        public void Add(T model)
        {
            context.Entry(model).State = System.Data.Entity.EntityState.Added;
        }
        public void Update(T model)
        {
            context.Entry(model).State = System.Data.Entity.EntityState.Modified;
        }
        public void Delete(object id)
        {
            T existing = this.entities.Find(id);
            this.entities.Remove(existing);
        }
        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);
        }
    }
}

 The Repository is a generic class and implements IRepository. Notice that since this class uses generic type T you can't access a DbSet as a property of data context.

That's why a generic DbSet variable is declared at the top that points to an appropriate DbSet based on the type of T.

Once Repository is ready you can use it in the Home controller like this:

HomeController and view code are the same above not changes.


Updated 16-May-2020
I am a content writter !

Leave Comment

Comments

Liked By