zoukankan      html  css  js  c++  java
  • 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: oteefcorepic27.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();
    
  • 相关阅读:
    某耳机厂商微信公众平台建设方案
    微信公众号订单好评红包返现系统
    LNMP的配置与优化
    微信公众号用户OpenID同步导出系统
    微信公众号无限定时群发系统
    小程序想要什么
    微信支付默认推荐关注规则
    微信小程序(应用号)资源汇总整理
    微信公众平台小程序开发教程
    微信应用号开发教程
  • 原文地址:https://www.cnblogs.com/AlexanderZhao/p/12878798.html
Copyright © 2011-2022 走看看