Partager via


Comment : retourner ou ignorer des éléments d'une séquence

Utilisez l'opérateur Take pour retourner un nombre donné d'éléments dans une séquence et ignorer le reste.

Utilisez l'opérateur Skip pour ignorer un nombre donné d'éléments dans une séquence et retourner le reste.

Notes

Take et Skip sont soumis à certaines limites lorsqu'ils sont utilisés dans des requêtes SQL Server 2000. Pour plus d’informations, consultez « Exceptions d’ignorance (Skip) et d’acceptation (Take) dans SQL Server 2000 » dans Résolution des problèmes.

LINQ to SQL traduit Skip à l’aide d’une sous-requête avec la clause SQL NOT EXISTS. Cette traduction présente les limites suivantes :

  • L’argument doit être un jeu. Les multijeux ne sont pas pris en charge, même s'ils sont ordonnés.

  • La requête générée peut être beaucoup plus complexe que celle qui est générée pour la requête de base sur laquelle Skip est appliqué. Cette complexité peut entraîner une dégradation des performances ou un délai d'expiration.

Exemple 1

L'exemple suivant utilise Take pour sélectionner les cinq premiers Employees embauchés. Notez que la collection est d’abord triée par HireDate.

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

Exemple 2

L'exemple suivant utilise Skip pour sélectionner tous les Products exceptés les dix produits les plus chers.

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

Exemple 3

L'exemple suivant combine les méthodes Skip et Take pour ignorer les cinquante premiers enregistrements et retourner les dix suivants.

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

Les opérations Take et Skip sont bien définies uniquement sur les jeux ordonnés. La sémantique des jeux ou des multijeux non ordonnés n'est pas définie.

Du fait des limitations de classement dans SQL, LINQ to SQL tente de déplacer le classement de l’argument de l’opérateur Take ou Skip vers le résultat de l’opérateur.

Notes

La traduction est différente pour SQL Server 2000 et SQL Server 2005. Si vous envisagez d’utiliser Skip avec une requête d’un niveau de complexité quelconque, utilisez SQL Server 2005.

Examinons la requête LINQ to SQL suivante pour 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 déplace le classement à la fin du code SQL, comme suit :

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]

Lorsque Take et Skip sont enchaînés, l'ensemble du classement spécifié doit être cohérent. Si ce n'est pas le cas, les résultats ne sont pas définis.

Pour les arguments intégraux constants non négatifs basés sur la spécification SQL, Take et Skip sont bien définis.

Voir aussi