To Show you the example,let's first create the ProfessorDbContext class representing our database context:
public class ProfessorDbContext : DbContext
{
public DbSet<Professor> Professors { get; set; }
public DbSet<Course> Courses { get; set; }
public ProfessorDbContext(DbContextOptions<ProfessorDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
Here, we define the Professor class representing the Professor table:
public class Professor
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string DepartmentName { get; set; }
public ICollection<Course> Courses { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int ProfessorId { get; set; }
public Professor Professor { get; set; }
}
In the Professor class, we define properties such as Id, Name, Email, Address, and DepartmentName. Additionally, we include a navigation property Courses to represent the relationship with the Course table.
Now, let's write the GenericRepository to work with the ProfessorDbContext and Professor table:
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
private readonly ProfessorDbContext _context;
public GenericRepository(ProfessorDbContext context)
{
_context = context;
}
public IQueryable<TEntity> GetAll()
{
return _context.Set<TEntity>().AsNoTracking();
}
public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
params Expression<Func<TEntity, object>>[] includeProperties)
{
IQueryable<TEntity> query = _context.Set<TEntity>().AsNoTracking();
if (includeProperties != null)
{
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
}
if (orderBy != null)
{
query = orderBy(query);
}
return query.Where(predicate);
}
}
In GenericRepository class, we inject the ProfessorDbContext , allowing us to work with the Professor table. The GetAll method retrieves all entities from the Professor table, while the Find method enables filtering, ordering, and eager loading of related entities.
With these modifications, our GenericRepository is now work with the ProfessorDbContext and Professor table, providing a generic data access layer for our application.
Let's let's extend the usage of the GenericRepository to demonstrate filtering and ordering using the Find method in our ProductController:
public class ProductController : ControllerBase
{
private readonly IGenericRepository<Professor> _professorRepository;
public ProductController(IGenericRepository<Professor> professorRepository)
{
_professorRepository = professorRepository;
}
[HttpGet]
public IActionResult GetProfessors()
{
var professors = _professorRepository.GetAll().ToList();
return Ok(professors);
}
[HttpGet("{id}")]
public IActionResult GetProfessor(int id)
{
var professor = _professorRepository.Find(p => p.Id == id).FirstOrDefault();
if (professor == null)
{
return NotFound();
}
return Ok(professor);
}
[HttpGet("filtered")]
public IActionResult GetFilteredProfessors(string department, string orderBy)
{
IQueryable<Professor> query = _professorRepository.Find(
predicate: p => string.IsNullOrEmpty(department) || p.DepartmentName == department,
orderBy: orderBy switch
{
"Name" => q => q.OrderBy(p => p.Name),
"Email" => q => q.OrderBy(p => p.Email),
_ => null
}
);
var professors = query.ToList();
return Ok(professors);
}
}
In ProductController, we've added action methods:
Using GenericRepository's Find method in performing filtering, ordering, and retrieval of entities based on specific criteria.