Entity Framework - SkipメソッドとTakeメソッドを使うとFETCH句とOFFSET句が使われることを確認する
SQL Server 2012からOFFSET句とFETCH句が追加されて、クエリだけでページングを実現できるようになりました。Entity Frameworkを使っているときに、SkipメソッドとTakeメソッドを使うとOFFSET句とFETCH句が使われるの?ってあたりが気になったのでログで発行されるクエリを確認してみました。
以前OFFSET句とFETCH句を試した記事はこちら。
SQL Server - OFFSET 句と FETCH 句 - いちろぐ
以前と同じように1~10までの連番を用意して確認してみます。
テストデータ
with Source(Value) as( select 1 union all select Value + 1 from Source ) select top 10 * into Sequence from Source; select * from Sequence; /* Value ----------- 1 2 3 4 5 6 7 8 9 10 */
Entity Frameworkを使ってログを確認
まずモデルとかDbContextとか。ログを出力するようにしています。
[Table("Sequence")] class Sequence { [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] public int Value { get; set; } } class AppDbContext : DbContext { public AppDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { // ログをコンソールに出力 Database.Log = Console.WriteLine; } public IDbSet<Sequence> Sequences { get; set; } }
SkipメソッドとTakeメソッド
SkipメソッドとTakeメソッドを使ってデータを取得してみます。
using (var dbContext = new AppDbContext(connectionString)) { dbContext.Sequences .OrderBy(entry => entry.Value) .Skip(4) .Take(3) .ToList() .ForEach(entry => Console.WriteLine(entry.Value)); // 5 // 6 // 7 }
発行されるSQLはOFFSET句とFETCH句が使われています。
SELECT [Extent1].[Value] AS [Value] FROM [dbo].[Sequence] AS [Extent1] ORDER BY [Extent1].[Value] ASC OFFSET 4 ROWS FETCH NEXT 3 ROWS ONLY
Skipメソッドのみ
Skipメソッドだけ使うと、OFFSET句だけが使われています。
using (var dbContext = new AppDbContext(connectionString)) { dbContext.Sequences .OrderBy(entry => entry.Value) .Skip(7) .ToList() .ForEach(entry => Console.WriteLine(entry.Value)); // 8 // 9 // 10 }
SELECT [Extent1].[Value] AS [Value] FROM [dbo].[Sequence] AS [Extent1] ORDER BY [Extent1].[Value] ASC OFFSET 7 ROWS
Takeメソッドのみ
ちなみにTakeメソッドだけ使うと、TOP句になります。
using (var dbContext = new AppDbContext(connectionString)) { dbContext.Sequences .OrderBy(entry => entry.Value) .Take(3) .ToList() .ForEach(entry => Console.WriteLine(entry.Value)); // 1 // 2 // 3 }
SELECT TOP (3) [Extent1].[Value] AS [Value] FROM [dbo].[Sequence] AS [Extent1] ORDER BY [Extent1].[Value] ASC
さらにちなみにですが、Entity FrameworkではSkipメソッドの前にOrderByメソッドを呼び出す必要があります。呼び出さないとNotSupportedExceptionがスローされます。
The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
次の環境で確認しました。
- SQL Server 2012 Developer Edition
- Entity Framework 6.1.3