¿Cuál es el equivalente de Linq a SQL a TOP o LIMIT / OFFSET?

195

Cómo hago esto

Select top 10 Foo from MyTable

en Linq a SQL?

Hierba caudill
fuente

Respuestas:

146

En VB:

from m in MyTable
take 10
select m.Foo

Esto supone que MyTable implementa IQueryable. Puede que tenga que acceder a través de un DataContext u otro proveedor.

También supone que Foo es una columna en MyTable que se asigna a un nombre de propiedad.

Consulte http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx para obtener más detalles.

David Alpert
fuente
127
Eso no funciona en C #, no hay expresión de toma. Necesita usar el método Take ().
Adam Lassek
10
Técnicamente, el interlocutor pidió Linq a SQL, por lo que VB es una suposición viable. Dicho esto, ALassek, yo mismo soy un chico # # y prefiero tu respuesta. :-)
David Alpert
3
Bueno, su ejemplo fue escrito en C # LINQ, por eso lo señalé.
Adam Lassek
3
2 problemas: 1) esto funciona bien en VB. en C # tienes el método Take. 2) la toma funciona en el cliente, no en db, por lo que si tiene un conjunto de resultados grande, ¡terminará llevándolo todo al cliente desde el db!
Yuki
8
Aprecio que esto tiene algunos años, pero para aquellos que acaban de llegar, vale la pena señalar que ".Take (x)" debe aparecer antes de hacer un ".Select ()" o ".ToList ()", como el " .Take (x) "solo se incluirá en el SQL generado si es antes de enumerar los resultados. Si aparece después de esto, se realizará una vez que se haya enumerado el conjunto de resultados y, por lo tanto, ¡es una simple y antigua declaración de Linq!
Bertie
248

Utiliza el método Take :

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

En VB LINQ tiene una expresión take:

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

De la documentación:

Take<TSource>enumera sourcey produce elementos hasta que los countelementos hayan sido cedidos o sourceno contengan más elementos. Si countexcede el número de elementos source, sourcese devuelven todos los elementos de .

Adam Lassek
fuente
13
Las pequeñas diferencias en LINQ entre C # y VB son molestas. ¿Por qué C # no tiene una expresión take como VB? Eso parece un descuido. Y la falta de Subs anónimos de VB hace que las lambdas sean mucho menos útiles.
Adam Lassek
Justo lo que estaba buscando +1
jasonco
1
+1 Justo lo que necesitaba, también. Y FWIW, parece que solo los diez registros realmente caen en picado. De lo contrario, mi SELECT devolvería una enorme cantidad de datos, suficiente para lanzar una OutOfMemoryException después de un retraso doloroso. Con Take ( cantidad manejable ), sin demora, sin excepción.
Bob Kaufman
VB ahora también tiene un método Take (). Tuve que usar una variable para la cantidad a tomar, y la expresión no funcionó, mientras que el método sí.
Dave Johnson
33

Usa el Take(int n)método:

var q = query.Take(10);
codificador
fuente
25

El OP también mencionó el desplazamiento, así que por ej. si desea obtener los artículos del 30 al 60, haría:

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

Use el método "Saltar" para el desplazamiento.
Use el método "Take" para el límite.

Inc33
fuente
13

@Janei: mi primer comentario aquí es sobre su muestra;)

Creo que si te gusta esto, quieres tomar 4 y luego aplicar el tipo en estos 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 a ordenar todo tbl_News por idNews descendiendo y luego tomando 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 ? Los resultados pueden ser diferentes.

Yann
fuente
5

Esto funciona bien en C #

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

Me gusta esto:

 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
fuente
77
El problema con este enfoque es que tomará 4 y luego los ordenará, cuando sospecho que lo que realmente quiere es obtener los 4 mejores resultados. Debe hacer la toma después del pedido, vea el comentario de Yanns.
Russell Troywest
3

Usaría el método Take (N).

FlySwat
fuente
3

Si la toma ocurre en el cliente o en la base de datos depende de dónde aplique el operador de toma. Si lo aplica antes de enumerar la consulta (es decir, antes de usarla en un foreach o convertirla en una colección), la toma dará como resultado que el operador SQL "n superior" se envíe a la base de datos. Puede ver esto si ejecuta el generador de perfiles SQL. Si aplica la toma después de enumerar la consulta, sucederá en el cliente, ya que LINQ habrá tenido que recuperar los datos de la base de datos para que pueda enumerarlos.

usuario124368
fuente
2

Tomar datos de DataBase sin ordenar es lo mismo que tomar aleatoriamente

Anton
fuente
Ciertamente no es aleatorio, aunque no se garantiza que los resultados sean repetibles, pero hay muchas veces que desea hacerlo, especialmente en las pruebas.
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
fuente
0

Tuve que usar el método Take (n), luego transformar a la lista, funcionó como un 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();
SOFTWARE Apollo
fuente
0

De esta manera funcionó para mí:

var noticias = from n in db.Noticias.Take(6)
                       where n.Atv == 1
                       orderby n.DatHorLan descending
                       select n;
Gladson Reis
fuente
Acabo de editar su publicación, traduje el texto portugués al inglés, porque este sitio es solo en inglés (no se aplica a nombres de variables, es por eso que no los he cambiado).
waka
Lo siento ! No me di cuenta, pensé que estaba en el stackoverflow brasileño. Lo siento
Gladson Reis
0

Para limit 1usar métodosFirstOrDefault() o First().

Ejemplo

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

Desarrollador Marius Žilėnas
fuente