EF Core での Microsoft.Extensions.Logging の使用

Microsoft.Extensions.Logging は、多くの一般的なログ システム用のプラグイン プロバイダーを備えた拡張可能なログ メカニズムです。 Microsoft が提供するプラグイン (Microsoft.Extensions.Logging.Console など) およびサード パーティのプラグイン (Serilog.Extensions.Logging など) は、NuGet パッケージとして使用できます。

Entity Framework Core (EF Core) は、Microsoft.Extensions.Logging と完全に統合されています。 ただし、特に依存関係の挿入を使用しないアプリケーションの場合は、単純なログ記録を使用することをお勧めします。

ASP.NET Core アプリケーション

Microsoft.Extensions.Logging は、既定で ASP.NET Core アプリケーションによって使用されますAddDbContext または AddDbContextPool を呼び出すと、EF Core では、通常の ASP.NET メカニズムで構成されたログ設定が自動的に使用されます。

その他のアプリケーションの種類

その他のアプリケーションの種類では、GenericHost を使用して、ASP.NET Core で使用されているものと同じ依存関係の挿入パターンを取得できます。 その後、AddDbContext または AddDbContextPool を、ASP.NET Core アプリケーション内と同様に使用できます。

Microsoft.Extensions.Logging は、依存関係の挿入を使用しないアプリケーションについても使用できますが、簡単なロギングの方が設定が簡単です。

Microsoft.Extensions.Logging では LoggerFactory の作成が必要です。 このファクトリは、静的/グローバル インスタンスとしてどこかに格納し、DbContext が作成されるたびに使用する必要があります。 たとえば、ロガー ファクトリは、DbContext の静的プロパティとして格納するのが一般的です。

public static readonly ILoggerFactory MyLoggerFactory
    = LoggerFactory.Create(builder => { builder.AddConsole(); });

このシングルトンまたはグローバル インスタンスは、DbContextOptionsBuilder で EF Core に登録する必要があります。 次に例を示します。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLoggerFactory(MyLoggerFactory)
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFLogging;Trusted_Connection=True;ConnectRetryCount=0");

詳細なメッセージを取得する

ヒント

AddDbContext が使用される場合も、または DbContextOptions インスタンスが DbContext コンストラクターに渡される場合も、OnConfiguring が呼び出されます。 したがって、それは DbContext の構築方法に関係なく、コンテキスト構成を適用するのに理想的な場所となります。

機密データ

既定では、EF Core には例外メッセージ内のデータの値は含まれません。 これは、そのようなデータは機密情報である可能性があるためで、例外が処理されない場合に運用環境で流出するおそれがあるためです。

ただし、特にキーについて、データ値を把握することは、デバッグ時に非常に役立ちます。 これは、EnableSensitiveDataLogging() を呼び出すことによって EF Core 内で有効にすることができます。 次に例を示します。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.EnableSensitiveDataLogging();

詳細なクエリの例外

パフォーマンス上の理由により、EF Core ではデータベース プロバイダーから値を読み取るために各呼び出しを try-catch ブロックでラップすることはしません。 ただし、これによって診断が困難な例外が発生することがあり、特にモデルで許可されない場合にデータベースが NULL を返す場合がそうです。

EnableDetailedErrors をオンにすると、EF によってこれらの try-catch ブロックが導入され、より詳細なエラーが生成されます。 次に例を示します。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.EnableDetailedErrors();

特定のメッセージの構成

EF Core ConfigureWarnings API を使用すると、特定のイベントが発生したときの動作をアプリケーションで変更できます。 これは次の場合に使用できます。

  • イベントがログに記録されるログ レベルを変更する
  • イベントのログ記録を完全にスキップする
  • イベントが発生したときに例外をスローする

イベントのログ レベルの変更

イベントの定義済みログ レベルを変更すると便利な場合があります。 たとえば、以下は 2 つの追加のイベントを LogLevel.Debug から LogLevel.Information に昇格させるために使用できます。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(
            b => b.Log(
                (RelationalEventId.ConnectionOpened, LogLevel.Information),
                (RelationalEventId.ConnectionClosed, LogLevel.Information)));

イベントのログ記録を抑制する

同様に、個々のイベントをログに記録しないようにすることもできます。 これは、確認して理解した警告を無視する場合に特に便利です。 次に例を示します。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Ignore(CoreEventId.DetachedLazyLoadingWarning));

イベントに対してスローする

最後に、特定のイベントに対してスローするように EF Core を構成できます。 これは、警告をエラーに変更する場合に特に便利です。 (実際には、このことが ConfigureWarnings メソッドの本来の目的であったため、そのような名前になっています。)次に例を示します。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Throw(RelationalEventId.QueryPossibleUnintendedUseOfEqualsWarning));

フィルター処理とその他の構成

ログのフィルター処理とその他の構成については、「.NET でのログの記録」を参照してください。

EF Core のログ イベントは、次のいずれかの方法で定義されます。

  • すべての EF Core データベース プロバイダーに共通のイベントの CoreEventId
  • すべてのリレーショナル データベース プロバイダーに共通のイベントの RelationalEventId
  • 現在のデータベース プロバイダーに固有のイベントの類似クラス。 たとえば、SQL Server プロバイダーの場合は SqlServerEventId です。

これらの定義には、Microsoft.Extensions.Logging によって使用される各イベントの、イベント ID、ログ レベル、およびカテゴリが含まれます。