Что такое Linq to SQL, эквивалентный TOP или LIMIT / OFFSET?

195

Как мне это сделать

Select top 10 Foo from MyTable

в Linq для SQL?

Херб Каудилл
источник

Ответы:

146

В VB:

from m in MyTable
take 10
select m.Foo

Это предполагает, что MyTable реализует IQueryable. Возможно, вам придется получить доступ к этому через DataContext или какой-либо другой поставщик.

Также предполагается, что Foo - это столбец в MyTable, который сопоставляется с именем свойства.

См. Http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx для получения более подробной информации.

Дэвид Альперт
источник
127
Это не работает в C #, нет выражения take. Вам необходимо использовать метод Take ().
Адам Лассек
10
Технически, спрашивающий попросил Linq to SQL, поэтому VB - жизнеспособное предположение. Тем не менее, ALassek, я сам парень и предпочитаю ваш ответ. :-)
Дэвид Альперт
3
Ну, ваш пример был написан на C # LINQ, поэтому я указал на это.
Адам Лассек
3
2 проблемы: 1) это отлично работает в VB. в C # у вас есть метод Take. 2) дубль работает в клиенте, а не в БД, поэтому, если у вас большой набор результатов, вы получите все это клиенту из БД!
Юки
8
Признайте, что это несколько лет, но для тех, кто только что пришел сюда, стоит отметить, что «.Take (x)» должен появиться до того, как вы сделаете «.Select ()» или «.ToList ()», как « .Take (x) "будет включен только в сгенерированный SQL, если он есть до того, как вы перечислите результаты. Если оно появится после этого, то оно будет выполнено после перечисления набора результатов и, следовательно, является простым старым оператором Linq!
Берти
248

Используйте метод Take :

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

В VB LINQ есть выражение take:

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

Из документации:

Take<TSource>перечисляет sourceи возвращает элементы до countтех пор, пока элементы не будут получены или не sourceсодержат больше элементов. Если countколичество элементов превышает source, все элементы sourceвозвращаются.

Адам Лассек
источник
13
Небольшие различия в LINQ между C # и VB раздражают. Почему C # не имеет выражения типа VB? Это похоже на недосмотр. А отсутствие у VB анонимных подписчиков делает лямбды гораздо менее полезными.
Адам Лассек
Просто то, что я искал +1
Джейсон
1
+1 Только то, что мне тоже нужно. И FWIW, кажется, что только десять записей на самом деле идут по трубе. В противном случае мой SELECT вернул бы огромное количество данных, достаточное для того, чтобы после мучительной задержки вызвать исключение OutOfMemoryException . С Take ( управляемое количество ), без задержки, без исключения.
Боб Кауфман
VB теперь также имеет метод Take (). Я должен был использовать переменную для суммы, которую нужно взять, и выражение не работало, в то время как метод работал.
Дейв Джонсон,
33

Используйте Take(int n)метод:

var q = query.Take(10);
amcoder
источник
25

ОП фактически упомянул смещение, так что, например, если вы хотите получить предметы от 30 до 60, вы должны сделать:

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

Используйте метод «Пропустить» для смещения.
Используйте метод «Take» для лимита.

работе 33
источник
13

@Janei: мой первый комментарий здесь о вашем образце;)

Я думаю, что если вам это нравится, вы хотите взять 4, а затем применить сортировку к этим 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
                };

Отличается от сортировки целых tbl_News по idNews по убыванию и затем принимает 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);

нет? результаты могут быть разными.

Yann
источник
5

Это хорошо работает в C #

var q = from m in MyTable.Take(10)
        select m.Foo
spdrcr911
источник
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
                };
Джаней Виейра
источник
7
Проблема с этим подходом состоит в том, что вы берете 4, а затем заказываете их, когда я подозреваю, что вы действительно хотите получить 4 лучших результата. Вы должны сделать дубль после заказа, см. Комментарий Яннса.
Рассел Тройвест
3

Вы бы использовали метод Take (N).

FlySwat
источник
3

Происходит ли получение на клиенте или в БД, зависит от того, где вы применяете оператор получения. Если вы примените его перед тем, как перечислить запрос (т. Е. Перед тем, как использовать его в foreach или преобразовать его в коллекцию), результат приведет к тому, что оператор SQL «top n» будет отправлен в базу данных. Вы можете увидеть это, если вы запустите SQL Profiler. Если вы примените дубль после перечисления запроса, это произойдет на клиенте, так как LINQ придется извлечь данные из базы данных, чтобы вы могли перечислять через них

user124368
источник
2

Получение данных из базы данных без сортировки аналогично случайному

Антон
источник
Это, конечно, не случайно, хотя не гарантируется, что результаты будут повторяемыми, но есть много раз, когда вы хотите это сделать, особенно в тестировании.
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();
minhnguyen
источник
0

Мне пришлось использовать метод Take (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();
ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ Apollo
источник
0

Так у меня получилось:

var noticias = from n in db.Noticias.Take(6)
                       where n.Atv == 1
                       orderby n.DatHorLan descending
                       select n;
Глэдсон Рейс
источник
Я только что отредактировал ваш пост, я перевел португальский текст на английский, потому что этот сайт только на английском языке (не относится к именам переменных, поэтому я их не менял).
Вака
Извини ! Я не понял, я думал, что я был в бразильском стеке потока. Извините
Глэдсон Рейс
0

Для limit 1использования методов FirstOrDefault()или First().

пример

var y = (from x in q select x).FirstOrDefault();

Разработчик Мариус Жиленас
источник