Section 2 of 5

Repository Pattern

🎯 What You'll Learn

  • What is Repository Pattern
  • Creating repository interface
  • Implementing repository
  • Generic repository
  • Using in controllers

What is Repository Pattern?

The Repository Pattern abstracts data access logic, providing a collection-like interface for accessing domain objects.

Benefits

  • Separation of concerns: Business logic separate from data access
  • Testability: Easy to mock repositories
  • Maintainability: Centralized data access logic
  • Flexibility: Easy to switch data sources

Repository Interface

IProductRepository.cs C#
public interface IProductRepository
{
    Task<Product> GetByIdAsync(int id);
    Task<IEnumerable<Product>> GetAllAsync();
    Task AddAsync(Product product);
    Task UpdateAsync(Product product);
    Task DeleteAsync(int id);
}

Repository Implementation

ProductRepository.cs C#
public class ProductRepository : IProductRepository
{
    private readonly InvenTrackDbContext _context;

    public ProductRepository(InvenTrackDbContext context)
    {
        _context = context;
    }

    public async Task<Product> GetByIdAsync(int id)
    {
        return await _context.Products.FindAsync(id);
    }

    public async Task<IEnumerable<Product>> GetAllAsync()
    {
        return await _context.Products.ToListAsync();
    }

    public async Task AddAsync(Product product)
    {
        await _context.Products.AddAsync(product);
        await _context.SaveChangesAsync();
    }

    public async Task UpdateAsync(Product product)
    {
        _context.Products.Update(product);
        await _context.SaveChangesAsync();
    }

    public async Task DeleteAsync(int id)
    {
        var product = await _context.Products.FindAsync(id);
        if (product != null)
        {
            _context.Products.Remove(product);
            await _context.SaveChangesAsync();
        }
    }
}

Register Repository

Program.cs C#
builder.Services.AddScoped<IProductRepository, ProductRepository>();

Generic Repository

IRepository.cs C#
public interface IRepository<T> where T : class
{
    Task<T> GetByIdAsync(int id);
    Task<IEnumerable<T>> GetAllAsync();
    Task AddAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(int id);
}
Repository.cs C#
public class Repository<T> : IRepository<T> where T : class
{
    private readonly InvenTrackDbContext _context;
    private readonly DbSet<T> _dbSet;

    public Repository(InvenTrackDbContext context)
    {
        _context = context;
        _dbSet = _context.Set<T>();
    }

    public async Task<T> GetByIdAsync(int id)
    {
        return await _dbSet.FindAsync(id);
    }

    public async Task<IEnumerable<T>> GetAllAsync()
    {
        return await _dbSet.ToListAsync();
    }

    public async Task AddAsync(T entity)
    {
        await _dbSet.AddAsync(entity);
        await _context.SaveChangesAsync();
    }

    public async Task UpdateAsync(T entity)
    {
        _dbSet.Update(entity);
        await _context.SaveChangesAsync();
    }

    public async Task DeleteAsync(int id)
    {
        var entity = await _dbSet.FindAsync(id);
        if (entity != null)
        {
            _dbSet.Remove(entity);
            await _context.SaveChangesAsync();
        }
    }
}

Using in Controller

ProductsController.cs C#
public class ProductsController : Controller
{
    private readonly IProductRepository _repository;

    public ProductsController(IProductRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public async Task<IActionResult> Index()
    {
        var products = await _repository.GetAllAsync();
        return View(products);
    }

    [HttpPost]
    public async Task<IActionResult> Create(Product product)
    {
        await _repository.AddAsync(product);
        return RedirectToAction("Index");
    }
}

Key Takeaways

  • Repository Pattern: Abstracts data access
  • Interface: Define contract for data operations
  • Implementation: Encapsulate EF Core logic
  • Generic Repository: Reusable for all entities
  • Dependency Injection: Inject repository into controllers
  • Benefits: Testability, maintainability, flexibility