Any alternative for this 'Where' LINQ query - c#

i have this linq query. I need to look for any good alternative if possible for this higlighted lambda expression inside Where condition. I was thinking to use coalesce condition ( ?? ) but couldnt make a query.
.Where(p => p.Property== null ? true : p.Property.SubPropertyList.Contains(Item))
So, I want to get those items from list which has a property null or if not null then satisfies a condition ( Contains() )

You need to create a predicate.
A function that will return true of false.
In you case:
.Where(***p => p.PalletMission == null || p.PalletMission.Destinations.Contains(currentGtpOrder.GtpStation.Node))

var result = list
.Where(p =>p.Property == null || p.Property?.SubPropertyList.Contains(1) == true);

Related

Returning Wrong value in LINQ .Any()

I have a method which return a List of Class object.
After getting the list I want to check whether a specific entry exists or not
Below is my query
var myList = GetMethod()
if(myList != null && myList.Select(x => x.Id=='MyId').Any())
{
// Do work
}
If the mylist is not null then myList.Select(x => x.Id=='MyId').Any() is always returning true even if a matching entry is not there.
Can someone help me in this?
That is because you need a Where over a Select:
if(myList != null && myList.Where(x => x.Id=='MyId').Any())
Now the Select ends up with an enumerable of booleans... Some are true, some are false.
You could simply that to:
if(myList != null && myList.Any(x => x.Id=='MyId'))
Select returns an IEnumerable of booleans whether the condition was true for each item or not. So, Any() is always returning true as long as there are items in your list.
Just use:
myList?.Any(x => x.Id == "MyId") == true;
Note that I don't like boolean comparisons like == true but this is for the null-check with ?. upfront.

Using multiple clauses in where

What is the correct way to include multiple wheres in a LINQ call for OR
List<Pos> posList = DbContext.PosList
.Where<Pos>(p => p.Pos == "51000785" ||
p => p.Pos == "123")
.ToList<Pos>();
The Linq where clause takes one expression and returns one bool value. Yours is taking two expressions each with their own return value. You would need to combine these two into one lambda expression that returns one value rather than the two separate ones in your example.
List<Pos> posList = DbContext.PosList
.Where<Pos>(p => p.Pos == "51000785" || p.Pos == "123")
.ToList<Pos>();

LINQ search query doesn't work

I'm trying to write a search query in LINQ. Below is the where condition.
where (!string.IsNullOrEmpty(nameWithInitials)
&& tb.NameWithInitials.Contains(nameWithInitials))
&& (!string.IsNullOrEmpty(studentRegNo)
&& tbSR.StudentRegistrationNo.Contains(studentRegNo))
&& (!string.IsNullOrEmpty(NIC) && tb.NIC.Contains(NIC))
&& (!string.IsNullOrEmpty(fullName) && tbi.Name.Contains(fullName))
It doesn't return any values if I pass a single parameter. For example if I pass 'Chamara' as fullname it doesn't return any result but if I pass all the parameters at the once then it returns the matching records.
I need to get this to work even when I pass several parameters dynamically
You are using AND (&&) everywhere, so if at least one of these conditions is false, your where condition will be false. Try using OR conditions instead:
where (string.IsNullOrEmpty(nameWithInitials) || tb.NameWithInitials.Contains(nameWithInitials))
&& (string.IsNullOrEmpty(studentRegNo) || tbSR.StudentRegistrationNo.Contains(studentRegNo))
&& (string.IsNullOrEmpty(NIC) || tb.NIC.Contains(NIC))
&& (string.IsNullOrEmpty(fullName) || tbi.Name.Contains(fullName))
In this case in any of these conditions if you have empty parameter, only the first part of condition will be evaluated, otherwise the second condition will be evaluated.
One potential issue is that Entity Framework might not be able to translate this to actual SQL. In this case, you can use such approach:
var query = // your original query without where condition
// Check if the condition is valid and only then add where condition
if(!string.IsNullOrEmpty(nameWithInitials))
{
query = query.Where(tb => tb.NameWithInitials.Contains(nameWithInitials));
}
// repeat this for all other conditions
What you're asking is semi-confusing but i think you want to search for every string if exists, which translates to
where ((string.IsNullOrEmpty(nameWithInitials)
|| tb.NameWithInitials.Contains(nameWithInitials))
&& (string.IsNullOrEmpty(studentRegNo)
|| tbSR.StudentRegistrationNo.Contains(studentRegNo))
&& (string.IsNullOrEmpty(NIC) || tb.NIC.Contains(NIC))
&& (string.IsNullOrEmpty(fullName) || tbi.Name.Contains(fullName))

Lambda vs LINQ- "Expression is always false"

I have the following code:
var thing = (from t in things
where t.Type == 1 && t.IsActive
select t).SingleOrDefault();
if (thing == null)
{
// throw exception
}
things is a collection of Entity Framework Self-Tracking Entities
This works nicely, however I want to use a Lambda expression instead and changed the LINQ to this:
var thing = things.Select(t => t.Type == 1 && t.IsActive).SingleOrDefault();
Now Resharper is telling me Expression is always false for (thing == null).
What have I missed?
You want:
var thing = things.Where(t => t.Type == 1 && t.IsActive).SingleOrDefault();
Select performs a projection (converting the type of the IEnumerable from IEnumerable<Thing> to IEnumerable<bool> with values true if t.Type == 1 && t.IsActive == true, otherwise false), then the SingleOrDefault returns either the only bool in this sequence, or the default value of a bool which is false if the sequence is empty. This can never be null since bool is not a reference type.
Where performs a filtering action (pulling out only those objects that meet a given criterion - in this case only selecting those where Type is 1 and IsActive is true), leaving the type of the IEnumerable as IEnumerable<Thing>. Assuming Thing is a class, the SingleOrDefault will return the only item in the sequence or null.
In either case, SingleOrDefault will throw an exception if the sequence contains more than one item (which is far more likely in the Select version!).

Using Contains() on Collection of Anonymous Types

I'm still learning LINQ and I have a collection of anonymous types obtained using something like the following. [mycontext] is a placeholder for my actual data source:
var items = from item in [mycontext]
select new { item.col1, item.col2, item.col3 };
How can I use items.Contains() to determine if items contains a matching value?
The value I am searching for is not an anonymous type. So I will need to write my own compare logic, preferably as a lambda expression.
If you prefer to use a predicate then you're probably better off using Any rather than Contains:
bool exists = items.Any(x => x.col1 == "foo"
&& x.col2 == "bar"
&& x.col3 == 42);
Try the LINQ Any() method:
if (items.Any(i => i.col1 == myOtherThing.Value))
{
// Effectively Contains() == true
}
Or you could use the "Any" method with a predicate.
bool exists = items.Any( i => {logic} );

Categories