http://www.codeproject.com/Articles/231163/IQueryable-Vs-IEnumerable-in-terms-of-LINQ-to-SQL
LINQの結果をIEnumerableとして取得するかIQueryableとして取得するかで発行されるSQLが変わる…?
よくわからないので自分で試してみる。
SchoolClassなる学校のクラスデータが入っているテーブルと、
それに紐つく Scholler(生徒) テーブルを用意。
まずはIEnumerable
private IEnumerable<SchoolClass> GetSchoolAsEnumarable()
{
return from school in db.SchoolClass
where school.Grade > 1
select school;
}
public void ConsoleOutScholler()
{
// クラスデータをIEnumerableとして取得
IEnumerable<SchoolClass> schoolList = GetSchoolAsEnumarable();
// IEnumerableとして取得したクラスデータに生徒テーブルを結合
var schoolerList =
from school in schoolList
join schooler in db.Schooler
on school.ClassID equals schooler.ClassID
where school.Grade > 2
select schooler;
foreach (var schooler in schoolerList)
{
Console.WriteLine("出席番号:" + schooler.Number + " 名前:" + schooler.Name);
}
}
実際にどのようなSQLが発行されているかトレースしてみると…
(データベースはSQLServer)
■発行されたSQL1
SELECT
[Extent1].[ClassID] AS [ClassID],
[Extent1].[Number] AS [Number],
[Extent1].[Name] AS [Name]
FROM [dbo].[Schooler] AS [Extent1]
■発行されたSQL2
SELECT
[Extent1].[ClassID] AS [ClassID],
[Extent1].[Grade] AS [Grade],
[Extent1].[Class] AS [Class]
FROM [dbo].[SchoolClass] AS [Extent1]
WHERE [Extent1].[Grade] > 1
SQLが2つ発行されてる…遅延実行で最終的に一個のSQLになると思ってたんだけど…。
しかも生徒テーブルの方を先に読み込んでいるのがよくわかない件について。
あと school.Grade > 2 がない。えっ。どうやらそちらの条件は.NETの方で絞っているようだ。
次に IQueryable として受け取ってみる
private IQueryable<SchoolClass> GetSchoolAsQueryable()
{
return from school in db.SchoolClass
where school.Grade > 1
select school;
}
public void ConsoleOutScholler()
{
// クラスデータをIQuaryableとして取得
IQueryable<SchoolClass> schoolList = GetSchoolAsQueryable();
// IQuaryableとして取得したクラスデータに生徒テーブルを結合
var schoolerList =
from school in schoolList
join schooler in db.Schooler
on school.ClassID equals schooler.ClassID
where school.Grade > 2
select schooler;
foreach (var schooler in schoolerList)
{
Console.WriteLine("出席番号:" + schooler.Number + " 名前:" + schooler.Name);
}
}
■発行されたSQL
SELECT
[Extent2].[ClassID] AS [ClassID],
[Extent2].[Number] AS [Number],
[Extent2].[Name] AS [Name]
FROM [dbo].[SchoolClass] AS [Extent1]
INNER JOIN [dbo].[Schooler] AS [Extent2] ON [Extent1].[ClassID] = [Extent2].[ClassID]
WHERE ([Extent1].[Grade] > 1) AND ([Extent1].[Grade] > 2)
SQLが一つになったよ!やったね!
で、なんで IEnumerable のときは2つ発行されてたの?
発行されるSQLが違う理由についてはこのサイト↓にIEnumerableは「pull型」、IQueryableは「外部クエリ」という説明があった。
http://www.atmarkit.co.jp/fdotnet/chushin/roadtolinq_01/roadtolinq_01_03.html
> IEnumerable<T>インターフェイスを使っても外部システムからの
> データ取得はできなくはないのだが、データを全件返すという部分がネックになる
そうなの…。
とにかく LINQ to SQL と LINQ to Entities のときは素直に IQueryable として使いますね?(それでいいのか)
0 件のコメント:
コメントを投稿