skip(n).take(m)
を実行した場合、疑問に対する簡単な回答を提供しようとしています linqのメソッド(データベースサーバーとしてSQL 2005/2008を使用)では、クエリはSelect ROW_NUMBER() Over ...
を使用します。 ステートメント、withは、SQLエンジンでの直接ページングです。
例を挙げると、mtcity
というデータベーステーブルがあります。 そして私は次のクエリを書きました(エンティティへのlinqでも同様に機能します):
using (DataClasses1DataContext c = new DataClasses1DataContext())
{
var query = (from MtCity2 c1 in c.MtCity2s
select c1).Skip(3).Take(3);
//Doing something with the query.
}
結果のクエリは次のようになります:
SELECT [t1].[CodCity],
[t1].[CodCountry],
[t1].[CodRegion],
[t1].[Name],
[t1].[Code]
FROM (
SELECT ROW_NUMBER() OVER (
ORDER BY [t0].[CodCity],
[t0].[CodCountry],
[t0].[CodRegion],
[t0].[Name],
[t0].[Code]) AS [ROW_NUMBER],
[t0].[CodCity],
[t0].[CodCountry],
[t0].[CodRegion],
[t0].[Name],
[t0].[Code]
FROM [dbo].[MtCity] AS [t0]
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
ORDER BY [t1].[ROW_NUMBER]
これはウィンドウ化されたデータアクセスです(かなりクールですが、btw cuzは最初からデータを返し、条件が満たされている限りテーブルにアクセスします)。これは次のようになります:
With CityEntities As
(
Select ROW_NUMBER() Over (Order By CodCity) As Row,
CodCity //here is only accessed by the Index as CodCity is the primary
From dbo.mtcity
)
Select [t0].[CodCity],
[t0].[CodCountry],
[t0].[CodRegion],
[t0].[Name],
[t0].[Code]
From CityEntities c
Inner Join dbo.MtCity t0 on c.CodCity = t0.CodCity
Where c.Row Between @p0 + 1 AND @p0 + @p1
Order By c.Row Asc
ただし、この2番目のクエリは、インデックスのみを使用してデータアクセスウィンドウを作成するため、linqの結果よりも高速に実行されます。つまり、フィルタリングが必要な場合は、エンティティリスト(行が作成される場所)にフィルタリングを含める必要があります(または含める必要があります)。また、良好なパフォーマンスを維持するために、いくつかのインデックスも作成する必要があります。
さて、何がいいですか?
ロジックにかなり堅実なワークフローがある場合、適切なSQLの方法を実装するのは複雑になります。その場合、LINQが解決策になります。
ロジックのその部分を(ストアドプロシージャで)SQLに直接下げることができれば、(インデックスを使用して)2番目に示したクエリを実装し、SQLがの実行プランを生成して保存できるようになるため、さらに優れたものになります。クエリ(パフォーマンスの向上)。