I have a grid passing me filters. So I may have an object like:
var filter = new Filter(){
Member = "Titles",
Operator = Filter.Operators.IsEqualTo,
Value = "Developer"
};
Then I need to take this and extend an IQueryable so to do that, I use dynamic.LINQ and have a method to apply these filters:
private IQueryable<TReportClass> ApplyFilter(ReportFilter filter, IQueryable<TReportClass> baseQuery)
{
switch (filter.Operator)
{
case ReportFilter.Operators.Contains:
baseQuery = baseQuery.Where(string.Format("{0}.Contains(@0)", filter.Member), filter.Value);
break;
case ReportFilter.Operators.DoesNotContain:
baseQuery = baseQuery.Where(string.Format("!{0}.Contains(@0)", filter.Member), filter.Value);
break;
case ReportFilter.Operators.IsEqualTo:
baseQuery = baseQuery.Where(string.Format("{0} = @0", filter.Member), filter.Value);
break;
case ReportFilter.Operators.IsNotEqualTo:
baseQuery = baseQuery.Where(string.Format("{0} != @0", filter.Member), filter.Value);
break;
case ReportFilter.Operators.StartsWith:
baseQuery = baseQuery.Where(string.Format("{0}.StartsWith(@0)", filter.Member), filter.Value);
break;
case ReportFilter.Operators.EndsWith:
baseQuery = baseQuery.Where(string.Format("{0}.EndsWith(@0)", filter.Member), filter.Value);
break;
case ReportFilter.Operators.IsNull:
baseQuery = baseQuery.Where(string.Format("{0} = NULL", filter.Member));
break;
case ReportFilter.Operators.IsNotNull:
baseQuery = baseQuery.Where(string.Format("{0} != NULL", filter.Member));
break;
case ReportFilter.Operators.IsEmpty:
baseQuery = baseQuery.Where(string.Format("string.IsNullOrEmpty({0})", filter.Member));
break;
case ReportFilter.Operators.IsNotEmpty:
baseQuery = baseQuery.Where(string.Format("!string.IsNullOrEmpty({0})", filter.Member));
break;
}
return baseQuery;
}
However this works only for non-collections. How can I get it to work with collections? If I have this model:
public class UserReport : Entity
{
public string Name { get; set; }
public string Email { get; set; }
public List<string> Titles { get; set; }
}
And this query as a base:
IQueryable<UserReport> baseQuery = MyDbContext.DbSet<User>.Select(user => new UserReport
{
Id = user.Id,
Name = user.FirstName + " " + user.LastName,
Email = user.Email,
Titles = user.Positions.Select(apptment => apptment.Title).ToList()
})
So I can call like:
IQueryable<UserReport> filteredQuery = ApplyFilters(filters, baseQuery);
How do I transform the above filter to translate into a LINQ like:
baseQuery.Where(userReport => userReport.Titles.Any(title => title == "Developer")
Can that be done with dynamic LINQ? Or do I need to build my own predicate? If so, how do I do that?