I'm using EF Core and .NET 5.0.
My repository has a method such as this:
public async Task<IEnumerable<Report>> GetByAsync(Expression<Func<Report, bool>> expression)
{
return await DbSet.Where(expression).ToListAsync();
}
I wanted to implement a Service
's method as follows:
public async Task<IEnumerable<ReportResponse>> GetByAsync(int? productId, int? brandId, int? modelId, int? lineId, DateTime from, DateTime to)
{
var reports = await _repository.GetByAsync(
r => r.ProductId == productId &&
r.BrandId == brandId &&
r.ModelId == modelId &&
r.LineId == lineId &&
r.Date >= from && r.Date <= to);
// other staff
}
UPDATE
Wanted to get result, instead of creating separate methods, based on input has value or not.
For example:
GetByAsync(1, null, null, null, '2022-05-01', '2022-06-01')
should ignore types that have no values.
And:
var reports = await _repository.GetByAsync(r => r.ProductId == 1 && r.Date >= '2022-05-01' && r.Date <= '2022-06-01');
I tried with dynamic queries but could not manage.
CodePudding user response:
what you need is some sort of dynamic predicate builder, you can use this utility class: https://gist.github.com/YoussefSell/ec50f079dd3d1a192ba1f5cd5df2d64d
after you import the PredicateBuilder class to your project, actual implementation will be like this:
public async Task<IEnumerable<ReportResponse>> GetByAsync(int? productId,
int? brandId,
int? modelId,
int? lineId,
DateTime? from,
DateTime? to)
{
var predicate = PredicateBuilder.True<Report>();
if (productId.HasValue)
predicate = predicate.And(p => p.ProductId == productId);
if (brandId.HasValue)
predicate = predicate.And(p => p.BrandId== brandId);
if (modelId.HasValue)
predicate = predicate.And(p => p.ModelId == modelId);
if (lineId.HasValue)
predicate = predicate.And(p => p.LineId == lineId);
if (from.HasValue)
predicate = predicate.And(p => p.Date >= from);
if (to.HasValue)
predicate = predicate.And(p => p.Date <= to);
// pass the predicate
var reports = await _repository.GetByAsync(predicate);
// other code ...
}