I'm trying to write a class that helps create a LINQ query dynamically.
protected Func<T, TColumn> GetColumn;
public MyClass(Func<T, TColumn> getColumn)
{
GetColumn = getColumn;
}
public virtual IQueryable<T> ApplyFilter(IQueryable<T> query)
{
if (FilterMode == FilterModeMatchAny)
return query.Where(x => FilterIds.Contains(GetColumn(x)));
return query;
}
This class is called like this:
MyClass<Location, string> myClass = new MyClass<Location, string>(l => l.State);
var locations = myClass.ApplyFilter(DbContext.Locations);
However, the code above fails:
The LINQ expression 'DbSet
.Where(l => Invoke(__GetJoiningTables_0, l[Location])
.Any(xx => __FilterIds_1
.Contains(Invoke(__GetColumn_2, xx)
)))' 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 either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
The trouble appears to be the way I'm using GetColumn
. So I changed the declaration of GetColumn
so that it is now an expression.
protected Expression<Func<T, TColumn>> GetColumn;
The same argument being passed to my constructor can easily be converted to this type. I Only need to change the argument type.
But now how can I use this new GetColumn
in my ApplyFilter()
method?
Update:
Eventually, I also need to do the same thing to the following two expressions.
// Expressions to incorporate
protected Expression<Func<T, ICollection<TJoinTable>>> GetJoiningTables;
protected new Expression<Func<TJoinTable, TColumn>> GetColumn;
// Match any query
return query.Where(x => GetJoiningTables(x).Any(xx => FilterIds.Contains(GetColumn(xx))));
// Match all query
return query.Where(x => GetJoiningTables(x).Count(xx => FilterIds.Contains(GetColumn(xx))) >= FilterIds.Count());