Reputation: 2068
I have a query expression that takes an array of strings and should be generating a query that returns some items based on the query. However, it does not return anything. I think there is a closure problem, but I am not sure what it is.
public static Expression<Func<Item, bool>> IsKnownByIn(string[] query )
{
var i = PredicateBuilder.True<Item>();
foreach (string keyword in query)
{
string temp = keyword;
i = i.And(p=> p.Name.Contains(temp) || p.ID.ToString().Contains(temp));
}
return i;
}
I tried replacing the .Contains(temp) with .Contains(keyword) which causes the only the last string in query to be returned. In addition, replacing the i.And with i.Or causes every item (even those that do not contain any of the strings in query) to be returned. Any ideas on where the problem may be hiding?
Upvotes: 0
Views: 62
Reputation: 16257
When you tried the Or, you got them all because you start with true, i.e.
true or something or something
will always be true. Change the construction of i to be False instead.
In the code you present, your assigning keyword to temp is the correct approach when using PredicateBuilder and building up within a loop.
EDIT:
Based on your answer to my question, I would do this:
public static Expression<Func<Item, bool>> IsKnownByIn(string[] query )
{
var i = PredicateBuilder.False<Item>();
foreach (string keyword in query)
{
string temp = keyword;
i = i.Or(p=> p.Name.Contains(temp) || p.ID.ToString().Contains(temp));
}
return i;
}
Upvotes: 1
Reputation: 5327
So do you have items with all keywords specified in query? These should be the only ones which can pass your filter. Probably, you should use Or instead. The issue with Or you've seen might be because you start with PredicateBuilder.True, so 'true or expr1 or expr2 ... exprn' will yield true always. If you've used PredicateBuilder.False you should probably show more code so we can tell what is the issue.
Upvotes: 1