2012-09-14 38 views
16

Tôi đang tìm hiểu về LINQ-to-SQL và tất cả mọi thứ đã tiến triển tốt cho đến khi một cái gì đó kỳ lạ đã xảy ra:DISTINCT() và ORDERBY vấn đề

tôi đã cố gắng để làm cho một ví dụ về distinct, vì vậy, sử dụng dabatase Northwind Tôi đã viết truy vấn sau đây:

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

Nếu tôi in SQL được tạo ra bởi LINQ-to-SQL cho truy vấn được lưu trữ trong query nó trông như thế này:

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

Vì vậy, như thường lệ, truy vấn mang tất cả CustomerID cho mỗi Order trong bảng Orders được sắp xếp theo thứ tự bảng chữ cái.

Nhưng! Nếu tôi sử dụng phương pháp Distinct() như thế này:

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

Truy vấn mang lại kết quả mong đợi của mệnh đề Distinct, nhưng CustomerID s không ra lệnh mặc dù tôi đã viết orderby o.CustomerID!

Truy vấn SQL cho truy vấn LINQ thứ hai này là như sau:

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

Như chúng ta có thể thấy ** mệnh đề ORDER BY là mất tích. Tại sao vậy?

Tại sao mệnh đề ORDER BY biến mất khi tôi sử dụng phương thức Distinct()?

+1

Là một dành cú pháp lambda là đơn giản hơn nhiều cho các truy vấn như thế này: 'var query = db.Orders.Select (o => o .CustomerId) .Distinct(); ' – asawyer

Trả lời

28

Từ Queryable.Distinct documentation;

Hành vi mong đợi là nó trả về chuỗi thứ tự không có thứ tự các mục duy nhất trong nguồn.

Nói cách khác, bất kỳ thứ tự nào mà IQueryable hiện có bị mất khi bạn sử dụng Distinct() trên đó.

Những gì bạn muốn có thể là một cái gì đó giống như thế này, một OrderBy() sau Distinct() được thực hiện;

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

Hãy thử sắp xếp lại các thành viên để đặt OrderBy sau Sự khác biệt. Bạn sẽ phải trở lại phương pháp chaining:

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

Đây sẽ là cách hiệu quả hơn để thiết lập truy vấn trong LINQ Enumerable dù sao, vì OrderBy sau đó sẽ hoạt động chỉ vào các mục duy nhất và không trên tất cả các chúng. Ngoài ra, theo số MSDN, Enumerable.Distinct không đảm bảo thứ tự trả lại của các phần tử, vì vậy việc đặt hàng trước khi deduping là vô nghĩa.

+3

Không có thiết kế. – asawyer

+0

... Có nó là: http://msdn.microsoft.com/en-us/library/system.linq.enumerable.distinct.aspx. Câu hỏi đặt ra là, tại sao Distinct không duy trì thứ tự của các yếu tố đầu vào, khi nó dễ dàng như vậy có thể bằng cách mang lại lợi nhuận? – KeithS

+2

@KeithS Bạn đã đọc liên kết của mình ... "Chuỗi kết quả không có thứ tự." Nó không phải là một lỗi khi nó được xây dựng trong thiết kế. –

3

Do việc sử dụng riêng biệt, thứ tự của danh sách được trả về không được đảm bảo. LinqToSql đủ thông minh để nhận ra điều này, do đó nó bỏ qua nó.

Nếu bạn đặt hàng vào SAU KHI PHÂN TÍCH, mọi thứ sẽ diễn ra như bạn mong muốn.

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

hoặc

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

hãy xem bài viết này để làm rõ:

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

1

Bạn có thể mô phỏng ORDERBY và DISTINCT với counstruction này:

var distinctItems = employees.GroupBy(x => x.EmpID).OrderBy(x => x).Select(y => y.First()); 
Các vấn đề liên quan