O que o Linq to SQL equivale a TOP ou LIMIT / OFFSET?

195

Como eu faço isso

Select top 10 Foo from MyTable

no Linq para SQL?

Caudill de ervas
fonte

Respostas:

146

No VB:

from m in MyTable
take 10
select m.Foo

Isso pressupõe que MyTable implementa IQueryable. Pode ser necessário acessá-lo por meio de um DataContext ou de outro provedor.

Ele também assume que Foo é uma coluna no MyTable que é mapeada para um nome de propriedade.

Consulte http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx para obter mais detalhes.

David Alpert
fonte
127
Isso não funciona em C #, não há expressão de aceitação. Você precisa usar o método Take ().
Adam Lassek 10/10/08
10
Tecnicamente, o questionador solicitou o Linq to SQL, então o VB é uma suposição viável. Dito isto, ALassek, eu sou um cara e prefiro sua resposta. :-)
David Alpert
3
Bem, seu exemplo foi escrito em C # LINQ e foi por isso que eu mencionei isso.
Adam Lassek 10/10/08
3
2 problemas: 1) isso funciona bem no VB. em c # você tem o método Take. 2) o take funciona no cliente, não no db; portanto, se você tiver um conjunto de resultados grande, acabaria recebendo tudo do db para o cliente!
Yuki
8
Perceba que isso tem alguns anos, mas para aqueles que estão chegando aqui, é importante notar que o ".Take (x)" deve aparecer antes de você fazer um ".Select ()" ou ".ToList ()", como o " .Take (x) "só será incluído no SQL gerado se for antes de você enumerar os resultados. Se aparecer depois disso, será feito assim que o conjunto de resultados tiver sido enumerado e, portanto, é uma instrução Linq antiga e simples!
22412 Bertie
248

Use o método Take :

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

No VB, o LINQ tem uma expressão take:

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

A partir da documentação:

Take<TSource>enumera sourcee produz elementos até que os countelementos tenham sido produzidos ou que sourcenão contenham mais elementos. Se countexceder o número de elementos em source, todos os elementos desource são retornados.

Adam Lassek
fonte
13
As pequenas diferenças no LINQ entre C # e VB são irritantes. Por que C # não tem uma expressão take como VB? Isso parece uma supervisão. E a falta de subs anônimos do VB torna as lambdas muito menos úteis.
Adam Lassek 10/10/08
Apenas o que eu estava procurando +1
jasonco 18/11/2009
1
+1 Exatamente o que eu precisava também. E FWIW, parece que apenas os dez discos realmente caem no cano. Caso contrário, meu SELECT retornaria uma quantidade enorme de dados, o suficiente para gerar uma OutOfMemoryException após um atraso doloroso. Com Take ( quantidade gerenciável ), sem atraso, sem exceção.
Bob Kaufman
O VB agora também possui um método Take (). Eu tive que usar uma variável para a quantidade a receber, e a expressão não funcionou, enquanto o método funcionou.
Dave Johnson
33

Use o Take(int n)método:

var q = query.Take(10);
amcoder
fonte
25

O PO também mencionou a compensação, assim, por ex. se você gostaria de obter os itens de 30 a 60, você faria:

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

Use o método "Ignorar" para deslocamento.
Use o método "Take" para limitar.

Inc33
fonte
13

@ Janei: meu primeiro comentário aqui é sobre sua amostra;)

Eu acho que se você gosta disso, você quer pegar 4 e aplicar o tipo nesses 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
                };

Diferente do que ordenar tbl_News inteiro por idNews descendente e depois levar 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);

não ? os resultados podem ser diferentes.

Yann
fonte
5

Isso funciona bem em c #

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

Eu faço assim:

 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
                };
Janei Vieira
fonte
7
O problema com essa abordagem é que você pega 4 e depois as ordena, quando eu suspeito que o que você realmente deseja é obter os 4 principais resultados. Você precisa fazer a tomada após o pedido, veja o comentário de Yanns.
Russell Troywest 22/09/10
3

Você usaria o método Take (N).

FlySwat
fonte
3

Se a tomada acontece no cliente ou no banco de dados depende de onde você aplica o operador de tomada. Se você aplicá-lo antes de enumerar a consulta (ou seja, antes de usá-lo em um foreach ou convertê-lo em uma coleção), a tomada resultará no envio do operador "top n" SQL ao banco de dados. Você pode ver isso se executar o SQL Profiler. Se você aplicar a tomada após enumerar a consulta, ela ocorrerá no cliente, pois o LINQ terá que recuperar os dados do banco de dados para que você possa enumerá-la.

user124368
fonte
2

Obter dados do DataBase sem classificar é o mesmo que obter aleatoriamente

Anton
fonte
Certamente não é aleatório, embora os resultados não sejam garantidos para serem repetidos, mas há muitas vezes que você deseja fazer isso, principalmente nos testes.
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
fonte
0

Eu tive que usar o método Take (n), em seguida, transformar em lista, funcionou como um encanto:

    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 SOFTWARE
fonte
0

Dessa forma, funcionou para mim:

var noticias = from n in db.Noticias.Take(6)
                       where n.Atv == 1
                       orderby n.DatHorLan descending
                       select n;
Gladson Reis
fonte
Acabei de editar seu post, traduzi o texto em português para inglês, porque este site é apenas em inglês (não se aplica a nomes de variáveis, é por isso que não os mudei).
waka
Desculpe ! Eu não percebi, pensei que estava no stackoverflow brasileiro. Desculpe
Gladson Reis
0

Para limit 1métodos de uso FirstOrDefault()ou First().

Exemplo

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

Desenvolvedor Marius Žilėnas
fonte