Reputation: 3994
I'm new with lambda expressions and linq and can't figure out what I'm doing wrong here:
GroupSet groupToChange = context.GroupSet.Select(q => q.groupId == groupId);
I'm trying to get and change the name of an entity.
groupToChange.groupName = newGroupName;
I'm not having any problems with the second line though. Any ideas? It tells me I can't convert bool to GroupSet but the function returns what it finds, right?
Upvotes: 1
Views: 2949
Reputation: 174299
You want to use Where
instead of Select
.
Where
returns everything that matches the supplied lambda expression.
Select
is a transformation. It transforms each element using the supplied lambda expression.
Additionally, Where
returns an IEnumerable<T>
, because it can't know that only one element will match your condition. If you know it will only return one result, append Single
to the query, to return only one element. Only then it will compile:
GroupSet groupToChange = context.GroupSet.Where(q => q.groupId == groupId)
.Single();
If you are unsure, whether or not one element will match, use SingleOrDefault
:
GroupSet groupToChange = context.GroupSet.Where(q => q.groupId == groupId)
.SingleOrDefault();
The difference between those two:
Single
will throw an exception, if the result set of Where
is empty.
SingleOrDefault
will return default(T)
, i.e. null
in your case.
Upvotes: 5
Reputation: 1380
GroupSet groupToChange = context.GroupSet.Where(q => q.groupId == groupId);
Since you want the list filtered by the condition, use Where instead of Select.
groupToChange will be a collection, so you should assign the newGroupName to individual elements in the collection, if it has only one element you could do the following
groupToChange.Single().groupName = newGroupName;
otherwise you have to iterate through each element and assign them
foreach(var g in groupToChange)
g.groupName = newGroupName;
Also look at SingleOrDefault, First, FirstOrDefault methods
Upvotes: 3
Reputation: 32936
The Select
is a transformation as has been pointed out, so when you say:
.Select(q => q.groupId == groupId)
what you get is a list of booleans based on if the element in the GroupSet has a groupId equal to the given groupId
it sort of like doing:
List<bool> results = new List<bool>;
foreach(group in GroupSet)
{
results.Add(group.goupId==groupId);
}
return results;
What you want is either
Where
which will filter based on the lambda expression and return all instances that match the filter.First
which will return the first element that matches the lambda expression(and throw an exception if none do)FirstOrDefault
which will return the first element which matches or the default (probably null in this case) if none match. Single
will return the only element that matches and throw an exception if there is not exactly one SingleOrDefault
will return the only element that matches or the default (probably null) if none matches but throw an exception if there is more than one.Exactly which to choose depends on such factors as, will the list always contain an element which matches? Is it an error condition if not? will there be more than 1? Is more than 1 an error condition. Obviously if you know there will only ever be one then First
will be quicker as it will stop when it hits the first one, but Single
will iterate until it checks the whole list or finds a second element.
Upvotes: 2
Reputation: 4918
Select
returns IEnumerable<TResult>
and you want to return only one element - as Jon mentioned you should use Single
Upvotes: 1