基于运行时的表达式动态查询

Dynamic Queries with Expressions based on runtime

我正在使用 EF Core 和 .NET 5.0。

我的存储库有一个这样的方法:

public async Task<IEnumerable<Report>> GetByAsync(Expression<Func<Report, bool>> expression)
{
    return await DbSet.Where(expression).ToListAsync();                                            
}

我想实现一个Service的方法如下:

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        
}

更新

想要得到结果,而不是创建单独的方法,基于输入是否有价值。

例如:

GetByAsync(1, null, null, null, '2022-05-01', '2022-06-01')

应该忽略没有值的类型。

并且:

var reports = await _repository.GetByAsync(r => r.ProductId == 1 && r.Date >= '2022-05-01' && r.Date <= '2022-06-01');

我试过 dynamic queries 但无法控制。

您需要的是某种动态谓词生成器,您可以使用此实用程序 class:https://gist.github.com/YoussefSell/ec50f079dd3d1a192ba1f5cd5df2d64d

将 PredicateBuilder class 导入项目后,实际实现如下:

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