アレがアレでアレ

(できれば)プログラミング関係のことを書きたい

Entity Framework Coreが生成するSQLクエリを確認する

ASP.NET CoreでEntity Framework Coreが生成するSQLクエリをログに出力してみます。
ここでは.NET Coreの組み込みのログ機能を使いました。

実行環境

.NET Core 3.1

SQLクエリのパラメーターをログに含める

デフォルトでは、SQLクエリに渡されるパラメーターは表示されないようになっています。
これを表示させるように修正します。

Startup.cs内のConfigureServicesメソッド内にあるEF Coreの設定が、以下のように構成されているとします。

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddDbContext<SchoolContext>(options =>
        options.UseSqlite(Configuration.GetConnectionString("SchoolContext")));
}

DbContextOptionsBuilderクラスのEnableSensitiveDataLoggingメソッドを追加すると有効化。

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddDbContext<SchoolContext>(options =>
    {
        options.EnableSensitiveDataLogging(); // new
        options.UseSqlite(Configuration.GetConnectionString("SchoolContext"));
    });
}

appsettings.jsonを修正

EF CoreのSQLがログに表示されるように、
appsettings.jsonLogLevel"Microsoft.EntityFrameworkCore": "Information"を追加します。

開発時のみ表示されればいいので、appsettings.Development.jsonに記述しました。

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "Microsoft.EntityFrameworkCore": "Information"
    }
  }
}

以上で設定は完了です。

SQLを確認

Webアプリを実行して、データベースを使う処理を実行します。
Visual Studio Codeでは「DEBUG CONSOLE」にSQLが出力されています。

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (2ms) [Parameters=[@__Format_1='%Yan%' (Size = 5)], CommandType='Text', CommandTimeout='30']
      SELECT COUNT(*)
      FROM "Student" AS "s"
      WHERE ("s"."LastName" LIKE @__Format_1) OR ("s"."FirstName" LIKE @__Format_1)

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Microsoft.EntityFrameworkCore.Database.Command: Information: Executed DbCommand (1ms) [Parameters=[@__Format_1='%Yan%' (Size = 5), @__p_3='3' (DbType = String), @__p_2='0' (DbType = String)], CommandType='Text', CommandTimeout='30']
SELECT "s"."ID", "s"."EnrollmentDate", "s"."FirstName", "s"."LastName"
FROM "Student" AS "s"
WHERE ("s"."LastName" LIKE @__Format_1) OR ("s"."FirstName" LIKE @__Format_1)
ORDER BY "s"."LastName"
LIMIT @__p_3 OFFSET @__p_2
      Executed DbCommand (1ms) [Parameters=[@__Format_1='%Yan%' (Size = 5), @__p_3='3' (DbType = String), @__p_2='0' (DbType = String)], CommandType='Text', CommandTimeout='30']
      SELECT "s"."ID", "s"."EnrollmentDate", "s"."FirstName", "s"."LastName"
      FROM "Student" AS "s"
      WHERE ("s"."LastName" LIKE @__Format_1) OR ("s"."FirstName" LIKE @__Format_1)
      ORDER BY "s"."LastName"
      LIMIT @__p_3 OFFSET @__p_2

デフォルトではパラメータが?になっていますが、 EnableSensitiveDataLoggingを追加することで中身が表示されています。

EnableSensitiveDataLogging なし

[Parameters=[@__Format_1='?' (Size = 5)], CommandType='Text', CommandTimeout='30']

EnableSensitiveDataLogging あり

[Parameters=[@__Format_1='%Yan%' (Size = 5)], CommandType='Text', CommandTimeout='30']

おわりに

ORMはブラックボックスな部分が多いので、開発時はSQLが出力されるようになっているほうがいいですね。
ASP.NET CoreもEntity Framework Coreもデフォルトでログが出力されるようになっているので、設定はかなり楽でした。

参考