Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq to Sql Group By Class

I would like to pass a groupedList to several functions, however I'm getting strange results when trying to group by using a class rather than an anonymous type. In the following example the anonymous type returns 2 results, as expected, but the concrete class returns 5, as if it wasn't even grouped.

The Question: Is it possible to do Linq to Sql Group By with concrete classes?

public class person
{
    public string Name;
    public string State;
}

public class personGroup
{
    public string State;
    public personGroup(string personState)
    {
        State = personState;
    }
}


void Main()
{   
    var people = new List<person>();
    people.Add(new person {Name = "Bob", State = "Tx"});
    people.Add(new person {Name = "Bill", State = "Tx"});
    people.Add(new person {Name = "Tracy", State = "Tx"});
    people.Add(new person {Name = "Steve", State = "Md"});
    people.Add(new person {Name = "Kelly", State = "Md"});

    var groupedPeople = people.GroupBy (p => p.State );
    groupedPeople.Count().Dump();//Returns 2

    var morePeople = people.GroupBy (p => new personGroup(p.State) );
    morePeople.Count().Dump();//Returns 5
}
like image 947
SumGuy Avatar asked Nov 06 '14 21:11

SumGuy


People also ask

How to group in LINQ C#?

The Linq GroupBy in C# belongs to the Grouping Operators category and exactly does the same thing as the Group By clause does in SQL Query. This method takes a flat sequence of elements and then organizes the elements into groups (i.e. IGrouping<TKey, TSource>) based on a given key.

How does GroupBy work LINQ?

The working of the GroupBy operator is similar to the SQL GroupBy clause. It is used to return the group of elements which share the common attributes or key from the given sequence or collection. Every group is represented by IGrouping<TKey, TElement> object.

What does GroupBy do in C#?

GroupBy() Method in C# The GroupBy() is an extension method that returns a group of elements from the given collection based on some key value. arr. GroupBy(b => chkSmaller(b)); The above chkSmaller() finds the elements smaller than 50.

What does GroupBy function do in SQL?

The GROUP BY statement groups rows that have the same values into summary rows, like "find the number of customers in each country". The GROUP BY statement is often used with aggregate functions ( COUNT() , MAX() , MIN() , SUM() , AVG() ) to group the result-set by one or more columns.


2 Answers

The GroupBy method uses EqualityComparer<T>.Default to compare the items in question when a custom IEqualityComparer is not provided (you did not provided one). This will be based on the implementation of IEquatable<T> of the type T in question, if there is one, and if not, then it will simply use object.Equals and object.GetHashCode of that type.

Your custom type does not provide any implementation whatsoever, it relies entirely on the implementations defined in object, which, for a reference type, is based on the reference of the object. Each of the personGroup objects you created have a different reference, and so are different.

Anonymous types don't use that default equality behvaior; they override the definition of Equals and GetHashCode to be dependent on the identity of each of the properties they represent.

If you want to use your own custom type to group on, and the default equality semantics aren't what you want, you'll need to either provide a custom IEqualityComparer implementation, or override Equals and GetHashCode for the type in question.

like image 148
Servy Avatar answered Oct 06 '22 01:10

Servy


In your second group by, there are 5 groups because the key is always different. personGroups are compared by reference, and all of the objects have different references.You need to override Equals and GetHashCode methods in your personGroup class to compare your instances based on State, or implement an IEqualityComparer<personGroup> and pass it to GroupBy.

like image 32
Selman Genç Avatar answered Oct 06 '22 00:10

Selman Genç