C# Linq Group by Object

帅比萌擦擦* 提交于 2021-01-28 09:11:09

问题


I have an issue of using group by in LINQ to SQL statement.

The cod I have is

var combinedItems = (from article in articles
                     join author in authors
                     on article.AuthorId equals author.Id into tempAuthors
                     from tempAuthor in tempAuthors.DefaultIfEmpty()
                     select new { article , author = tempAuthor});

var groups1 = (from combinedItem in combinedItems
               group combinedItem by combinedItem.article into g
               select g.Key).ToList();

var groups2 = (from combinedItem in combinedItems
               group combinedItem by combinedItem.article.Id into g
               select g.Key).ToList();

I tried to group in two different ways. The first way, I group by an object and the second way I just group by a field in one of the objects.

When I run groups1, I got an error saying need to evaluate in client side, while when I use groups2, it works all good. Can I ask what could be wrong? If I want to group by object, is there any way to do it?


回答1:


In case you want to group by object, as you've not overridden Equals and GetHashCode() in your Article class or implemented IEqualityComparer<Article> you're just getting the default comparison, which checks if the references are equal. So what you need is something like this:

class GroupItemComparer : IEqualityComparer<Article>
{

    public bool Equals(Article x, Article y)
    {
        return x.Id == y.Id &&
            x.Name == y.Name;
    }

    public int GetHashCode(Article obj)
    {
        return obj.Id.GetHashCode() ^
            obj.Name.GetHashCode();
    }
}

And then you need to change your query to lambda expression:

var groups1 = combinedItems.GroupBy(c => c.article , new GroupItemComparer())
                           .Select(c => c.Key).ToList();

In case you got any exception regarding translation your method to SQL, you can use AsEnumerable or ToList methods before your GroupBy method, with this methods after data is loaded, any further operation is performed using Linq to Objects, on the data already in memory.




回答2:


As others have pointed out, the GroupBy is using reference equality by default, and you could get around it by specifying one or more properties to group by. But why is that an error?

The whole point of the query is to translate your Linq query into SQL. Since object reference equality on the client can't be easily translated to SQL, the translator doesn't support it and gives you an error.

When you provide one or more properties to group by, the provider can translate that to SQL (e.g. GROUP BY article.Id), and thus the second method works without error.



来源:https://stackoverflow.com/questions/61164667/c-sharp-linq-group-by-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!