C# IQueryable.Distinct()与List.Distinct()的比较
我有一个linq查询,我正在上使用C# IQueryable.Distinct()与List.Distinct()的比较,c#,linq,distinct,iqueryable,telerik-open-access,C#,Linq,Distinct,Iqueryable,Telerik Open Access,我有一个linq查询,我正在上使用Distinct()。如果我只调用Distinct(),而不转换为列表,那么它不会返回一个Distinct列表-它仍然包含重复项 但是,如果我转换为一个列表,然后调用Distinct(),它将按预期工作,并且我只得到唯一的对象 我使用的是Telerik ORM,返回的对象是表示数据库中一个表的类 var uniqueUsers = (from u in Database.Users select u).Distinct()
Distinct()
。如果我只调用Distinct()
,而不转换为列表,那么它不会返回一个Distinct列表-它仍然包含重复项
但是,如果我转换为一个列表,然后调用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()
时集合会发生什么情况,这使得它能够工作
[编辑]我简化了上述查询,在现实世界中,查询有几个连接,这些连接生成非唯一的结果,但我只返回用户对象
我尝试重写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
,在生成的查询上生成一个SQLDistinct
运算符,该运算符将表中的每个字段相互比较。由于表中不能有完全重复的行,因此它将返回所有行
另一方面,在
列表上调用Distinct
将使用User
对象的Equals
方法来比较内存中的对象(从数据库中获取所有行之后)。最终的结果取决于Equals
方法的实现,该方法只能检查一些字段的值是否相等。您看过生成的SQL是什么样子吗?我不清楚,如果你只是列出一个表的内容,你怎么能在第一时间得到重复的内容。。。这似乎很奇怪。也许你在代码中覆盖了Jon Skeet所说的Equals
。你覆盖了User
对象的Equals
方法了吗?如果是这样的话,你的两个案例之间会有很大的不同。@JonSkeet&MD.Unicorn-抱歉,我已经为这个问题添加了更多的细节。如果你能尝试提出一个最小的例子来说明问题,并包括为此生成的SQL,那将是很有帮助的。这可能是显而易见的,但也要注意在DB中这样做(iqeryable上的Distinct)的速度要快得多,因为每一行都不必传输到你的应用程序中,也不必转换为C#objects。我将此标记为答案-尽管这个问题似乎是一个Telerik ORM问题(因为它在LinqPad中工作正常)。这个答案向我阐明了iqeryable.Distinct
和ToList()的原理.Distinct
DISTINCE使我走上了确定问题的道路。当我有时间向Telerik提出问题并获得更多信息时,我将发布更新。这正是我要找的东西。+1 mate。