Getting Attribute Inside Linq “Where” using string

I am trying to pass a list of strings that contain fields that need to filtered.

string[] filterList = {"CostCenterId", "Description", ....}

Object Definition:

public class CostCenter
{
    public int Id { get; set; }
    public string CostCenterId { get; set; }
    public string Description { get; set; }
}

Instead of doing:

var filterData = data
  .Where(x => x.CostCenterId.Contains(request.Filter) || x.Description.Contains(request.Filter));

Is it possible to get an attribute inside the lambda expression: Where() by passing in a string instead?

Is it possible to do something like:

var filterData = data
  .Where(x => x["CostCenterId"].Contains(request.Filter) || x.["Desription"]
  .Contains(request.Filter));

substituting values from the filterList:

var filterData = data
  .Where(x => x[filterList[0]].Contains(request.Filter) || x.[filterList[1]
  .Contains(request.Filter));

I have tried the following approach:

var filterData = data
  .Where(x => x.GetType().GetField("CostCenterId").Name.Contains(filter) || x.GetType().GetField("Description").Name.Contains(filter));

but this does not work,

The expected result is the filtered data. The result I’m getting right now is null, any help would be greatly appreciated

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

EF uses IQueryable interface which accepts expression trees so it can analyze your code and try to translate it to actual SQL. One of the options here is to build the filter expression for Where clause yourself. For limited case of handling only string properties you can something like that (edge case of empty filterList is omitted):

var filterValue = "test";// request.Filter

string[] filterList = { "CostCenterId", "Description" };
var par = Expression.Parameter(typeof(CostCenter));
var stringContains = typeof(string).GetMethod(nameof(string.Contains), new[] {typeof(string)});
var predicate = filterList
    .Select(f => 
    {
        var prop = Expression.Property(par, typeof(CostCenter), f);
        return (Expression) Expression.Call(prop, stringContains, Expression.Constant(filterValue));
    })
    .Aggregate((agg,curr) => Expression.OrElse(agg,curr));
    
var filter = Expression.Lambda<Func<CostCenter, bool>>(predicate, par);

And then use it in the query:
var filterData = data.Where(filter);


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x