Return Or Skip Elements in a Sequence


Use the Take<TSource> operator to return a given number of elements in a sequence and then skip over the remainder.

Use the Skip<TSource> operator to skip over a given number of elements in a sequence and then return the remainder.

System_CAPS_ICON_note.jpg Note

Take<TSource> and Skip<TSource> have certain limitations when they are used in queries against SQL Server 2000. For more information, see the "Skip and Take Exceptions in SQL Server 2000" entry in Troubleshooting.

LINQ to SQL translates Skip<TSource> by using a subquery with the SQL NOT EXISTS clause. This translation has the following limitations:

  • The argument must be a set. Multisets are not supported, even if ordered.

  • The generated query can be much more complex than the query generated for the base query on which Skip<TSource> is applied. This complexity can cause decrease in performance or even a time-out.

The following example uses Take to select the first five Employees hired. Note that the collection is first sorted by 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, _

The following example uses Skip<TSource> to select all except the 10 most expensive Products.

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

        For Each prodObj As Product In lessExpensiveQuery

The following example combines the Skip<TSource> and Take<TSource> methods to skip the first 50 records and then return the next 10.

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

        For Each custRecord As Customer In custQuery2

Take<TSource> and Skip<TSource> operations are well defined only against ordered sets. The semantics for unordered sets or multisets is undefined.

Because of the limitations on ordering in SQL, LINQ to SQL tries to move the ordering of the argument of the Take<TSource> or Skip<TSource> operator to the result of the operator.

System_CAPS_ICON_note.jpg Note

Translation is different for SQL Server 2000 and SQL Server 2005. If you plan to use Skip<TSource> with a query of any complexity, use SQL Server 2005.

Consider the following LINQ to SQL query for 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

LINQ to SQL moves the ordering to the end in the SQL code, as follows:

SELECT TOP 1 [t0].[CustomerID], [t0].[CompanyName],  
FROM [Customers] AS [t0]  
    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]  

When Take<TSource> and Skip<TSource> are chained together, all the specified ordering must be consistent. Otherwise, the results are undefined.

For non-negative, constant integral arguments based on the SQL specification, both Take<TSource> and Skip<TSource> are well-defined.

Query Examples
Standard Query Operator Translation