Gewusst wie: Zurückgeben oder Überspringen von Elementen in einer Sequenz (LINQ to SQL)

Aktualisiert: November 2007

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

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

Hinweis:

Take<TSource> und Skip<TSource> weisen bestimmte Einschränkungen auf, wenn diese in Abfragen mit 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).

LINQ to SQL übersetzt Skip<TSource> 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<TSource> angewendet wird. Diese Komplexität kann zu einer Abnahme der Leistung oder sogar zu einer Zeitüberschreitung führen.

Beispiel

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.

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

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

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

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

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

Die Take<TSource>-Operation und die Skip<TSource>-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 des Take<TSource>-Operators oder des Skip<TSource>-Operators auf das Operatorergebnis zu verlagern.

Hinweis:

Die Übersetzung weicht für SQL Server 2000 und SQL Server 2005 ab. Wenn Sie planen, Skip<TSource> mit einer komplexeren Abfrage einzusetzen, verwenden Sie SQL Server 2005.

Beachten Sie die folgende LINQ to SQL-Abfrage für 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 verschiebt die Bestellung 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<TSource> und Skip<TSource> 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<TSource> und Skip<TSource> klar definiert.

Siehe auch

Referenz

Übersetzen von Standardabfrageoperatoren (LINQ to SQL)

Weitere Ressourcen

Beispiele für Abfragen (LINQ to SQL)