Compartir a través de


Cómo: Devolver u omitir elementos de una secuencia (LINQ to SQL)

Utilice el operador Take<TSource> para devolver un número determinado de elementos de una secuencia y omitir el resto.

Utilice el operador Skip<TSource> para omitir un número determinado de elementos de una secuencia y devolver el resto.

NotaNota

Take<TSource> y Skip<TSource> tienen ciertas limitaciones cuando se utilizan en consultas en SQL Server 2000.Para obtener más información, vea la sección donde se tratan las excepciones de Skip y Take en SQL Server 2000, en el tema Solución de problemas (LINQ to SQL).

LINQ to SQL convierte Skip<TSource> utilizando una subconsulta con la cláusula NOT EXISTS de SQL. Esta conversión tiene las limitaciones siguientes:

  • El argumento debe ser un conjunto. No se admiten los conjuntos múltiples, aunque estén ordenados.

  • La consulta generada puede ser mucho más compleja que la consulta generada para la consulta base en la que se aplica Skip<TSource>. Esta complejidad puede mermar el rendimiento o incluso hacer que se agote el tiempo de espera.

Ejemplo

En el ejemplo siguiente se utiliza Take para seleccionar los cinco primeros Employees contratados. Observe que la colección primero se ordena por HireDate.

Dim firstHiredQuery = _
    From emp In db.Employees _
    Select emp _
    Order By emp.HireDate _
    Take 5

For Each empObj As Employee In firstHiredQuery
    Console.WriteLine("{0}, {1}", empObj.EmployeeID, _
        empObj.HireDate)
Next
IQueryable<Employee> firstHiredQuery =
    (from emp in db.Employees
    orderby emp.HireDate
    select emp)
    .Take(5);

foreach (Employee empObj in firstHiredQuery)
{
    Console.WriteLine("{0}, {1}", empObj.EmployeeID,
        empObj.HireDate);
}

En el ejemplo siguiente se utiliza Skip<TSource> para seleccionar todos los Products excepto los 10 más caros.

Dim lessExpensiveQuery = _
    From prod In db.Products _
    Select prod _
    Order By prod.UnitPrice Descending _
    Skip 10

For Each prodObj As Product In lessExpensiveQuery
    Console.WriteLine(prodObj.ProductName)
Next
IQueryable<Product> lessExpensiveQuery =
    (from prod in db.Products
    orderby prod.UnitPrice descending
    select prod)
    .Skip(10);

foreach (Product prodObj in lessExpensiveQuery)
{
    Console.WriteLine(prodObj.ProductName);
}

En el ejemplo siguiente se combinan los métodos Skip<TSource> y Take<TSource> para omitir los 50 primeros registros y después devolver los 10 siguientes.

Dim custQuery2 = _
    From cust In db.Customers _
    Order By (cust.ContactName) _
    Select cust _
    Skip 50 _
    Take 10

For Each custRecord As Customer In custQuery2
    Console.WriteLine(custRecord.ContactName)
Next
var custQuery2 =
    (from cust in db.Customers
    orderby cust.ContactName
    select cust)
    .Skip(50).Take(10);

foreach (var custRecord in custQuery2)
{
    Console.WriteLine(custRecord.ContactName);
}

Las operaciones Take<TSource> y Skip<TSource> solo están perfectamente definidas para los conjuntos ordenados. La semántica para los conjuntos no ordenados o conjuntos múltiples no está definida.

Debido a las limitaciones de la ordenación en SQL, LINQ to SQL intenta trasladar la ordenación del argumento del operador Take<TSource> o Skip<TSource> al resultado del operador.

NotaNota

La conversión es diferente para SQL Server 2000 y SQL Server 2005.Si piensa utilizar Skip<TSource> con una consulta de cualquier complejidad, utilice SQL Server 2005.

Considere la siguiente consulta LINQ to SQL para SQL Server 2000:

Dim custQuery3 = _
    From custs In db.Customers _
    Where custs.City = "London" _
    Select custs _
    Order By custs.CustomerID _
    Skip 1 _
    Take 1

For Each custObj In custQuery3
    Console.WriteLine(custObj.CustomerID)
Next
IQueryable<Customer> custQuery3 =
    (from custs in db.Customers
     where custs.City == "London"
     orderby custs.CustomerID
     select custs)
    .Skip(1).Take(1);

foreach (var custObj in custQuery3)
{
    Console.WriteLine(custObj.CustomerID);
}

LINQ to SQL traslada la operación de ordenación al final en el código de SQL, como se observa a continuación:

SELECT TOP 1 [t0].[CustomerID], [t0].[CompanyName],
FROM [Customers] AS [t0]
WHERE (NOT (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM (
        SELECT TOP 1 [t1].[CustomerID]
        FROM [Customers] AS [t1]
        WHERE [t1].[City] = @p0
        ORDER BY [t1].[CustomerID]
        ) AS [t2]
    WHERE [t0].[CustomerID] = [t2].[CustomerID]
    ))) AND ([t0].[City] = @p1)
ORDER BY [t0].[CustomerID]

Cuando se encadenan Take<TSource> y Skip<TSource>, todos los criterios de ordenación especificados deben ser coherentes. De lo contrario, los resultados no están definidos.

Para los argumentos integrales constantes no negativos basados en la especificación de SQL, tanto Take<TSource> como Skip<TSource> están perfectamente definidos.

Vea también

Referencia

Conversión de operadores de consulta estándar (LINQ to SQL)

Otros recursos

Ejemplos de consultas (LINQ to SQL)