Home > Net >  Dynamic Queries with Expressions based on runtime
Dynamic Queries with Expressions based on runtime

Time:06-04

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

  • Related