LINQ Group By Wrong Results

Viewed 318

My table

userid                                       UserApproveLevel_Two_T
1118bda4-6cba-43d6-a0cd-555555555555               True
22299872-aa01-498a-831d-555555555555               False
333a8ddb-d261-47d9-8ec8-555555555555               False

-

 var sky = DB.UserSkypeTrackers.GroupBy(x => x.UserApproveLevel_Two_T == true).FirstOrDefault();

-

 foreach (var item in sky )
  {
       // in here    i see  
       //22299872-aa01-498a-831d-555555555555
       //333a8ddb-d261-47d9-8ec8-555555555555        
  }

-

i should be seeing

1118bda4-6cba-43d6-a0cd-555555555555

in my foreach

why i see false results??

Thanks

2 Answers

The Enumerable.GroupBy method in LINQ to Objects preserves the order of the groupings, as per the docs:

The IGrouping<TKey,TElement> objects are yielded in an order based on the order of the elements in source that produced the first key of each IGrouping<TKey,TElement>. Elements in a grouping are yielded in the order they appear in source.

Which is probably what you expected to see 111....

However, you seem to be using GroupBy on a database table or something like that. This means that you are using Queryable.GroupBy. According to its docs,

The query behavior that occurs as a result of executing an expression tree that represents calling GroupBy<TSource,TKey>(IQueryable<TSource>, Expression<Func<TSource,TKey>>) depends on the implementation of the type of the source parameter. The expected behavior is that it groups the elements of source by a key value that is obtained by invoking keySelector on each element.

As you can see, the exact behaviour is implementation specific, and it doesn't have to preserve the order. Therefore, the first IGrouping is not necessarily the group with the key true.

So to get your desired results, either:

  • use Where to find the group with the key true, or
  • Load all the objects into memory first, then use LINQ to Object's GroupBy. (This could be slow if you have a lot of objects in the database)

GroupBy() groups the element present in List based on specified pradicates. In your case you are trying to get elements whose UserApproveLevel_Two_T property set to True,

Instead of GroupBy(), you can use Where() clause to achieve expected result

 var sky = DB.UserSkypeTrackers.Where(x => x.UserApproveLevel_Two_T).FirstOrDefault();

Bonus :

As you are checking condition against bool variable, no need to check == true condition, .Where(x => x.UserApproveLevel_Two_T) will work instead of .Where(x => x.UserApproveLevel_Two_T == true)

sky variable contains single record as you are calling FirstOrDefault(); after where clause. Here FirstOrDefault() will return single element or default value from collection. So no need to iterate over sky

Related