I would like to modify the following procedure
public async Task<IActionResult> GetMany(List<int> values)
{
List<TEntity> entities = await _crudApiDbContext.Set<TEntity>()
.Where(entity => values.Contains(entity.Id)).ToListAsync();
return new OkObjectResult(entities);
}
to accept the column name which will be searched in the Contains method, something like:
public async Task<IActionResult> GetMany(List<int> values, string colName)
{
List<TEntity> entities = await _crudApiDbContext.Set<TEntity>()
.Where(entity => values.Contains<TEntity>(colName)).ToListAsync();
return new OkObjectResult(entities);
}
I've tried overloading Contains and using expression trees but got lost...
Any ideas?
Introduce the following extension method, which should filter any entity type by collection:
public static class QueryableExtensions
{
public static IQueryable<TEntity> FilterByList<TEntity, TKey>(this IQueryable<TEntity> query, IEnumerable<TKey> values, string colName)
where TEntity : class
{
var param = Expression.Parameter(typeof(TEntity), "e");
var propAccess = Expression.PropertyOrField(param, colName);
var listExpr = Expression.Constant(values);
var predicate = Expression.Call(typeof(Enumerable), "Contains", new[] {typeof(TKey)}, listExpr,
propAccess);
var predicateLambda = Expression.Lambda<Func<TEntity, bool>>(predicate, param);
return query.Where(predicateLambda);
}
}
And rewrite your GetMany
to this variant:
public async Task<IActionResult> GetMany<TEntity>(List<int> values, string colName)
{
var entities = await _crudApiDbContext.Set<TEntity>()
.FilterByList(values, colName)
.ToListAsync();
return new OkObjectResult(entities);
}