Segregation of Repository

All in one

IProductRepository with 20 methods will quickly become a monster when you started to implement it in your ProductRepository. Instead we will break them down to at least 2 level

The Master Interface

public interface IAsyncRepository<T>: Where T: Class 
{
    Task<T> GetByIdAsync(Guid id);
    Task<IReadOnlyList<T>> GetAllAsync();
    Task<T> AddItemAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(T entity);
} 

The Specific Interface

public interface IProductRepository: IAsyncRepository<Product> 
{
    Task<List<ProductByCategoryViewModel>> GetProductsByCategory(guid categoryId);
}

The Base implementation

public class BaseRepository<T>: IAsyncRepository<T> Where T: Class 
{
    // implementing CRUD
}

The specific implementation


public class ProductRepository: BaseRepository<Product>, IProductRepository 
{
    public async Task<List<ProductByCategoryViewModel>> GetProductsByCategory(guid categoryId) 
    {
        // implementation for this specific thing here
    }
}