次の方法で共有


方法 : シーケンスの要素を返すまたはスキップする (LINQ to SQL)

更新 : November 2007

Take<TSource> 演算子を使用すると、シーケンス内の指定された数の要素を返し、残りをスキップできます。

Skip<TSource> 演算子を使用すると、シーケンス内の指定された数の要素をスキップし、残りを返すことができます。

メモ :

Take<TSource>Skip<TSource> には、SQL Server 2000 に対するクエリで使用する場合に特定の制限があります。詳細については、「トラブルシューティング (LINQ to SQL)」の「SQL Server 2000 の Skip 例外と Take 例外」を参照してください。

LINQ to SQL は、SQL NOT EXISTS 句を含むサブクエリを使用して Skip<TSource> を変換します。この変換には、次のような制限があります。

  • 引数は、セットである必要があります。順序が指定されていてもマルチセットはサポートされません。

  • 生成されるクエリは、Skip<TSource> が適用される基本クエリに対して生成されるクエリより複雑な場合があります。複雑なために、パフォーマンスが低下したり、タイムアウトが発生することもあります。

使用例

次の例では、Take を使用して、雇用された最初の 5 人の Employees を選択します。コレクションは最初、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);
}

次の例では、Skip<TSource> を使用して、最も値段が高い 10 個の Products 以外のすべてを選択します。

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

次の例では、Skip<TSource> メソッドと Take<TSource> メソッドを組み合わせて、最初の 50 レコードをスキップし、次の 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
    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);
}

Take<TSource> 操作と Skip<TSource> 操作は、順序付けされたセットに対してのみ正しく定義されます。順序付けされていないセットまたはマルチセットのセマンティクスは未定義です。

SQL での順序付けの制限により、LINQ to SQL は、Take<TSource> 演算子または Skip<TSource> 演算子の引数の順序を、演算子の結果に移動することを試みます。

メモ :

SQL Server 2000 と SQL Server 2005 で変換は異なります。複雑さに関係なくクエリを指定して Skip<TSource> を使用する予定の場合は、SQL Server 2005 を使用してください。

SQL Server 2000 に対して次の LINQ to SQL クエリを検討します。

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 は、次に示すように、順序付けを SQL コードの最後に移動します。

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]

Take<TSource>Skip<TSource> を連結する場合は、指定されているすべての順序が一致する必要があります。それ以外の場合は、未定義の結果が返されます。

SQL の仕様に基づく負でない定数の整数引数に対して、Take<TSource>Skip<TSource> の両方とも正しく定義されます。

参照

参照

標準クエリ演算子の変換 (LINQ to SQL)

その他の技術情報

クエリの例 (LINQ to SQL)