2

I'm trying to understand predicate builder so I can apply it to a web app I'm creating.

Basically I have 4 parameters that come in through a POST request, 'name', 'location', 'age', 'gender', and I have to filter out people from a database table based on these parameters.

problem is, every parameter has the possibility of being 'All' (meaning, if name = 'All', that means don't filter out people by name, if location = 'All' don't filter people by location etc...).

So one way I thought of doing this is to get all people into a list, and have 4 if statements:

if (name != 'All') {
 //filter list of people by name string
}
if (location != 'All') {
 //filter list of people by location
}

but I don't want to do this, I want to use predicate builder to build the linq expression and only get a list of people who match the parameters, but I don't understand what predicate builder is doing.

This is the site I'm looking at but it doesn't really explain what's going on, and I don't know how to apply it to my situation

Abdul Ahmad
  • 9,673
  • 16
  • 64
  • 127
  • The linked site explains *exactly* how the tool works, it's full of examples on how to use it, and even covers this exact case. You only needed to read your own link to get your answer and then some. – Servy Jan 14 '15 at 16:23
  • @Servy I still needed some clarification, otherwise I wouldn't ask, so no need to state the obvious – Abdul Ahmad Jan 14 '15 at 16:27
  • 1
    What do you need clarification on? You just said, "explain the whole thing to me" which is **exactly** what that link is already doing. If you had a specific question about a specific aspect of the tool, it's usage, its explanation, etc. then *you'd need to ask that*. You didn't do that. – Servy Jan 14 '15 at 16:28
  • are you done being angry and raging? – Abdul Ahmad Jan 14 '15 at 16:37
  • Are you willing to ask an answerable, reasonably scoped question after having done your research and made a reasonable effort to try to solve it before asking rather than asking a question because you just can't be bothered to read the documentation of the tool you want to use? – Servy Jan 14 '15 at 16:40
  • I'm not arguing with you anymore, I told you I read it and still didn't understand it, now please stop making assumptions and if you don't want to help go find someone else to harass – Abdul Ahmad Jan 14 '15 at 16:42

2 Answers2

3

Perhaps I'm not understanding the issue but why can't you just do:

query = name == "All" ? query : query.Where(x => x.Name == name);
query = location == "All" ? query : query.Where(x => x.Location == location);

For your particular situation I think what you need to do is:

var query = db.People;
query = name == "All" ? query : query.Where(x => x.Name == name);
query = location == "All" ? query : query.Where(x => x.Location == location);
query = age == "All" ? query : query.Where(x => x.Age == age);
query = weight == "All" ? query : query.Where(x => x.Weight == weight);
var results = query.ToList();
Spencer Ruport
  • 34,865
  • 12
  • 85
  • 147
  • 2
    This is exactly the answer. I'm sure OP doesnt understand that the expressions combine as you assign them. – crthompson Jan 14 '15 at 16:16
  • because I'm a noob, can you elaborate more on how to make the query and use it? – Abdul Ahmad Jan 14 '15 at 16:16
  • by the way, I forgot to mention I'm using entity framework, does that change anything? sorry I'm just not very familiar with sql querying from c# – Abdul Ahmad Jan 14 '15 at 16:19
  • @AbdulAhmad - I'm still not sure what your exact issue is. Do you already have the code in place to display all records from the database using EF? If so you should post that. If not that's something you should ask about in another question. – Spencer Ruport Jan 14 '15 at 16:23
  • @SpencerRuport yes to get all records from the database using EF I do the following List people = db.People.ToList(); I can do db.people.where(x => x.name == parameter) but that won't work if the parameter says "All" because no one has a name of "All" – Abdul Ahmad Jan 14 '15 at 16:45
  • @AbdulAhmad Spencer and I's answers rest on the principle of checking if the parameter value = "ALL" if AND ONLY IF the parameter value is something other than "ALL" the filter will be applied to the IQueryable source. – Michael Humelsine Jan 14 '15 at 16:48
  • I just have one more question, what type of object is this query that you're using? how do I instantiate it? is it Query q = new Query()? then I do query = name etc... – Abdul Ahmad Jan 15 '15 at 04:53
2

If there are only four parameters then I would just use default parameter values and a conditional Linq Where clause. I included the StartsWith(), EndsWith(), and Contains() to show other possibilities.

Updated to clarify where the database interaction is happening.

public class Example {
    private IRepository repos;

    //pass in your database context abstract here
    public Example(IRepository repos){
        this.repos = repos;
    }

    public IEnumerable<Person> PostMethod(string name = "All", string age = "All",
    string height = "All", string weight = "All") {
    //reference your database abstract here
    return repos.People.Where(x => name == "All" || x.Name == name)
        .Where(x => age == "All" || x.Age.Contains(age))
        .Where(x => height == "All" || x.Height.StartsWith(height))
        .Where(x => weight == "All" || x.Weight.EndsWith(weight));
    }
}
  • the problem is I can't check if the prop == 'All' because that will return no results, there is no property that has a value of 'All' – Abdul Ahmad Jan 14 '15 at 16:28
  • You are correct, my code was wrong. I was typing too fast. Updated answer. – Michael Humelsine Jan 14 '15 at 16:31
  • I understand, so how do I access the database with this? would it databaseContext.People.?? I haven't used queries before so I'm not sure how to access the database after I get my results object – Abdul Ahmad Jan 14 '15 at 16:52
  • this is causing an exception to be thrown.. not sure why – Abdul Ahmad Jan 14 '15 at 20:58
  • What type of exception..? – Michael Humelsine Jan 14 '15 at 20:59
  • well, I fixed the exception, but the filter didn't work as planned, when I picked 'All' for the parameters, I got no results even though I should have gotten all people in my people table in the database, I'll update my question to show the code I used, but I have to go somewhere right now – Abdul Ahmad Jan 14 '15 at 23:35
  • Since you are using strings (and not nulls ex. Where(x => age == null || x.Age == age)) you need to make sure your strings are in the same case. I didn't do that in my example. I've used this technique hundreds of times so I know it works. If you are not getting the results you should then start stepping through the code and make sure it is the Linq that is not correct and not something else. – Michael Humelsine Jan 15 '15 at 12:54