Linq to SQL tương đương với TOP hoặc GIỚI HẠN / OFFSET là gì?


195

Làm thế nào để tôi làm điều này

Select top 10 Foo from MyTable

trong Linq sang SQL?

Câu trả lời:


146

Trong VB:

from m in MyTable
take 10
select m.Foo

Điều này giả định rằng MyTable triển khai IQueryable. Bạn có thể phải truy cập thông qua DataContext hoặc một số nhà cung cấp khác.

Nó cũng giả định rằng Foo là một cột trong MyTable được ánh xạ tới tên thuộc tính.

Xem http://bloss.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx để biết thêm chi tiết.


127
Điều đó không hoạt động trong C #, không có biểu hiện. Bạn cần sử dụng phương thức Take ().
Adam Lassek

10
Về mặt kỹ thuật, người hỏi đã yêu cầu Linq cho SQL, vì vậy VB là một giả định khả thi. Điều đó nói rằng, ALassek, tôi là một người đàn ông và thích câu trả lời của bạn. :-)
David Alpert

3
Chà, ví dụ của bạn đã được viết bằng C # LINQ, đó là lý do tại sao tôi chỉ ra điều đó.
Adam Lassek

3
2 vấn đề: 1) điều này hoạt động tốt trong VB. trong C # bạn có phương thức Take. 2) Take hoạt động trong máy khách, không phải trong db, vì vậy nếu bạn có tập kết quả lớn, cuối cùng bạn sẽ nhận được tất cả cho máy khách từ db!
Yuki

8
Đánh giá cao điều này đã vài năm tuổi, nhưng đối với những người mới đến đây, đáng chú ý rằng ".Take (x)" sẽ xuất hiện trước khi bạn thực hiện ".Select ()" hoặc ".ToList ()", như là " .Take (x) "sẽ chỉ được bao gồm trong SQL được tạo nếu có trước khi bạn liệt kê kết quả. Nếu nó xuất hiện sau đó, thì nó sẽ được thực hiện khi tập kết quả đã được liệt kê và do đó là một tuyên bố Linq cũ đơn giản!
Bertie

248

Sử dụng phương thức Take :

var foo = (from t in MyTable
           select t.Foo).Take(10);

Trong VB LINQ có một biểu thức:

Dim foo = From t in MyTable _
          Take 10 _
          Select t.Foo

Từ tài liệu:

Take<TSource>liệt kê sourcevà sản lượng các phần tử cho đến khi countcác phần tử đã được mang lại hoặc sourcekhông chứa các phần tử nữa. Nếu countvượt quá số lượng phần tử trong source, tất cả các phần tử sourceđược trả về.


13
Sự khác biệt nhỏ về LINQ giữa C # và VB gây khó chịu. Tại sao C # không có biểu thức như VB? Đó dường như là một sự giám sát. Và việc thiếu chương trình ẩn danh của VB khiến lambdas trở nên ít hữu ích hơn.
Adam Lassek

Chỉ là những gì tôi đang tìm kiếm +1
jasonco

1
+1 Chỉ cần những gì tôi cần, quá. Và FWIW, dường như chỉ có mười hồ sơ thực sự đi xuống. CHỌN của tôi nếu không sẽ trả lại một lượng dữ liệu khổng lồ , đủ để ném OutOfMemoryException sau một thời gian trì hoãn đau đớn. Với Take ( có thể quản lý số lượng ), không chậm trễ, không ngoại lệ.
Bob Kaufman

VB bây giờ cũng có một phương thức Take (). Tôi đã phải sử dụng một biến cho số lượng cần lấy và biểu thức không hoạt động, trong khi phương thức thì có.
Dave Johnson


25

OP thực sự cũng đề cập đến offset, vì vậy đối với ex. nếu bạn muốn nhận các mục từ 30 đến 60, bạn sẽ làm:

var foo = (From t In MyTable
       Select t.Foo).Skip(30).Take(30);

Sử dụng phương pháp "Bỏ qua" để bù đắp.
Sử dụng phương pháp "Lấy" cho giới hạn.


13

@Janei: nhận xét đầu tiên của tôi ở đây là về mẫu của bạn;)

