Generic Repository Pattern in C#

Generic Repository Pattern in C#

In this article, I am going to discuss the Generic Repository Pattern in c# with an example. Here, in this article, we are going to implement the generic repository pattern using an ASP.NET MVC application with Entity Framework. Please read our last article where we discussed the Basic Repository Pattern with an example before proceeding to this article as we are going to work with the same example.

As we already discussed, in Basic Repository (Non-Generic Repository), you need to create separate repositories for each and every entity present in your application. For example, if you have three entities such as Employee, Product, and Customer, and then you need to create three repositories such as EmployeeRepository, ProductRepository, and CustomerRepository.

This is actually boring and repeating work, especially if all the repositories are going to do the same kind of work (i.e. typically database CRUD operations) and this is against the DRY (Don’t Repeat Yourself) principle as you are repeating the same code again and again in each repository.

To solve the above problem Generic Repository Pattern comes into the picture. Please have a look at the below diagram.

generic repository pattern in ASP.NET MVC

Creating a Generic Repository:

A Generic Repository Pattern in C# typically does at least five operations are as follows

  1. Selecting all records from a table
  2. Selecting a single record based on its primary key
  3. Insert
  4. Update
  5. Delete

However, the above list is not fixed. You may have more or fewer methods in your generic repository. For the simplicity of this demo, let’s assume our Generic Repository going to perform the above Five Operations.

To implement a Generic Repository in C#, first, we need to create an interface let say IGenericRepository interface with the above five methods and then we need to create a class let say GenericRepository which will implement the IGenericRepository interface

Adding GenericRepository Folder in your project.

To do so, right-click on the Project => Add => New Folder and then Rename the folder name as GenericRepository

Now add an Interface within the GenericRepository folder with the name IGenericRepository.cs and then copy and paste the following code.

IGenericRepository.cs
namespace RepositoryUsingEFinMVC.GenericRepository
{
    public interface IGenericRepository<T> where T : class
    {
        IEnumerable<T> GetAll();
        T GetById(object id);
        void Insert(T obj);
        void Update(T obj);
        void Delete(object id);
        void Save();
    }
}

The IGenericRepository interface is a generic interface that defines the same set of five methods that we created in the IEmployeeRepository interface of our previous article. Notice that instead of the Employee entity, now we are using T everywhere. Also notice that GetById() and Delete() methods now accept object parameter instead of integer parameter. This is necessary because different tables may have different types of primary keys (Customers table has a string primary key whereas Employees table has an integer primary key).

Implement IGenericRepository

Add a class file with the name GenericRepository within the GenericRepository Folder and then implement the IGenericRepository interface as shown below.

GenericRepository.cs

namespace RepositoryUsingEFinMVC.GenericRepository
{
    public class GenericRepository<T> : IGenericRepository<T> where T : class
    {
        private EmployeeDBContext _context = null;
        private DbSet<T> table = null;

        public GenericRepository()
        {
            this._context = new EmployeeDBContext();
            table = _context.Set<T>();
        }

        public GenericRepository(EmployeeDBContext _context)
        {
            this._context = _context;
            table = _context.Set<T>();
        }

        public IEnumerable<T> GetAll()
        {
            return table.ToList();
        }

        public T GetById(object id)
        {
            return table.Find(id);
        }

        public void Insert(T obj)
        {
            table.Add(obj);
        }

        public void Update(T obj)
        {
            table.Attach(obj);
            _context.Entry(obj).State = EntityState.Modified;
        }

        public void Delete(object id)
        {
            T existing = table.Find(id);
            table.Remove(existing);
        }

        public void Save()
        {
            _context.SaveChanges();
        }
    }
}

The above GenericRepository is a generic class and implements the IGenericRepository interface. As the above GenericRepository class uses the 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.

Modifying Employee Controller

Once the GenericRepository is ready, now we can use this repository in our Employee Controller as shown below.

Employee Controller

using System.Web.Mvc;
using RepositoryUsingEFinMVC.DAL;
using RepositoryUsingEFinMVC.GenericRepository;

namespace RepositoryUsingEFinMVC.Controllers
{
    public class EmployeeController : Controller
    {
        private IGenericRepository<Employee> repository = null;

        public EmployeeController()
        {
            this.repository = new GenericRepository<Employee>();
        }

        public EmployeeController(IGenericRepository<Employee> repository)
        {
            this.repository = repository;
        }

        [HttpGet]
        public ActionResult Index()
        {
            var model = repository.GetAll();
            return View(model);
        }

        [HttpGet]
        public ActionResult AddEmployee()
        {
            return View();
        }

        [HttpPost]
        public ActionResult AddEmployee(Employee model)
        {
            if (ModelState.IsValid)
            {
                repository.Insert(model);
                repository.Save();
                return RedirectToAction("Index", "Employee");
            }
            return View();
        }

        [HttpGet]
        public ActionResult EditEmployee(int EmployeeId)
        {
            Employee model = repository.GetById(EmployeeId);
            return View(model);
        }

        [HttpPost]
        public ActionResult EditEmployee(Employee model)
        {
            if (ModelState.IsValid)
            {
                repository.Update(model);
                repository.Save();
                return RedirectToAction("Index", "Employee");
            }
            else
            {
                return View(model);
            }
        }

        [HttpGet]
        public ActionResult DeleteEmployee(int EmployeeId)
        {
            Employee model = repository.GetById(EmployeeId);
            return View(model);
        }

        [HttpPost]
        public ActionResult Delete(int EmployeeID)
        {
            repository.Delete(EmployeeID);
            repository.Save();
            return RedirectToAction("Index", "Employee");
        }
    }
}

As shown in the above code, the IGenericRepository variable is declared with Employee as its type. The constructor then assigns an instanced of GenericRepository or some other implementation of IGenericRepository to this variable.

That’s it. We are done with our implementation. Now run the application and perform the CRUD operations which should work as expected.

What is a Repository Pattern in C#?

The Repository Pattern in C# is used to create an abstraction layer between the data access layer and the business logic layer of an application. That means the Repository Pattern allows us to separate the data access code from the rest of the application. This isolation provides the advantages of code reuse, minimizes future modifications to the code and also simplifies testing of the controller classes.

This article gave you an understanding of the Repository pattern in C# from the context of ASP.NET MVC and Entity Framework. We created entity-specific repositories in our previous article as and generic repositories in this article.

In the next article, I am going to discuss how to use both generic and non-generic repository in ASP.NET MVC application. Here, in this article, I try to explain the Generic Repository pattern in C# using ASP.NET MVC application with Entity Framework step by step with a simple example. 

4 thoughts on “Generic Repository Pattern in C#”

  1. what if i want to add a method to a specific Model ? (i think i must create an interface and repository class for that model and write my method inside it )

  2. This is suboptimal. Remember that a controller is instantiated for every request by the ControllerFactory (which by default is the DefaultControllerFactory). Each time an HTTP request is received, your implementation is creating a new database context.

    Instead, one should instantiate one context in the controller and pass it as an argument to the GenericRepository.

Leave a Reply

Your email address will not be published. Required fields are marked *