My Helper
My Helper

Reputation: 707

Select only needed field with ListAsync in Ardalis Clean Architecture

All - I have got two questions regarding the repository pattern used in the Ardalis CleanArchitecture.

  1. 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.

  2. 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

Answers (1)

valkarin
valkarin

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

Related Questions