C# Linq 按对象分组

C# Linq Group by Object

我在 LINQ to SQL 语句中使用 group by 时遇到问题。

我的鳕鱼是

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();

我尝试用两种不同的方式进行分组。第一种方式,我按对象分组,第二种方式我只按其中一个对象中的字段分组。

当我 运行 groups1 时,我收到一条错误消息,提示需要在客户端进行评估,而当我使用 groups2 时,一切正常。请问有什么问题吗?如果我想按对象分组,有什么办法吗?

如果您想按对象分组,因为您没有在 Article class 中覆盖 EqualsGetHashCode() 或实现 IEqualityComparer<Article>您只是获得默认比较,它检查引用是否相等。所以你需要的是这样的:

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();
    }
}

然后您需要将查询更改为 lambda 表达式:

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

如果您在将方法转换为 SQL 时遇到任何异常,您可以在 GroupBy 方法之前使用 AsEnumerableToList 方法,在之后使用此方法加载数据后,将使用 Linq to Objects 对内存中已有的数据执行任何进一步的操作。

正如其他人指出的那样,GroupBy 默认使用 引用相等性 ,您可以通过指定一个或多个 来绕过它properties 作为分组依据。但是为什么会出错

查询的重点是将您的 Linq 查询转换为 SQL。由于客户端上的对象引用相等性不能轻易翻译成 SQL,翻译器不支持它并给你一个错误。

当您提供一个或多个属性作为分组依据时,提供商可以将其转换为SQL(例如GROUP BY article.Id), 因此第二种方法没有错误。