Designing ASP.NET Core application with Repository, Unit of work and EF Core

by Philipp Bocharov   Last Updated December 19, 2017 10:05 AM

I develop ASP.NET Core (Web API) application that uses EF Core for the data access. I also utilize UnitOfWork and Repository pattern to abstract from EF, simplify unit testing and strictly separate data access logic from my business logic. My business logic is encapsulated in several services that have no direct access to EF context but uses IUnitOfWork and IRepository abstractions.

My controllers are very thin and generally looks like:

// injected with DI
IService Service;
IUnitOfWork Uow;

public IActionResult DoSomething(int id)
    var resultEntity = this.Service.DoDomething(this.Uow, id);
    return Ok(resultEntity);

1. Leaky EF abstraction

Controller usually receives identifiers as arguments (e.g.: from URL). But I think business layer should operate entities rather than identifiers. And controller will looks like:

    public IActionResult DoSomething(int id)
        ArgumentEntity entity = this.Uow.Repository.GetById(id);
        if (entity == null) return NotFound(...)    
        var resultEntity = this.Service.DoDomething(this.Uow, entity);
        return Ok(resultEntity);

Pros: More expressive syntax. Ability to handle some sort of input errors (like missing entities) in controller.

The problem: Internally it uses EF core that loads related data only if you ask to do so. So now your controller have to know what entity related data is required for each service method.

Loading all data for the entity is silly.

Passing identifier instead of entity is ugly.

Specifying what related data to load in controller is error prone and ugly too.

The question is: how to solve the issue with required related data?

2. Scope management

As you could see the scope (UnitOfWork) is injected with DI to Controller and passed as argument to the service method. So it is the Controller who owns the scope.

Pros: It lets me to call several service methods in one scope/context

Cons: Service methods (that represents business logic) get additional parameter that have nothing to do with business itself.

The question is: who should manage the scope: Controller or Service? Should service create it's own context inside methods?

Related Questions

Relationship between Repository and Unit of Work

Updated October 17, 2017 12:05 PM