[英]Combining functions conditionally to create Linq filter
我有一个要有条件地查询的测试实体存储库和测试实体过滤器。
测试实体过滤器如下所示:
public class TestEntityFilter
{
public string Name { get; set; } = null!;
public string Type { get; set; } = null!;
public Status? Status { get; set; }
public int Take { get; set; }
public int PageNumber { get; set; }
}
我希望查询在Name
、 Type
和Status
为 null 时返回所有内容,并在它们不是时使用给定值进行过滤。 如果其中一个是 null,它将被忽略,另外两个将用于过滤。 对于这个条件查询,我尝试有条件地创建一个函数并根据值组合它们,但我的存储库方法看起来并不像它不起作用。 解决此类问题的最佳方法是什么?
public async Task<IEnumerable<TestEntity>> GetTestEntitiesAsync(TestEntityFilter testEntityFilter, CancellationToken cancellationToken)
{
var combinedFilter = BuildFilers(testEntityFilter);
return await _dbContext.TestEntity
.Where(testEntity => combinedFilter(testEntity))
.ToListAsync(cancellationToken);
}
public Func<TestEntity, bool> BuildFilers(TestEntityFilter testEntityFilter)
{
Func<TestEntity, bool> mainFilter = testEntityFilter => true;
Func<TestEntity, bool> filterByName = string.IsNullOrEmpty(testEntityFilter.Name) ?
(TestEntity j) => true :
(TestEntity j) => testEntityFilter.Name == j.Name;
Func<TestEntity, bool> filterByType = string.IsNullOrEmpty(testEntityFilter.Type) ?
(TestEntity j) => true :
(TestEntity j) => testEntityFilter.Type == j.Type;
Func<TestEntity, bool> filterByStatus = testEntityFilter.Status is null?
(TestEntity j) => true :
(TestEntity j) => testEntityFilter.Status == j.Status;
Func<TestEntity, bool> combinedFilter = (TestEntity j) => mainFilter(j) && filterByName(j) && filterByType(j) && filterByStatus(j);
}
使用过滤器运行上述方法会引发以下异常:
'The LINQ expression 'DbSet<TestEntity>()
.Where(j => Invoke(__combinedFilter_0, j))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.
您可以结合Where
条件
var res = _db.TestEntity;
if (!string.IsNullOrWhiteSpace(filter.Name))
res = res.Where(x => x.Name = filter.Name)
if (!string.IsNullOrWhiteSpace(filter.Status))
res = res.Where(x => x.Status = filter.Status)
// .. rest
return await res.ToListAsync(cancellationToken);
你可以试试这个:
public async Task<IEnumerable<TestEntity>> GetTestEntitiesAsync(TestEntityFilter testEntityFilter, CancellationToken cancellationToken)
{
var combinedFilter = BuildFilers(testEntityFilter);
var data = BuildFilers(_dbContext.TestEntity.AsQueryable(), testEntityFilter);
return await data.ToListAsync(cancellationToken);
}
public IQueryable<TestEntity> BuildFilers(IQueryable<TestEntity> entities, TestEntityFilter testEntityFilter)
{
if (string.IsNullOrEmpty(testEntityFilter.Name))
{
entities = entities.Where(j => testEntityFilter.Name == j.Name);
}
if (string.IsNullOrEmpty(testEntityFilter.Type))
{
entities = entities.Where(j => testEntityFilter.Type == j.Type);
}
if (testEntityFilter.Status.HasValue)
{
entities = entities.Where(j => testEntityFilter.Status == j.Status);
}
return entities;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.