Zurückgeben oder Überspringen von Elementen in einer Sequenz

Verwenden Sie den Take-Operator, um eine bestimmte Anzahl von Elementen in einer Sequenz zurückzugeben und den Rest zu überspringen.

Verwenden Sie den Skip-Operator um eine bestimmte Anzahl von Elementen in einer Sequenz zu überspringen und den Rest zurückzugeben.

Hinweis

Take und Skip weisen bestimmte Einschränkungen auf, wenn sie für Abfragen in SQL Server 2000 verwendet werden. Weitere Informationen finden Sie im Eintrag „Überspringen und Behandeln von Ausnahmen in SQL Server 2000“ unter Problembehandlung.

LINQ to SQL übersetzt Skip mithilfe einer Unterabfrage mit der SQL NOT EXISTS-Klausel. Diese Übersetzung weist die folgenden Einschränkungen auf:

  • Das Argument muss ein Satz sein. Multisets werden nicht unterstützt, auch dann nicht, wenn diese geordnet sind.

  • Die erzeugte Abfrage kann wesentlich komplexer sein als die Abfrage, die für die Basisabfrage erstellt wurde, auf die Skip angewendet wird. Diese Komplexität kann zu einer Abnahme der Leistung oder sogar zu einer Zeitüberschreitung führen.

Beispiel 1

Im folgenden Beispiel wird Take verwendet, um die ersten fünf eingestellten Employees auszuwählen. Beachten Sie, dass die Auflistung zuerst nach HireDate sortiert wird.

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);
}
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

Beispiel 2

Im folgenden Beispiel wird Skip verwendet, um alle außer den zehn teuersten Products auszuwählen.

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);
}
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

Beispiel 3

Im folgenden Beispiel werden die Skip-Methode und die Take-Methode kombiniert, um die ersten 50 Datensätze zu überspringen und dann die nächsten zehn zurückzugeben.

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);
}
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

Die Take-Operation und die Skip-Operation sind nur bei geordneten Sätzen gut definiert. Die Semantik für ungeordnete Sätze oder Multisets ist nicht definiert.

Aufgrund der Sortierungseinschränkungen in SQL versucht LINQ to SQL, die Sortierung des Arguments für den Operator Take oder Skip auf das Operatorergebnis zu verlagern.

Hinweis

Die Übersetzung unterscheidet sich für SQL Server 2000 und SQL Server 2005. Wenn Sie planen, Skip mit einer komplexeren Abfrage einzusetzen, verwenden Sie SQL Server 2005.

Betrachten Sie die folgende LINQ to SQL-Abfrage für SQL Server 2000:

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);
}
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

LINQ to SQL verschiebt die Sortierung im SQL-Code wie folgt an das Ende:

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]

Wenn Take und Skip verkettet werden, muss die angegebene Sortierung konsistent sein. Andernfalls sind die Ergebnisse nicht definiert.

Für nicht negative, konstante, ganzzahlige Argumente auf Grundlage der SQL-Spezifikation sind Take und Skip klar definiert.

Siehe auch