How can I use a Lambda bool method within a WHERE clause? - c#

I have a method IsMatchingRegex which will return true or false. I want to check whether the Lambda property matches against the IsMatchingRegEx. If it does match, it should be added to the validItems List. How can I make the Lambda Expression work without changing the TRUE/FALSE method?
validItems = items.Where(x => x.Sub.PropertyToCheck == IsMatchingRegex(x.Sub.PropertyToCheck))

Why compare equality to the property? Just:
validItems = items.Where(x => IsMatchingRegex(x.Sub.PropertyToCheck));
The Where expects a predicate that given an item of the collection returns for it true or false. If you method already does that - just call it.

Related

Create empty lambda expression

Consider the function:
public async Task<IEnumerable<Purchases>> GetPurchases(User user, Expression<Func<Purchases, bool>> whereClause)
{
using (var context = new UserDbContext())
{
context.Users.Attach(user);
context.Entry(user).Collection(p => p.Purchases)
.Query()
.Where(whereClause)
.Load();
if (Equals(user.Purchases, null))
return new List<Purchases>();
}
return user.Purchases;
}
In this function the parameter whereClause can at times be null, I'm wanting to check if its null and then assign an empty Expression if so. This is as close as I've come:
if (Equals(whereClause, null))
whereClause = () => { };
This was based on the question here, but for the line that makes whereClause empty I'm getting the error.
Error 7 Not all code paths return a value in lambda expression of type
'System.Func'<'Purchases,bool>'
Anyone know how this could be corrected?
"Not all code paths return a value" means your lambda isn't returning anything. I mean, it's got only one code path, and it's not a long one.
Where requires a lambda which takes one parameter, and returns bool. Where won't let you give it an empty lambda expression.
You need to give it something it can use to filter items with.
That's actually easy:
if (Equals(whereClause, null))
whereClause = o => true;
That's a where clause that always returns true, regardless of what you give it. That's probably what you want: If there's no filter, include everything. For each item in the enumeration, one at a time, Where gives the lambda the item as o. If the lambda returns true, it includes that value of o in the results.
If you want a null filter to return no items, just return false instead:
if (Equals(whereClause, null))
// Whatever it is, I'm against it.
whereClause = o => false;
whereClause must return a boolean value to use it in LinQs Where method.
Assuming you don't want to filter the list (include all items) you must return true, otherwise false:
if (Equals(whereClause, null))
whereClause = () => true;
Notice: The { and } are not necessary if you only return a value with a single statement.
But you should know that the most framework methods don't work in this way. They would throw an ArgumentNullException instead of setting a value.
Assuming that when whereClause is null you don't want to apply any filter.
using (var context = new UserDbContext())
{
context.Users.Attach(user);
context.Entry(user).Collection(p => p.Purchases)
.Query()
.Where(whereClause ?? p => true)
.Load();
if (Equals(user.Purchases, null))
return new List<Purchases>();
}

Enumerable.Where(predicate) vs. Enumerable.All(predicate)

What's the difference between:
items.Where(i => i.Foo == "bar")
and
items.All(i => i.Foo == "bar")
? Seems like they'd do the exact same thing - is this actually the case, or do they behave differently in some subtle way?
Where<T> returns an IEnumerable<T> and acts as a filter for your collection:
Enumerable.Where Method
Filters a sequence of values based on a predicate.
In your case, it returns all elements where the Foo property equals "bar".
All<T> returns a bool and just checks if all elements in your collection satisfies the given predicate:
Enumerable.All Method
Determines whether all elements of a sequence satisfy a condition.
In your case, it returns true when the Foo property of all elements equals "bar", otherwise false.
items.Where - filters based on condition and returns a collection of filtered objects.
items.All - returns true if all objects in the collection satisfy the condition, and false otherwise.
Does not look the exact same thing , does it?
Enumerable.All returns a bool value that indicates whether all the elements in question satisfy the condition that is expressed by the predicate.
Enumerable.Where returns a generic IEnumerable collection that contains only the items that satisfy the said condition.
I do not see anything in common between the results that are being returned from those LINQ functions - one is a bool, the other is a collection. Yes, they are similar in syntax, but are used in completely different situations.
A quick example:
Let's say you have an int list:
List sampleList = new List { 3, 4, 6, 9 };
If you run
sampleList.All(v => v % 3 == 0);
you will get false because 4 does not satisfy the condition.
If you run
sampleList.Where(v => v % 3 == 0);
you will receive an IEnumerable containing the values that satisfy the condition: 3, 6 and 9/

