Reputation: 707
All - I have got two questions regarding the repository pattern used in the Ardalis CleanArchitecture.
With ListAsync how can I project to only a few fields not to all of them? Example: if I have 20+ fields in the table & I need only 3 fields to fetch from it. I see in the template the repository uses "ToListAsync()" ef api, however this executes a "Select * " in the SQL Server database table. I wanted only to fetch 3 fields which is part of my DTO.
With specification pattern I see an option to select required fields. That means when using specification I can project to a DTO. Where is the ideal place to put these kinds of dtos? Under specifications folder itself?
Any help on these would be very much appreciated. Thanks a bunch!
Template Repo: https://github.com/ardalis/CleanArchitecture
Upvotes: 1
Views: 1365
Reputation: 11
The easiest way I thought of is using AutoMapper. AutoMapper has an extension method IQueryable.ProjectTo<>
. You can implement RepositoryBase<>
and inherit that to EfRepository<>
instead of inheriting RepositoryBase<>
directly.
public class EfRepository<T> : ApplicationRepository<T>, IReadRepository<T>, IRepository<T> where T : EntityBase, IAggregateRoot
{
public EfRepository(ApplicationDbContext dbContext) : base(dbContext)
{
}
public EfRepository(ApplicationDbContext dbContext, IMapper mapper)
: base(dbContext, mapper)
{}
}
ApplicationRepository class
public abstract class ApplicationRepository<T> : RepositoryBase<T> where T : EntityBase, IAggregateRoot
{
private readonly IMapper _mapper;
private readonly DbContext _dbContext;
protected ApplicationRepository(DbContext dbContext)
: base(dbContext)
{
_dbContext = dbContext;
}
protected ApplicationRepository(DbContext dbContext, ISpecificationEvaluator specificationEvaluator)
: base(dbContext, specificationEvaluator)
{
_dbContext = dbContext;
}
protected ApplicationRepository(DbContext dbContext,
IMapper mapper)
: base(dbContext)
{
_dbContext = dbContext;
_mapper = mapper;
}
public async Task<List<TProjectTo>> ListAsyncProjected<TProjectTo>(CancellationToken cancellationToken = default)
{
return await ListAsyncProjected<TProjectTo>(null, cancellationToken);
}
public async Task<List<TProjectTo>> ListAsyncProjected<TProjectTo>(ISpecification<T> specification,
CancellationToken cancellationToken = default)
{
if (specification == null)
return await _dbContext.Set<T>()
.AsNoTracking()
.ProjectTo<TProjectTo>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
return await SpecificationEvaluator.Default
.GetQuery(_dbContext.Set<T>()
.AsNoTracking()
.AsQueryable(), specification)
.ProjectTo<TProjectTo>(_mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);
}
}
Upvotes: 0