シーケンスの要素の取得またはスキップ
Take 演算子を使用すると、シーケンス内の指定された数の要素を返し、残りをスキップできます。
Skip 演算子を使用すると、シーケンス内の指定された数の要素をスキップし、残りを返すことができます。
Note
Take と Skip を SQL Server 2000 に対するクエリで使用する場合は、いくつかの制限があります。 詳しくは、「トラブルシューティング」の「SQL Server 2000 の Skip 例外と Take 例外」をご覧ください。
LINQ to SQL では、SQL の NOT EXISTS
句を含むサブクエリを使用して、Skip が変換されます。 この変換には、次のような制限があります。
引数は、セットである必要があります。 順序が指定されていてもマルチセットはサポートされません。
生成されるクエリは、Skip が適用される基本クエリに対して生成されるクエリより複雑な場合があります。 複雑なために、パフォーマンスが低下したり、タイムアウトが発生することもあります。
例 1
次の例では、Take
を使用して、雇用された最初の 5 人の Employees
を選択します。 コレクションは最初、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
例 2
次の例では、Skip を使用して、最も値段が高い 10 個の Products
以外のすべてを選択します。
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
例 3
次の例では、Skip メソッドと Take メソッドを組み合わせて、最初の 50 レコードをスキップし、次の 10 レコードを返します。
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
Take 操作と Skip 操作は、順序付けされたセットに対してのみ正しく定義されます。 順序付けされていないセットまたはマルチセットのセマンティクスは未定義です。
SQL での順序付けの制限により、LINQ to SQL は、Take 演算子または Skip 演算子の引数の順序を、演算子の結果に移動することを試みます。
Note
SQL Server 2000 と SQL Server 2005 では変換が異なります。 複雑さに関係なくクエリで Skip を使用する場合は、SQL Server 2005 を使用します。
SQL Server 2000 の場合は次のような LINQ to SQL クエリを検討します。
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 は、次に示すように、順序付けを 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 と Skip を連結する場合は、指定されているすべての順序が一致する必要があります。 それ以外の場合、結果は未定義です。
SQL の仕様に基づく負でない定数の整数引数に対して、Take と Skip の両方とも正しく定義されます。