Entity Framework Coreログ
SQLをEF Coreに記録し、デバッグのためにトレース情報を変更する必要があることがよくあります。
EF Coreログは、.NET Coreのログメカニズムと自動的に統合されます。したがって、EF Coreのログを暗黙的に使用する前に、.NET Coreログに関する基本を理解してください。
Entity Framework Coreは.NET Coreロギングと統合され、SQLを記録し、トレース情報をさまざまな出力ターゲットに変更します。まず、選択したログプロバイダーのNugetパッケージをインストールし、次にDbContextをILoggerFactoryにバインドします。
ロギングプロバイダーのNuGetパッケージをインストールしましょう。ここでは、コンソールにログを表示するため、NuGetパッケージマネージャーからMicrosoft.Extensions.Logging.Console NuGetパッケージをインストールするか、パッケージマネージャーコンソールで次のコマンドを実行します。
Install-Package Microsoft.Extensions.Logging.Console
次の図は、ロギングAPIおよびコンソールロギングプロバイダーでDbContextがどのように使用されるかを示しています。
[外部チェーン画像の転送に失敗しました。ソースサイトに盗難防止チェーンメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-afUjJAU3-1581165281344)(d:\ note \ efcore \ pic \ 27.png)]
コンソールロガープロバイダーをインストールした後、以下に示すように、LoggerFactoryの静的/単一インスタンスを作成し、それをDbContextにバインドする必要があります。
public class SchoolContext : DbContext
{
//static LoggerFactory object
public static readonly ILoggerFactory loggerFactory = new LoggerFactory(new[] {
new ConsoleLoggerProvider((_, __) => true, true)
});
//or
// public static readonly ILoggerFactory loggerFactory = new LoggerFactory().AddConsole((_,___) => true);
public SchoolContext():base()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLoggerFactory(loggerFactory) //tie-up DbContext with LoggerFactory object
.EnableSensitiveDataLogging()
.UseSqlServer(@"Server=.\SQLEXPRESS;Database=SchoolDB;Trusted_Connection=True;");
}
public DbSet<Student> Students { get; set; }
}
上記の例では、LoggerFactoryクラスのオブジェクトを作成し、それをILoggerFactoryタイプの静的変数に割り当てました。次に、このオブジェクトをOnConfiguring()メソッドのoptionsBuilder.UseLoggerFactory()メソッドに渡しました。これにより、DbContextがloggerFactoryオブジェクトと情報を共有できるようになり、すべてのログ情報がコンソールに表示されます。
デフォルトでは、EF Coreはフィルターパラメーター値などの機密データを記録しません。したがって、EnableSensitiveDataLogging()を呼び出して機密データを記録します。
注:
EFチームは、アプリケーションの存続期間中、DbContextクラスのすべてのインスタンスで同じロガーファクトリオブジェクトを使用することをお勧めします。そうしないと、メモリリークやパフォーマンスの低下を引き起こす可能性があります。DbContextで使用するLoggerFactoryクラスのシングルトンオブジェクトを提供する個別のファクトリクラスを作成することもできます。
上記の例を詳しく見てみましょう。
最初に、以下に示すように、LoggerFactoryクラスのオブジェクトを作成し、タイプILoggerFactoryの静的変数に割り当てました。
public static readonly ILoggerFactory loggerFactory = new LoggerFactory(
new[] { new ConsoleLoggerProvider ((_, __) => true, true) }
);
LoggerFactoryには、1つ以上のログレコードプロバイダーを含めることができます。これを使用して、同時に複数のメディアに記録できます。LoggerFactoryのコンストラクターは、一連の異なるロガープロバイダーオブジェクトをnew [] {}として受け入れます。ログをコンソールに表示するため、コンソールロガープロバイダーConsoleLoggerProviderのオブジェクトを作成します。
ConsoleLoggerProviderには4つのコンストラクタがあります。以下に示すように、ログフィルタリングにラムダ式(Func <>)を許可するメソッドを使用し、includeScopeブール値を使用します。
new ConsoleLoggerProvider((_, __) => true, true)
ここでは、情報をフィルタリングしたくないので、ラムダ式は常にtrue(_、__)=> trueを返します。
ILoggerFactoryオブジェクトを作成した後、DbContextOptionsBuilderを使用して、DbContextとILoggerFactoryをOnConfiguring()メソッドでバインドします。
optionsBuilder.UseLoggerFactory(loggerFactory)
したがって、コンソールロガープロバイダーを含むLoggerFactoryにDbContextをバインドします。これで、DbContextインスタンスが操作を実行するたびに、コンソールですべてのログを確認できます。
次の例を考えてみましょう。
using (var context = new SchoolContext())
{
var std = new Student(){ StudentName = "Steve" };
context.Add(std);
context.SaveChanges();
Console.ReadLine();
}
上記の例では、コンソールに次のログが表示されます。
dbug: Microsoft.EntityFrameworkCore.Infrastructure[100401]
An 'IServiceProvider' was created for internal use by Entity Framework.
info: Microsoft.EntityFrameworkCore.Infrastructure[100403]
Entity Framework Core 2.0.0-rtm-26452 initialized 'SchoolContext' using pr
ovider 'Microsoft.EntityFrameworkCore.SqlServer' with options: SensitiveDataLoggingEnabled
dbug: Microsoft.EntityFrameworkCore.Database.Connection[200000]
Opening connection to database 'SchoolDB' on server '.\SQLEXPRESS'.
dbug: Microsoft.EntityFrameworkCore.Database.Connection[200001]
Opened connection to database 'SchoolDB' on server '.\SQLEXPRESS'.
dbug: Microsoft.EntityFrameworkCore.Database.Transaction[200200]
Beginning transaction with isolation level 'ReadCommitted'.
warn: Microsoft.EntityFrameworkCore.Database.Command[100400]
Sensitive data logging is enabled. Log entries and exception messages may
include sensitive application data, this mode should only be enabled during development.
dbug: Microsoft.EntityFrameworkCore.Database.Command[200100]
Executing DbCommand [Parameters=[@p0='' (DbType = DateTime2), @p1='' (DbTy
pe = Int32), @p2='0', @p3='' (Size = 8000) (DbType = Binary), @p4='Steve' (Size = 4000), @p5='0'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Students] ([DateOfBirth], [GradeId], [Height], [Photo], [Stud
entName], [Weight])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
SELECT [StudentID]
FROM [Students]
WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();
info: Microsoft.EntityFrameworkCore.Database.Command[200101]
Executed DbCommand (68ms) [Parameters=[@p0='' (DbType = DateTime2), @p1=''
(DbType = Int32), @p2='0', @p3='' (Size = 8000) (DbType = Binary), @p4='Steve'
(Size = 4000), @p5='0'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Students] ([DateOfBirth], [GradeId], [Height], [Photo], [Stud
entName], [Weight])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
SELECT [StudentID]
FROM [Students]
WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();
dbug: Microsoft.EntityFrameworkCore.Database.Command[200300]
A data reader was disposed.
dbug: Microsoft.EntityFrameworkCore.Database.Transaction[200202]
Committing transaction.
dbug: Microsoft.EntityFrameworkCore.Database.Connection[200002]
Closing connection to database 'SchoolDB' on server '.\SQLEXPRESS'.
dbug: Microsoft.EntityFrameworkCore.Database.Connection[200003]
Closed connection to database 'SchoolDB' on server '.\SQLEXPRESS'.
dbug: Microsoft.EntityFrameworkCore.Database.Transaction[200204]
Disposing transaction.
ご覧のとおり、すべての情報が記録されています。
ログのフィルタリング
上記の例では、DbContextはエンティティを保存するときにすべての情報を記録します。すべての情報を記録したくない場合や、不要なログをフィルタリングしたくない場合があります。EF Coreでは、ロガーのカテゴリとログレベルを指定することで、ログをフィルタリングできます。
ログ分類
EF Core 2.xには、Nameプロパティを使用してEntity Framework Coreロガーカテゴリを取得するためのDbLoggerCategoryクラスが含まれています。次の表に、ロガーのさまざまなカテゴリを示します。
ログカテゴリ | 説明文 |
---|---|
Database.Command | データベースに送信されたSQLを含む、コマンドが実行するロガーのタイプ。 |
Database.Connection | データベース接続操作のロガーカテゴリ。 |
Database.Transaction | データベーストランザクションのロガーカテゴリ。 |
インフラ | EFインフラストラクチャ内の他のメッセージのレコーダーカテゴリ。 |
マイグレーション | 移行されたロガーのカテゴリ。 |
型番 | モデルの構築とメタデータに使用されるロガーカテゴリ。 |
クエリ | クエリのロガーカテゴリ(生成されたSQLを除く)。 |
足場 | 足場とリバースエンジニアリング用のレコーダーのタイプ。 |
更新 | DbContext.SaveChanges()メッセージのロガーカテゴリ。 |
SQLクエリのログ
SQLクエリのみをログに記録するには、以下に示すように、ConsoleLoggerProviderコンストラクターのラムダ式でDbLoggerCategory.Database.CommandカテゴリーとLogLevel.Informationを指定します。
public static readonly ILoggerFactory consoleLoggerFactory
= new LoggerFactory(new[] {
new ConsoleLoggerProvider((category, level) =>
category == DbLoggerCategory.Database.Command.Name &&
level == LogLevel.Information, true)
});
または、デフォルトでは、LoggerFactoryでAddConsole()メソッドを呼び出すだけで、SQLクエリを記録できます。
public static readonly ILoggerFactory consoleLoggerFactory
= new LoggerFactory().AddConsole();
これで、DbContextを使用してエンティティを保存する次のクエリ情報が記録されます。
info: Microsoft.EntityFrameworkCore.Database.Command[200101]
Executed DbCommand (73ms) [Parameters=[@p0='' (DbType = DateTime2), @p1=''
(DbType = Int32), @p2='0', @p3='' (Size = 8000) (DbType = Binary), @p4='Steve'
(Size = 4000), @p5='0'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Students] ([DateOfBirth], [GradeId], [Height], [Photo], [Stud
entName], [Weight])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
SELECT [StudentID]
FROM [Students]
WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();