2009-12-14 34 views
10

tôi đã làm các truy vấn sau đây:Tại sao linq sau để truy vấn sql tạo truy vấn phụ?

var list = from book in books 
      where book.price > 50 
      select book; 

list = list.Take(50); 

Tôi mong chờ ở trên để tạo ra một cái gì đó như:

SELECT top 50 id, title, price, author 
FROM Books 
WHERE price > 50 

nhưng nó tạo ra:

SELECT 
[Limit1].[C1] as [C1] 
[Limit1].[id] as [Id], 
[Limit1].[title] as [title], 
[Limit1].[price] as [price], 
[Limit1].[author] 
FROM (SELECT TOP (50) 
      [Extent1].[id] as as [Id], 
      [Extent1].[title] as [title], 
      [Extent1].[price] as [price], 
      [Extent1].[author] as [author] 
     FROM Books as [Extent1] 
     WHERE [Extent1].[price] > 50 
    ) AS [Limit1] 

Tại sao các truy vấn LINQ trên tạo một truy vấn phụ và C1 đến từ đâu?

+3

Có lỗi nào liên quan không? –

+0

Không, tôi chỉ chạy nó nhìn vào sql trong hồ sơ và đã được tò mò tại sao nó tạo ra một truy vấn phụ. – Xaisoft

+0

tại sao nó tạo Limit1 và Extent1, thường LINQ sử dụng t0/t1, vv –

Trả lời

1

Bạn vẫn có thể làm cho nó sạch như thế này:

var c = (from co in db.countries 
        where co.regionID == 5 
        select co).Take(50); 

này sẽ cho kết quả:

Table(country).Where(co => (co.regionID = Convert(5))).Take(50) 

Tương đương với:

SELECT TOP (50) [t0].[countryID], [t0].[regionID], [t0].[countryName], [t0].[code] 
FROM [dbo].[countries] AS [t0] 
WHERE [t0].[regionID] = 5 

EDIT: Ý kiến, nó không nhất thiết vì với Take() riêng biệt, bạn vẫn có thể sử dụng nó như sau:

var c = (from co in db.countries 
        where co.regionID == 5 
        select co); 
      var l = c.Take(50).ToList(); 

Và kết quả sẽ giống như trước đây.

SELECT TOP (50) [t0].[countryID], [t0].[regionID], [t0].[countryName], [t0].[code] 
FROM [dbo].[countries] AS [t0] 
WHERE [t0].[regionID] = @p0 

Thực tế là bạn đã viết IQueryable = IQueryable.Take(50) là một phần khó khăn ở đây.

+0

Vâng, tôi đã làm cho nó sạch hơn, nhưng tôi đã tò mò tại sao nó tạo truy vấn phụ với truy vấn LINQ mà tôi đã cung cấp. Có phải vì tôi đang làm việc riêng rẽ không? – Xaisoft

+1

tôi nghĩ rằng dòng cuối cùng này là làm cho sự khác biệt ở đây: "list = list.Take (50)", nó tự chiếu và sau đó làm cho TAKE/TOP. – JOBG

+0

Cập nhật bài đăng của tôi bằng một ví dụ khác, nơi bạn có thể sử dụng .take riêng và vẫn nhận được Truy vấn rõ ràng. – JOBG

0

Truy vấn phụ được tạo cho mục đích chiếu, điều này có ý nghĩa hơn khi bạn chọn từ nhiều bảng vào một đối tượng ẩn danh duy nhất, khi đó truy vấn bên ngoài được sử dụng để thu thập kết quả.

Hãy thử những gì xảy ra với một cái gì đó như thế này:

from book in books 
where price > 50 
select new 
{ 
    Title = book.title, 
    Chapters = from chapter in book.Chapters 
      select chapter.Title 
} 
+0

Có, tôi có thể thấy điều đó xảy ra với nhiều bảng, nhưng ý của bạn là gì? – Xaisoft

+0

dự là những thứ như: Sum, Max, Min và cũng Take() –

+0

ok, vì vậy nếu tôi lấy ra Take, nó có thể sẽ không tạo ra truy vấn phụ. – Xaisoft

2

Disclaimer: Tôi chưa bao giờ sử dụng LINQ trước ...

tôi đoán sẽ được phân trang hỗ trợ? Tôi đoán bạn có phương thức Take(50, 50) có 50 bản ghi, bắt đầu từ bản ghi 50. Hãy xem SQL mà truy vấn tạo ra và có thể bạn sẽ thấy rằng nó sử dụng cấu trúc truy vấn phụ tương tự để cho phép nó trả về bất kỳ 50 hàng nào trong một truy vấn trong khoảng thời gian nó trả về 50 hàng đầu tiên.

Trong mọi trường hợp, truy vấn con lồng nhau không thêm bất kỳ chi phí hiệu năng nào khi được tối ưu hóa tự động trong khi lập kế hoạch thực hiện.

+0

vâng, tôi đã kiểm tra thời gian và nó hầu như giống nhau, tôi chỉ tò mò về lý do tại sao họ làm theo cách này khi nó có thể dễ dàng đạt được mà không cần truy vấn phụ. – Xaisoft

+0

Chỉ để ghi lại, nó sẽ thực sự là Take (50) và Skip (50), và đó là ý định để phân trang, nhưng tôi thực sự nghĩ rằng trong trường hợp này nó là vấn đề làm thế nào bạn xây dựng biểu thức. – JOBG

+0

Không quan tâm, truy vấn mà LINQ thực thi là gì nếu bạn bỏ qua 100 hàng? – Justin

0

Không phải là trường hợp truy vấn đầu tiên trả về tổng số hàng trong khi thứ hai trích xuất tập con của các hàng dựa trên lệnh gọi đến phương thức .Take()?

+0

Chậm hơn một con rùa vào một ngày mùa đông lạnh giá, lạnh ... – Henric

+0

ok, tôi thấy những gì bạn đang nói. Truy vấn LINQ đầu tiên tạo truy vấn sql bên ngoài và danh sách = list.Take (50) tạo ra truy vấn phụ. Đúng không? – Xaisoft

+0

Rùa thực sự chạy khá nhanh, lol – Xaisoft

0
  1. Tôi đồng ý với @Justin Swartsel. Không có lỗi liên quan, vì vậy đây phần lớn là một vấn đề học thuật.
  2. nỗ lực LINQ to SQL để tạo SQL chạy hiệu quả (trong trường hợp này).
    1. Nhưng không cố gắng tạo ra SQL thông thường SQL mà con người có khả năng sẽ tạo.
  3. Trình triển khai LINQ to SQL có thể sử dụng mẫu trình tạo để tạo SQL.
    1. Nếu vậy, sẽ dễ dàng hơn để nối thêm chuỗi con (hoặc truy vấn phụ trong trường hợp này) hơn là quay lại và chèn đoạn 'TOP x' vào mệnh đề SELECT.
+0

Vì vậy, những gì bạn đang nói là các nhà thiết kế LINQ nơi chỉ lười biếng và nó đã được dễ dàng hơn cho họ để tạo ra một truy vấn con hơn là làm một đầu trong truy vấn đầu tiên. – Xaisoft

+1

@Xaisoft: Nếu những người triển khai đã sử dụng mẫu trình xây dựng và gắn thêm các truy vấn con phụ vào 'Chèn x-TOP', họ có thể làm như vậy bởi vì cách tiếp cận mang lại mã mạnh mẽ; không nhất thiết vì nó dễ dàng hơn. –

Các vấn đề liên quan