I currently have a Repository/UnitOfWork pattern down. However, there is one hard coupling that I am unable to figure out how I can get rid of.
This is an overview of my pattern:
Business Logic Layer
- IRepository
- Used as type contraint
- IRepository< TModel, TDTO >
- Implements IRepository
- General CRUD methods
- IEmployeeRepository< TModel >
- Implements IRepository< TModel, EmployeeDTO >
- Some employee specific methods
- IUnitOfWork
- Getter for repositories
- Save method
- IEntityWithId
- Interface to force (and expose) DTOs and EF POCOs to have a Int32 field called ID
- Used as type contraints
- EmployeeDTO (Mapped with AutoMapper in the implemented EmployeeRepository)
- DTO entity used in the core project and (to come) test project
Data Layer (Injected with Ninject)
- UnitOfWork
- Implementation of IUnitOfWork based on Entity Framework
- EmployeesRepository
- Implementation of IEmployeeRepository< TModel >
- Employee
- EF POCO
Core
- EmployeesController
- Parametered constructer EmployeesController(IUnitOfWork unitOfWork)
- IUnitOfWork is injected with a Ninject module as a UnitOfWork (from Data layer)
Those are the problem methods in my generic IRepository interface.
TDTO Find(Expression<Func<TModel, bool>> filter);
and
IEnumerable<TDTO> FindAll(Expression<Func<TModel, bool>> filter);
As you can see, there is TModel in there, which is used to build up an expression to filter results. I COULD do something like using an expression on the DTO, but that would require a complete list of employees mapped to DTOs (aka it wouldnt generate a SQL filter but it would filter a SELECT * FROM Employee result list). So this isn't a good option.
The other, more viable but not optimal solution is to use dynamic LINQ. That way, I can pass a simple string in the Find / FindAll methods and get rid of the TModel requirement. However, this would means that refactoring becomes annoying since it fills the code with magic strings.