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对象。
我尝试覆盖Equals
和GetHashCode
方法,但这没有任何区别。
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
,在生成的查询上生成一个SQL DISTINCT
运算符,该运算符将表中的每个字段相互比较。因为表中不能有完全重复的行,所以它会返回所有行。
另一方面,在List<User>
上调用Distinct
将使用User
对象的Equals
方法来比较内存中的对象(在从数据库中获取所有行之后)。最终结果取决于Equals
方法的实现,该方法只能检查某些字段的相等值。