Please enable Javascript to correctly display the contents on Dot Net Tricks!

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

  Author : Shailendra Chauhan
Posted On : 15 Feb 2017
Total Views : 7,170   
Updated On : 15 Feb 2017
 

In this article you will learn how to use the repository pattern for CRUD operations and how to combine it with unit of work patterns. Before goining to write the code, let's understand 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 Framework is based on the repository and unit of work patterns to perform CRUD operations on an entity.

Entity Framework and Repository and Unit Of Work Patterns

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.



ABOUT AUTHOR

Shailendra Chauhan
Author, Architect, Corporate Trainer and Microsoft MVP

He is the author of some of most popular e-books which encompass technical Interview on Node.js Interview Questions and Answers, ASP.NET MVC Interview Questions and Answers, AngularJS Interview Questions and Answers and LINQ Interview Questions and AnswersKnow more...

Free Interview Books
 
COMMENTS (1)
Ali Kolahdoozan Reply

Hi, Thanks for the article. May I ask you something related to the scenario ?. Imagine that I want to insert a record and then update another record and then something else and else and else. It needs transaction so how can we do that in a Generic Repo?. I need to Commit or Roll back all of them by a single command. SO?.

2 JUN
Hadoop Development cum Administration (Online)

7:00 AM-9:00AM IST

Know More
28 MAY
ASP.NET Core with Angular4 Development (Classroom)

10:30 AM-11:30 AM Weekend

Know More
27 MAY
ASP.NET MVC with Angular4 Development (Classroom)

4:00 PM-5:30 PM Weekend

Know More
25 MAY
ASP.NET MVC with Angular4 Development (Online)

09:00 PM-11:00 PM IST(+5.30 GMT)

Know More
25 MAY
ASP.NET MVC with Angular4 Development (Online)

09:00 PM-11:00 PM IST(+5.30 GMT)

20 MAY
Angular2 and Angular4 Development (Online)

08:00 AM-10:00 AM IST(+5.30 GMT) Weekend

20 MAY
NodeJS with Angular4 Development (Classroom)

5:00 PM-6:30 PM Weekend

8 MAY
ASP.NET MVC with Angular4 Development (Online)

07:00 AM-09:00 AM IST(+5:30 GMT) M/W/F

2 MAY
ASP.NET Core Development (Online)

07:00 AM - 09:00 AM IST( TUS, THR)

29 APR
ASP.NET MVC with Angular2 Development (Classroom)

9:30 AM-11:00 AM

22 APR
MEAN Stack 2 Development (Classroom)

11:00 AM-12:30 PM Weekend

10 APR
Master Class ASP.NET MVC 5 with Angular2 Plus Angular4 Development (Online)

09:00 PM - 11:00 PM IST (M/W/F)

25 MAR
Xamarin Forms : Build Cross-platform Apps (Classroom)

8:00 AM-9:30AM Weekend

BROWSE BY CATEGORY
 
 
LIKE US ON FACEBOOK
 
+