IQueryable.Distinct() vs List.Distinct()

本文关键字:Distinct List vs IQueryable | 更新日期: 2023-09-27 18:20:28

我有一个正在使用Distinct()的linq查询。如果我只是调用Distinct()而不转换为List,那么它不会返回不同的列表-它仍然包含重复的列表。

但是,如果我转换为List并,则调用Distinct()——它按预期工作,并且我只得到唯一的对象。

我使用的是Telerik ORM,返回的对象是表示数据库中某个表的类。

var uniqueUsers = (from u in Database.Users 
                   select u).Distinct();

上面的代码不会产生不同的结果,但是当我转换到列表并调用distinct时,它确实会:

var uniqueUsers = (from u in Database.Users 
                   select u).ToList().Distinct();

我怀疑这与转换为列表之前的集合有关,将引用与对象进行比较,而不是与对象数据本身进行比较,但我不完全理解发生了什么——为什么第一个代码示例没有产生唯一的结果,以及在使用.ToList()时集合会发生什么?

[EDIT]我简化了上面的查询,在现实世界中,查询有几个联接,它们生成非唯一的结果,但我只返回User对象。

我尝试覆盖EqualsGetHashCode方法,但这没有任何区别。

public override bool Equals(object obj)
{
    User comparingObject = obj as User ;
    if (comparingObject == null)
    {
        return false;
    }
    else
    {
        return comparingObject.UserID.Equals(this.UserID);
    }
}
public override int GetHashCode()
{
    return this.UserID.GetHashCode();
}

[更新]在LinqPad中运行相同的查询后,它可以按预期工作,提供不同条目的列表。然而,当使用Telerik ORM dll时,在LinqPad中运行相同的查询,我会得到多个条目。因此,似乎是Telerik的一个特点。当我有时间的时候,我会进一步调查,并在Telerik的支持下提出。

IQueryable.Distinct() vs List.Distinct()

显然,表中不能有完全重复的行(包括主键)。您的意思可能是具有一些相等字段的行(不包括主键)。

IQueryable上调用Distinct,在生成的查询上生成一个SQL DISTINCT运算符,该运算符将表中的每个字段相互比较。因为表中不能有完全重复的行,所以它会返回所有行。

另一方面,在List<User>上调用Distinct将使用User对象的Equals方法来比较内存中的对象(在从数据库中获取所有行之后)。最终结果取决于Equals方法的实现,该方法只能检查某些字段的相等值。