Implementing Repository and Unit of Work Patterns with ASP.NET MVC

Implementing Repository and Unit of Work Patterns with ASP.NET MVC

02 Aug 2025
Advanced
100K Views
6 min read
Learn with an interactive course and practical hands-on labs

ASP.NET MVC with Web API Online Course - Learn & Certify

In this article you will learn how to use the repository pattern for CRUD operations and how to combine it with the unit of work patterns. Before going to write the code, let's understand the repository and unit of work patterns separately.

Repository Pattern

The repository pattern is used to create an abstraction layer between the DAL (data access layer) and the BAL (business access layer) to perform CRUD operations.

Repository Pattern

Repository Pattern Implementation

The repository pattern can be implemented by using following two method :

  1. Generic Repository Pattern

    A generic repository implementation is used to define common database operations (like Create, Retrieve Update, Delete etc.) for all the database entities in a single class.

    public interface IRepository where TEntity : class
    {
     IEnumerable GetAll();
     IEnumerable Find(Expression> predicate);
     TEntity Get(object Id);
    
     void Add(TEntity entity);
     void AddRange(IEnumerable entities);
    
     void Update(TEntity entity);
    
     void Remove(object Id);
     void Remove(TEntity entity);
     void RemoveRange(IEnumerable entities);
    }
    
    // implementation
    public class Repository : IRepository where TEntity : class
    {
     protected readonly DbContext db;
    
     public Repository(DbContext _db)
     {
     db = _db;
     }
    
     public IEnumerable GetAll()
     {
     return db.Set().ToList();
     }
    
     public IEnumerable Find(Expression> predicate)
     {
     return db.Set().Where(predicate);
     }
    
     public TEntity Get(object Id)
     {
     return db.Set().Find(Id);
     }
    
     public void Add(TEntity entity)
     {
     db.Set().Add(entity);
     }
    
     public void AddRange(IEnumerable entities)
     {
     db.Set().AddRange(entities);
     }
    
     public void Remove(TEntity entity)
     {
     db.Set().Remove(entity);
     }
    
     public void RemoveRange(IEnumerable entities)
     {
     db.Set().RemoveRange(entities);
     }
    
     public void Remove(object Id)
     {
     TEntity entity = db.Set().Find(Id);
     this.Remove(entity);
     }
    
     public void Update(TEntity entity)
     {
     db.Entry(entity).State = EntityState.Modified;
     }
    }
    
  2. Non-Generic Repository Pattern (Specific Repository)

    A non-generic repository implementation is used to define all database operation related to an entity within a separate class. For example, if you have two entities Category and Product, each entity will have its own implementation repository.

    public interface IProductRepository
    {
     IEnumerable GetAll();
     IEnumerable Find(Expression> predicate);
     Product Get(int Id);
    
     void Add(Product entity);
     void AddRange(IEnumerable entities);
    
     void Update(Product entity);
    
     void Remove(int Id);
     void Remove(Product entity);
     void RemoveRange(IEnumerable entities);
    }
    
    // implementation
    public class ProductRepository
    {
     protected readonly DbContext db;
    
     public Repository(DbContext _db)
     {
     db = _db;
     }
    
     public IEnumerable GetAll()
     {
     return db.Products.ToList();
     }
    
     public IEnumerable Find(Expression> predicate)
     {
     return db.Products.Where(predicate);
     }
    
     public Product Get(int Id)
     {
     return db.Products.Find(Id);
     }
    
     public void Add(Product entity)
     {
     db.Products.Add(Product);
     }
    
     public void AddRange(IEnumerable entities)
     {
     db.Products.AddRange(entities);
     }
    
     public void Remove(Product entity)
     {
     db.Products.Remove(entity);
     }
    
     public void RemoveRange(IEnumerable entities)
     {
     db.Products.RemoveRange(entities);
     }
    
     public void Remove(object Id)
     {
     Product entity = db.Products.Find(Id);
     this.Remove(entity);
     }
    
     public void Update(Product entity)
     {
     db.Entry(entity).State = EntityState.Modified;
     }
    }
    