PredicateBuilder is still true even after adding explicit false statement

I have the following statement.
var search = PredicateBuilder.True<SomeType>();
search.And(f => false);
// Still the "search" variable value is: {f => true}.
At first, I was trying an expression; nothing succeeded, so I tried this "false" instead. No matter what I did, it's still the same. What is happening?
PredicateBuilder methods don't mutate the expression (they couldn't, as expression trees are immutable) - you need to use the return value:
var search = PredicateBuilder.True<SomeType>();
search = search.And(f => false);

Rewriting a Linq statement

Here is what I currently have:
from s in domainThreads.Values
where (s.IsAvailable)
select s;
but I'm still learning Linq and believe that I can get it all on one line. Does the following look correct?
domainThreads.Values.Where(s => s.IsAvailable).Any();
Do I need the .Any()?
Any() returns a boolean indicating whether or not there are any entities in the given set.
The equivalent of your original LINQ expression would simply be:
domainThreads.Values.Where(s => s.IsAvailable)
The two are not equivalent.
The first returns all Values where s.IsAvailable.
The second returns whether there are any such values.
A correct conversion is:
domainThreads.Values.Where(s => s.IsAvailable)
Which translates to:
domainThreads.Values.Where(s => s.IsAvailable).Select(s => s)
Which is what the original query gets transformed to anyways.
You don't need the Any() -- that will return a bool indicating if any of elements satisfy the condition.
Instead, just do:
domainThreads.Values.Where(s => s.IsAvailable)
domainThreads.Values.Where(s => s.IsAvailable)
is enough.
Any() returns a bool value, but your original query returns a data set. So just use Where()
var result = domainThreads.Values.Where(s => s.IsAvailable);
Any() would be helpful when you just need ensure that at least single item satisfies a condition
Try this
var obj = domainThreads.Values.Where(s => s.IsAvailable == true).Select(o => o);
If you call Any() it returns bool which indicates that you have at least one item.
domainThreads.Values.Where(s => s.IsAvailable);
this expression is enough and it is equivalent to the LINQ statement.
Any() returns a boolean that is true if the result contains one or more items.
var elements = from s in domainThreads.Values
where (s.IsAvailable)
select s;
//elements now contains a list of objects.
This is equivalent to:
elements = domainThreads.Where(s => s.IsAvailable);
It looks but is not the same. The result is boolean and returns true if the collection contains any elements.
You could write something like this, but is it really worth the effort?
var result = domainThreads.Values.Where(s => s.IsAvailable).Select(s => s);
or shorter:
var result = domainThreads.Values.Where(s => s.IsAvailable);
EDIT: if you just want to have one line of code you can also write:
from s in domainThreads.Values where s.IsAvailable select s;
It's much more readable and generates to the same code in the end.

Linq expression that would always return true

I need to pass a parameter to a method that requires an Expression<Func<T, bool>>.
How to do I pass an expression that would always return true?
Using obj => true doesn't work because the framework complains at runtime that it cannot determine the memeber type from the True constant.
If you have a function like this
void TakeExpression<T>(Expression<Func<T, bool>> expr)
You should call it this way, specifying the T type :
TakeExpression<int>(_ => true)
It should work.
You need to define the parameter type you are passing:
(object o) => true
Or
(int a) => true
We can achieve the result as follows.
Consider context as your DbContext instance and Entity as your entity class name.
context.Entity.Where(t=> t.EntityID == t.EntityID);
By doing this the where clause will always return true and all the data will be shown.
There are two problems here:
1) If you're passing a predicate such that you always want to return true, then it's not much of a predicate. You may be able to omit whatever call you are trying to make.
2) If you want to just return true, you can simple use a more verbose lambda syntax to get what you want:
sample.AsQueryable().Where((x) => { return true; });
The more verbose syntax allows you to specify closer to an anonymous function while still being an expression.

Categories

Resources