200

How do I do this

Select top 10 Foo from MyTable

in Linq to SQL?

Craig Ringer
  • 307,061
  • 76
  • 688
  • 778
Herb Caudill
  • 50,043
  • 39
  • 124
  • 173

13 Answers13

255

Use the Take method:

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

In VB LINQ has a take expression:

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

From the documentation:

Take<TSource> enumerates source and yields elements until count elements have been yielded or source contains no more elements. If count exceeds the number of elements in source, all elements of source are returned.

John Cummings
  • 1,949
  • 3
  • 22
  • 38
Adam Lassek
  • 35,156
  • 14
  • 91
  • 107
  • 16
    The little differences in LINQ between C# and VB are annoying. Why doesn't C# have a take expression like VB? That seems like an oversight. And VB's lack of anonymous Subs makes lambdas much less useful. – Adam Lassek Oct 10 '08 at 16:59
  • Just what I was looking for +1 – jasonco Nov 18 '09 at 08:13
  • 1
    +1 Just what I needed, too. And FWIW, seems that only the ten records actually come down the pipe. My SELECT would otherwise return an _enormous_ amount of data, enough to throw an *OutOfMemoryException* after a painful delay. With Take( _manageable-quantity_ ), no delay, no exception. – Bob Kaufman Jul 20 '11 at 21:05
  • VB now has a Take() method as well. I had to use a variable for the amount to take, and the expression did not work, while the method did. – Dave Johnson Mar 02 '16 at 19:24
147

In VB:

from m in MyTable
take 10
select m.Foo

This assumes that MyTable implements IQueryable. You may have to access that through a DataContext or some other provider.

It also assumes that Foo is a column in MyTable that gets mapped to a property name.

See http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx for more detail.

AaronLS
  • 37,329
  • 20
  • 143
  • 202
David Alpert
  • 3,161
  • 1
  • 23
  • 19
  • 132
    That doesn't work in C#, there is no take expression. You need to use the Take() method. – Adam Lassek Oct 10 '08 at 16:49
  • 11
    Technically, the questioner asked for Linq to SQL, so VB is a viable assumption. That said, ALassek, i'm a c# guy myself and prefer your answer. :-) – David Alpert Oct 10 '08 at 16:51
  • 3
    Well, you're example was written in C# LINQ which is why I pointed that out. – Adam Lassek Oct 10 '08 at 16:52
  • thanks, ALassek. I didn't sleep last night so i appreciate the catch in my grammar. – David Alpert Oct 10 '08 at 19:19
  • 3
    2 problems: 1) this works fine in VB. in C# you have the Take method. 2) the take works in client, not in db, so if you have large result set you would end up getting all of it to the client from the db! – Yuki Mar 13 '11 at 04:50
  • @Yuki, actually LINQ method ".Take(10)" converted to SQL "SELECT TOP (10)" thereby "the take works in client" is NOT true. – some_engineer Nov 25 '11 at 13:58
  • 9
    Appreciate this is a few years old, but for those just getting here, it's worth noting that the ".Take(x)" should appear before you do a ".Select()" or ".ToList()", as the ".Take(x)" will only be included in the generated SQL if it is before you enumerate the results. If it appears after this, then it will be done once the result set has been enumerated and is therefore a plain old Linq statement! – Bertie Apr 13 '12 at 10:45
  • 1
    @Bertie ToList() yes, Select() no. You can do Select() before Take(x) in C# and the Top clause is properly generated. Select() is a deferred operation. – Stephen Kennedy May 23 '12 at 16:29
34

Use the Take(int n) method:

var q = query.Take(10);
amcoder
  • 1,131
  • 9
  • 5
32

The OP actually mentioned offset as well, so for ex. if you'd like to get the items from 30 to 60, you would do:

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

Use the "Skip" method for offset.
Use the "Take" method for limit.

Inc33
  • 1,747
  • 1
  • 20
  • 26
14

@Janei: my first comment here is about your sample ;)

I think if you do like this, you want to take 4, then applying the sort on these 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
                };

Different than sorting whole tbl_News by idNews descending and then taking 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);

no ? results may be different.

Herb Caudill
  • 50,043
  • 39
  • 124
  • 173
Yann
  • 141
  • 1
  • 2
5

This works well in C#

var q = from m in MyTable.Take(10)
        select m.Foo
spdrcr911
  • 51
  • 1
  • 1
5

Whether the take happens on the client or in the db depends on where you apply the take operator. If you apply it before you enumerate the query (i.e. before you use it in a foreach or convert it to a collection) the take will result in the "top n" SQL operator being sent to the db. You can see this if you run SQL profiler. If you apply the take after enumerating the query it will happen on the client, as LINQ will have had to retrieve the data from the database for you to enumerate through it

user124368
  • 61
  • 1
  • 2
4

I do like this:

 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
                };
Herb Caudill
  • 50,043
  • 39
  • 124
  • 173
  • 7
    The problem with this approach is that you will take 4 and then order them, when I suspect what you really want is to get the top 4 results. You need to do the take after the orderby, see Yanns comment. – Russell Troywest Sep 22 '10 at 19:41
3

You would use the Take(N) method.

FlySwat
  • 172,459
  • 74
  • 246
  • 311
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();
minhnguyen
  • 91
  • 1
  • 3
2

Taking data of DataBase without sorting is the same as random take

Anton
  • 39
  • 1
  • It's certainly not random, though the results are not guaranteed to be repeatable, but there are plenty of times you want to do that, particularly in testing. – Auspex Nov 07 '18 at 10:22
0

I had to use Take(n) method, then transform to list, Worked like a charm:

    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();
apollosoftware.org
  • 12,161
  • 4
  • 48
  • 69
0

This way it worked for me:

var noticias = from n in db.Noticias.Take(6)
                       where n.Atv == 1
                       orderby n.DatHorLan descending
                       select n;
waka
  • 3,362
  • 9
  • 35
  • 54
  • 1
    I just edited your post, I translated the portuguese text into english, because this site is english language only (doesn't apply to variable names, that's why I haven't changed those). – waka Oct 01 '17 at 17:05
  • Sorry ! I did not realize, I thought I was in the Brazilian stackoverflow. Sorry – Gladson Reis Oct 01 '17 at 23:49