Recommended Repository Pattern Implementation

If you will use one of the above implementation, generic you can not use for specific operation on an entity and in case of non-generic implementation, you have to write code for common CRUD operations for each entity. So better way is, just create a generic repository for commonly used CRUD operation and for specific one create a non-generic repository and inherit form generic repository. The example code is given below:

public interface IProductRepository : IRepository
{
 IEnumerable GetProductsByCategory(int id);
}
 
public class ProductRepository : Repository, IProductRepository
{
 public DatabaseContext context
 {
 get
 {
 return db as DatabaseContext;
 }
 }

 public ProductRepository(DatabaseContext _db) : base(_db)
 {

 }
 
 public IEnumerable GetProductsByCategory(int id)
 {
 return context.Products.Where(p => p.CategoryId == id).ToList();
 }
} 

Unit of work Pattern

The unit of pattern implementation manage in-memory database CRUD operations on entities as one transaction. So, if one of the operation is failing then entire db operations will be rollback.

Unit of Work pattern

 
public interface IUnitOfWork : IDisposable
{
 ICategoryRepository Categories { get; }
 IProductRepository Products { get; }

 int SaveChanges();
}

public class UnitOfWork : IUnitOfWork
{
 private readonly DatabaseContext db;

 public UnitOfWork()
 {
 db = new DatabaseContext();
 }

 private ICategoryRepository _Categories;
 public ICategoryRepository Categories
 {
 get
 {
 if (this._Categories == null)
 {
 this._Categories = new CategoryRepository(db);
 }
 return this._Categories;
 }
 }

 private IProductRepository _Products;
 public IProductRepository Products
 {
 get
 {
 if (this._Products == null)
 {
 this._Products = new ProductRepository(db);
 }
 return this._Products;
 }
 }

 public int SaveChanges()
 {
 return db.SaveChanges();
 }

 public void Dispose()
 {
 db.Dispose();
 }
}

Entity Framework and Repository and Unit Of Work Patterns

Entity Frame work

Entity Framework is based on the repository and unit of work patterns to perform CRUD operations on an entity.

The DbSet class is based on the repository design pattern which provides us a set of method to perform CRUD operations on an entity. The DbContext class is based on unit of work pattern which includes all the DbSet entities. The DbContext class manages in-memory database operations on these entities and later saves all these updates as one transaction into database.

Advantages of Repository and Unit Of Work Design Patterns

  1. Abstract Data Access Layer and Business Access Layer from the Application.

  2. Manage in-memory database operations and later saves in-memory updates as one transaction into database.

  3. Facilitates to make the layers loosely-coupled using dependency injection.

  4. Facilitates to follow unit testing or test-driven development (TDD).

What do you think?

I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

Share Article
About Author
Shailendra Chauhan (Microsoft MVP, Founder & CEO at ScholarHat)

He is a renowned Speaker, Solution Architect, Mentor, and 10-time Microsoft MVP (2016–2025). With expertise in AI/ML, GenAI, System Design, Azure Cloud, .NET, Angular, React, Node.js, Microservices, DevOps, and Cross-Platform Mobile App Development, he bridges traditional frameworks with next-gen innovations.

He has trained 1 Lakh+ professionals across the globe, authored 45+ bestselling eBooks and 1000+ technical articles, and mentored 20+ free courses. As a corporate trainer for leading MNCs like IBM, Cognizant, and Dell, Shailendra continues to deliver world-class learning experiences through technology & AI.
Live Training - Book Free Demo
ASP.NET Core Certification Training
12 Oct
08:00PM - 10:00PM IST
Checkmark Icon
Get Job-Ready
Certification
.NET Microservices Certification Training
26 Oct
08:30PM - 10:30PM IST
Checkmark Icon
Get Job-Ready
Certification
ASP.NET Core Certification Training
02 Nov
10:00AM - 12:00PM IST
Checkmark Icon
Get Job-Ready
Certification
Accept cookies & close this