Entity Framework Core系列教程-25-Entity Framework Core日志

Entity Framework Core日志

我们经常需要在EF Core中记录SQL并更改跟踪信息以进行调试。
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

下图说明了DbContext如何与日志记录API和控制台日志记录提供程序一起使用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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团队建议在应用程序生存期内,将同一个logger工厂对象与DbContext类的所有实例一起使用。否则,可能会导致内存泄漏和性能下降。您还可以创建一个单独的工厂类,为您提供LoggerFactory类的单例对象,以与DbContext一起使用。
让我们详细了解上面的示例。
首先,我们创建了LoggerFactory类的对象,并将其分配给ILoggerFactory类型的静态变量,如下所示。

public static readonly ILoggerFactory loggerFactory = new LoggerFactory(
    new[] { new ConsoleLoggerProvider ((_, __) => true, true) }
);

LoggerFactory可以包含一个或多个日志记录提供程序,可用于同时记录到多个介质。 LoggerFactory的构造函数接受一系列不同的记录器提供程序对象作为new [] {}。我们希望在控制台上显示日志,因此创建控制台记录器提供程序ConsoleLoggerProvider的对象。
ConsoleLoggerProvider有四个构造函数。使用允许lambda表达式(Func <>)进行日志过滤的方法,并使用includeScope布尔值,如下所示。

new ConsoleLoggerProvider((_, __) => true, true)

在这里,我们不想过滤任何信息,因此lambda表达式将始终返回true (_, __) => true.

创建ILoggerFactory对象之后,使用DbContextOptionsBuilder在OnConfiguring()方法中将DbContext与ILoggerFactory绑定在一起。

optionsBuilder.UseLoggerFactory(loggerFactory)

因此,我们将DbContext与包括控制台记录器提供程序的LoggerFactory绑定在一起。现在,每当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包含DbLoggerCategory类,以使用其Name属性获取Entity Framework Core记录器类别。下表列出了不同的记录器类别。

日志类别类 描述
Database.Command 命令执行的记录器类别,包括发送到数据库的SQL。
Database.Connection 数据库连接操作的记录器类别。
Database.Transaction 数据库事务的记录器类别。
Infrastructure EF基础结构的其他消息的记录器类别。
Migration 迁移的记录器类别。
Model 用于模型构建和元数据的记录器类别。
Query 查询的记录器类别(不包括生成的SQL)。
Scaffolding 脚手架和逆向工程的记录仪类别。
Update DbContext.SaveChanges()消息的记录器类别。

记录SQL查询

要仅记录SQL查询,请在ConsoleLoggerProvider的构造函数的lambda表达式中指定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();
发布了177 篇原创文章 · 获赞 61 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/xingkongtianyuzhao/article/details/104227989
今日推荐