Entity Framework Core, Unit of Work and Repository Pattern

entity-framework-core repository unit-of-work

Question

Having read numerous articles stating that putting a UOW and Repository pattern on top of an EF Core db context is not recommended, I am almost on board and am about to implement Services that gets IDBContext injected, in a new project of mine.

I say almost, as there's one feature I previously used that I don't understand how to implement without a repository.

In previous projects, I have used UOW and Repository patterns on top of EF and accessed them from a Service. The following method would be within a Repository and could be called thereafter by calling uow.StudentRepository.Get(id) from any Service.

public async Task<Student> Get(Guid id)
    {
        return await _context.Students
            .Include(x => x.Course)
            .Include(x=>x.Address)
            .Include(x => x.Grade)
            .FirstOrDefaultAsync(x => x.Id == id);
    }

Without a Repository, querying from IDBContext, I would have to call...

_context.Students
            .Include(x => x.Course)
            .Include(x=>x.Address)
            .Include(x => x.Grade)
            .FirstOrDefaultAsync(x => x.Id == id);

...everytime I wanted to do this query. Which seems wrong as it would not be DRY.

Question

Could someone please suggest a way that I could declare this code in one place without a Repository?

1
0
11/20/2019 8:44:39 PM

Popular Answer

Sounds like you need a service. You can create a service like DbContext so that you can inject it into your controllers.

IStudentService.cs:

public interface IStudentService
{
    Task<List<Student>> GetStudents();
    // Other students methods here..
}

StudentService.cs

public class StudentService : IStudentService
{
    private readonly DataContext _context;

    public StudentService(DataContext context)
    {
        _context = context;
    }

    public async Task<List<Student>> GetStudents()
    {
        return await _context.Students
        .Include(x => x.Course)
        .Include(x=>x.Address)
        .Include(x => x.Grade)
        .ToListAsync();
    }
}

Then register the service into ConfigureServices() in Startup.cs

services.AddScoped<IStudentService, StudentService>();

Now you can inject the service into any controller. Example:

[ApiController]
[Route("api/[controller]")]
public class StudentController: ControllerBase
{
    private readonly IStudentService _studentService;
    private readonly DataContext _context;

    public StudentService(DataContext context, IStudentService studentService)
    {
        _context = context;
        _studentService = studentService;
    }

    [HttpGet]
    public virtual async Task<IActionResult> List()
    {
        return Ok(await _studentService.GetStudents());
    }
}

Be sure to create the service only if you will use it on multiple controllers and avoid fall into an anti-pattern.

0
11/20/2019 10:39:17 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow