Phil
Phil

Reputation: 3994

Lambda expression problem

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

Answers (4)

Daniel Hilgarth
Daniel Hilgarth

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

Nasmi Sabeer
Nasmi Sabeer

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

Sam Holder
Sam Holder

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

Rafal Spacjer
Rafal Spacjer

Reputation: 4918

Select returns IEnumerable<TResult> and you want to return only one element - as Jon mentioned you should use Single

Upvotes: 1

Related Questions