LINQ to Entities で sp_executesql になる/ならない(ADO.NET Entity Framework)
LINQ to Entities で次のように Where 句を記述したとします。
Using ctx As New NorthwindEntities() Dim query = From p In northem.Products _ Where p.ProductID = 4 _ Select p.ProductID, p.ProductName For Each p In query Console.WriteLine(p.ProductID & ": " & p.ProductName) Next End Using
p.ProductID = 4 のように、値を LINQ クエリ内に埋め込んだ場合は、sp_executesql が利用されずに、次のように SQL が内部実行されてしまいます。
SELECT [Extent1].[ProductID] AS [ProductID], [Extent1].[ProductName] AS [ProductName] FROM [dbo].[Products] AS [Extent1] WHERE 4 = [Extent1].[ProductID]
このように sp_executesql が利用されない場合は、プロシージャ キャッシュ(実行プランが格納される SQL Server 内のメモリ領域)に Ad Hoc クエリとして登録されてしまうため(今回のケースでは単純なクエリなので自動パラメータ化も行われますが)、キャッシュ領域の無駄使いが発生する可能性が高くなるので、注意する必要があります。
しかし、通常は、値には変数を利用する場合が多いと思いますので、こういう使い方はほとんどしないと思いますが、値を直接埋め込んだ場合とそうでない場合に sp_executesql が利用される/されないが変化するということは、頭の片隅の留めておくことをお勧めします。
次のように、値に変数を利用する場合は、
Dim pID As Integer = 4 Dim query = From p In ctx.Products _ Where p.ProductID = pID _ Select p.ProductID, p.ProductName
内部実行される SQL は、
exec sp_executesql N'SELECT [Extent1].[ProductID] AS [ProductID], [Extent1].[ProductName] AS [ProductName], FROM [dbo].[Products] AS [Extent1] WHERE [Extent1].[ProductID] = @p__linq__0',N'@p__linq__0 int',@p__linq__0=4
のように sp_executesql が実行されて、パラメーター化が行われるので、キャッシュの無駄使いにはなりません(実行プランの再利用性も高まります)。
なお、プロシージャ キャッシュの中身を参照する方法については、こちらへ投稿しています。
http://d.hatena.ne.jp/matu_tak/20090905/1255059685