29

我正在学习 LINQ-to-SQL,一切都很顺利,直到发生了一些奇怪的事情:

我试图做一个例子distinct,所以,使用 Northwind 数据库,我编写了以下查询:

var query = 
    from o in db.Orders
    orderby o.CustomerID
    select new
    {
        o.CustomerID
    };

如果我打印 LINQ-to-SQL 为存储在其中的查询生成的 SQL,query它看起来像这样:

SELECT [t0].[CustomerID]
FROM [dbo].[Orders] AS [t0]
ORDER BY [t0].[CustomerID]

因此,像往常一样,查询将按字母顺序排列的表中的所有CustomerIDfor each 。OrderOrders

但!如果我使用这样的Distinct()方法:

var query = (
    from o in db.Orders
    orderby o.CustomerID
    select new
    {
        o.CustomerID
    }).Distinct();

查询带来了Distinct子句的预期结果,但是CustomerID尽管我写了 s 没有排序orderby o.CustomerID

第二个 LINQ 查询的 SQL 查询如下:

SELECT DISTINCT [t0].[CustomerID]
FROM [dbo].[Orders] AS [t0]

正如我们所见,**ORDER BY缺少该子句。这是为什么?

为什么ORDER BY我使用该Distinct()方法时该子句会消失?

4

4 回答 4

53

来自Queryable.Distinct 文档

预期的行为是它返回源中唯一项的无序序列。

换句话说,现有的 IQueryable 具有的任何订单在您使用Distinct()它时都会丢失。

您想要的可能更像是这样,在 Distinct() 完成后的 OrderBy() ;

var query = (from o in db.Orders
             select new
             {
                 o.CustomerID
             }).Distinct().OrderBy(x => x.CustomerID);
于 2012-09-14T17:13:43.433 回答
17

尝试重新排列成员以将 OrderBy 放在 Distinct 之后。您必须恢复到方法链接:

db.Orders.Select(o=>o.CustomerId).Distinct().OrderBy(id=>id);

无论如何,这将是在 Enumerable Linq 中设置查询的更有效方法,因为 OrderBy 将只对唯一项目而不是对所有项目进行操作。此外,根据MSDN, Enumerable.Distinct 无论如何都不能保证元素的返回顺序,因此在重复数据删除之前排序是没有意义的。

于 2012-09-14T17:13:33.550 回答
4

由于使用distinct,返回列表的顺序无法保证。LinqToSql 足够聪明,可以识别这一点,因此它会忽略它。

如果您在 Distinct 之后下订单,一切都会如您所愿。

var query = (from o in db.Orders
             select new
             {
                 o.CustomerID
             }).Distinct().OrderBy(o => o.CustomerID);

或者

var query = db.Orders.Select(o => o.CustomerID).Distinct().OrderBy(o => o.CustomerID);

请参阅这篇文章以获得澄清:

http://programminglinq.com/blogs/marcorusso/archive/2008/07/20/use-of-distinct-and-orderby-in-linq.aspx

于 2012-09-14T17:13:34.587 回答
2

您可以使用以下结构模拟 ORDERBY 和 DISTINCT:

var distinctItems = employees.GroupBy(x => x.EmpID).OrderBy(x => x).Select(y => y.First());
于 2015-07-14T12:39:34.813 回答