Tôi nghĩ rằng nếu bạn làm như thế này, bạn muốn lấy 4, sau đó áp dụng sắp xếp trên 4.

var dados =  from d in dc.tbl_News.Take(4) 
                orderby d.idNews descending
                select new 
                {
                    d.idNews,
                    d.titleNews,
                    d.textNews,
                    d.dateNews,
                    d.imgNewsThumb
                };

Khác với việc sắp xếp toàn bộ tbl_News theo idNews giảm dần và sau đó lấy 4

var dados =  (from d in dc.tbl_News
                orderby d.idNews descending
                select new 
                {
                    d.idNews,
                    d.titleNews,
                    d.textNews,
                    d.dateNews,
                    d.imgNewsThumb
                }).Take(4);

không kết quả có thể khác nhau.


5

Điều này hoạt động tốt trong C #

var q = from m in MyTable.Take(10)
        select m.Foo

4

Tôi thích điều này:

 var dados =  from d in dc.tbl_News.Take(4) 
                orderby d.idNews descending

                select new 
                {
                    d.idNews,
                    d.titleNews,
                    d.textNews,
                    d.dateNews,
                    d.imgNewsThumb
                };

7
Vấn đề với phương pháp này là bạn sẽ lấy 4 và sau đó đặt hàng chúng, khi tôi nghi ngờ điều bạn thực sự muốn là có được kết quả top 4. Bạn cần phải thực hiện sau khi đặt hàng, xem bình luận của Yanns.
Russell Troywest


3

Việc thực hiện xảy ra trên máy khách hay trong db tùy thuộc vào nơi bạn áp dụng toán tử Take. Nếu bạn áp dụng nó trước khi bạn liệt kê truy vấn (tức là trước khi bạn sử dụng nó trong một mục trước hoặc chuyển đổi nó thành một bộ sưu tập), kết quả sẽ dẫn đến toán tử SQL "top n" được gửi tới db. Bạn có thể thấy điều này nếu bạn chạy SQL profiler. Nếu bạn áp dụng mất sau khi liệt kê truy vấn, nó sẽ xảy ra trên máy khách, vì LINQ sẽ phải lấy dữ liệu từ cơ sở dữ liệu để bạn liệt kê thông qua nó


2

Lấy dữ liệu của DataBase mà không cần sắp xếp cũng giống như lấy ngẫu nhiên


Điều này chắc chắn không phải là ngẫu nhiên, mặc dù kết quả không được đảm bảo có thể lặp lại, nhưng có rất nhiều lần bạn muốn làm điều đó, đặc biệt là trong thử nghiệm.
Auspex

2
Array oList = ((from m in dc.Reviews
                           join n in dc.Users on m.authorID equals n.userID
                           orderby m.createdDate descending
                           where m.foodID == _id                      
                           select new
                           {
                               authorID = m.authorID,
                               createdDate = m.createdDate,
                               review = m.review1,
                               author = n.username,
                               profileImgUrl = n.profileImgUrl
                           }).Take(2)).ToArray();

0

Tôi đã phải sử dụng phương thức Take (n), sau đó chuyển đổi thành danh sách, Làm việc như một cơ duyên:

    var listTest = (from x in table1
                     join y in table2
                     on x.field1 equals y.field1
                     orderby x.id descending
                     select new tempList()
                     {
                         field1 = y.field1,
                         active = x.active
                     }).Take(10).ToList();

0

Cách này hiệu quả với tôi:

var noticias = from n in db.Noticias.Take(6)
                       where n.Atv == 1
                       orderby n.DatHorLan descending
                       select n;

Tôi vừa chỉnh sửa bài đăng của bạn, tôi đã dịch văn bản tiếng Bồ Đào Nha sang tiếng Anh, vì trang web này chỉ là ngôn ngữ tiếng Anh (không áp dụng cho tên biến, đó là lý do tại sao tôi không thay đổi chúng).
waka

Lấy làm tiếc ! Tôi đã không nhận ra, tôi nghĩ rằng tôi đang ở trong stackoverflow Brazil. Xin lỗi
Gladson Reis

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.