LINQ-to-SQL はコンポーズ可能なクエリをサポートしていますか?
-
01-07-2019 - |
質問
C# に詳しくないプログラマとして言えば、次のような LINQ クエリの評価セマンティクスに興味があります。
var people = from p in Person
where p.age < 18
select p
var otherPeople = from p in people
where p.firstName equals "Daniel"
select p
仮定して Person
を定義する ADO エンティティです。 age
そして firstName
フィールド、これはデータベースの観点からどうなるでしょうか?具体的には、 people
クエリを実行してメモリ内構造を生成し、その後、 otherPeople
クエリ?あるいは、 otherPeople
からクエリに関するデータを取得するだけです people
そして、新しいデータベースピアクエリを生成しますか?では、これらのクエリの両方を反復処理すると、いくつの SQL ステートメントが実行されるでしょうか?
解決
それらは構成可能です。これが可能なのは、LINQ クエリが実際には式 (データとしてのコード) であり、LINQ-to-SQL などの LINQ プロバイダーがそれを評価し、対応する SQL を生成できるためです。
LINQ クエリは遅延評価されるため (例:要素を反復処理するまで実行されません)、示したコードは実際にはデータベースに触れません。otherPeople を反復処理するまでは、SQL が生成されて実行されません。
他のヒント
はい、結果としてクエリが作成されます。これには完全な where 句が含まれます。SQL プロファイリングを有効にして、実際に試してみてください。
Linq は式ツリーを通じてこれを行います。最初の linq ステートメントは式ツリーを生成します。クエリは実行されません。2 番目の linq ステートメントは、最初の linq ステートメントで作成された式ツリーに基づいて構築されます。このステートメントは、結果のコレクションを列挙する場合にのみ実行されます。
var people = from p in Person
where p.age < 18
select p
翻訳すると:
SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0]
WHERE [t0].[Age] < @p0
ここで、@p0 は 18 として送信されます。
var otherPeople = from p in people
where p.firstName equals "Daniel"
select p
翻訳すると:
SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0]
WHERE [t0].[FirstName] = @p0
ここで、@p0 は「ダニエル」として送信されます。
var morePeople = from p1 in people
from p2 in otherPeople
where p1.PersonId == p2.PersonId
select p1;
翻訳すると:
SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0], [dbo].[Person] AS [t1]
WHERE ([t0].[PersonId] = [t1].[PersonId]) AND ([t0].[Age] < @p0) AND ([t1].[FirstName] = @p1)
ここで、@p0 は 18、@p1 は「ダニエル」です。
疑わしい場合は、IQueryable で ToString() を呼び出すか、DataContext の Log プロパティに TextWriter を指定します。
people
そして otherPeople
タイプのオブジェクトが含まれています IQueryable<Person>
.
両方を別々に反復すると、2 つのクエリが実行されます。ただ反復するだけなら otherPeople
, を指定すると、2 つの where 句を使用して予期されるクエリが実行されます。
もし、するなら .ToList()
の上 people
そして返されたものを使用します List<Person>
2 番目のクエリでは、people ではなく、LINQ-to-Objects になり、SQL は実行されません。
この動作は遅延実行と呼ばれます。つまり、必要になるまでクエリは実行されません。実行前は、最終的なクエリを作成するために操作される式ツリーにすぎません。
これらのクエリは両方とも、最終結果にアクセスしようとするときに実行されます。DataContext オブジェクトのプロパティから生成された元の SQL を表示してみることができます。