SqlCommand の実行を SQL Server Profiler でトレースしてみた
SqlCommand の ExecuteReader でクエリを実行する時にパラメータを渡すと sp_executesql を使って実行されます。パラメータを使わないと sp_executesql は使われないようです。
MSDN より引用します。
.NET Framework version 1.1 以降では、ExecuteReader は、コマンドにパラメーターが含まれている場合だけ、sp_executesql ストアド プロシージャのコンテキストでコマンドを実行します。
SqlCommand クラス (System.Data.SqlClient)
パフォーマンスを高めるために、ExecuteReader は Transact-SQL sp_executesql システム ストアド プロシージャを使用してコマンドを呼び出します。
前々からこのあたりを確認したかったので、SQL Server Profiler を使ってトレースしてみました。上記リンク先では触れられていない ExecuteNonQuery についても念のため確認してみました。
SQL Server Profiler でトレースを開始
SQL Server Profiler を立ち上げて、トレースするイベントを選択します。
sp_executesql が使われるときはRPC:Completed
イベントが、そうでないときはSQL:BatchCompleted
イベントが発生するのでそれぞれ選択します。
テンプレートは「Standard」のままです。
ExecuteReader と ExecuteNonQuery を実行
SqlCommand の ExecuteReader と ExecuteNonQuery の実行をトレースしてみます。
using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp { class Program { static void Main(string[] args) { var connectionString = new SqlConnectionStringBuilder { DataSource = ".", InitialCatalog = "ConsoleApp", IntegratedSecurity = true, }.ToString(); using (var connection = new SqlConnection(connectionString)) { connection.Open(); // パラメータを使わないExecuteReader using (var command = new SqlCommand("select 1;", connection)) { using (var reader = command.ExecuteReader()) { while (reader.Read()) { Console.WriteLine(reader[0]); // 1 } } } // パラメータを使うExecuteReader => sp_executesql using (var command = new SqlCommand("select @p;", connection)) { command.Parameters.AddWithValue("@p", 2); using (var reader = command.ExecuteReader()) { while (reader.Read()) { Console.WriteLine(reader[0]); // 2 } } } // create table Test(Id int);でテーブルが用意してあるとして // パラメータを使わないExecuteNonQuery using (var command = new SqlCommand("insert into Test values(3);", connection)) { command.ExecuteNonQuery(); } // パラメータを使うExecuteNonQuery => sp_executesql using (var command = new SqlCommand("insert into Test values(@p);", connection)) { command.Parameters.AddWithValue("@p", 4); command.ExecuteNonQuery(); } } } } }
結果
select 1; go exec sp_executesql N'select @p;',N'@p int',@p=2 go insert into Test values(3); go exec sp_executesql N'insert into Test values(@p);',N'@p int',@p=4 go
パラメータがある場合は ExecuteReader と ExecuteNonQuery のどちらでも sp_executesql が使われることを確認できました。