.net core实用技巧——将EF Core生成的SQL语句显示在控制台中

 更新时间:2020-09-24 15:09:13   作者:佚名   我要评论(0)

前言
笔者最近在开发和维护一个.NET Core项目,其中使用几个非常有意思的.NET Core相关的扩展,在此总结整理一下。
EF Core性能调优
如果你的项目中使用了EF Core,

前言

笔者最近在开发和维护一个.NET Core项目,其中使用几个非常有意思的.NET Core相关的扩展,在此总结整理一下。

EF Core性能调优

如果你的项目中使用了EF Core, 且正在处于性能调优阶段,那么了解EF Core生成的SQL语句是非常关键的。那么除了使用第三方工具,如何查看EF Core生成的SQL语句呢?这里笔者将给出一个基于.NET Core内置日志组件的实现方式。

创建一个实例项目

我们首先建一个控制台程序,在主程序中我们编写了一个最简单的EF查询。

  class Program {
    static void Main (string[] args) {

      var dbOptionBuilder = new DbContextOptionsBuilder<MyDbContext>();
      dbOptionBuilder
       .UseMySql("server=localhost;port=3306;database=EFCoreSampleDB;userid=root;pwd=a@12345");

      using (var dbContext = new MyDbContext(dbOptionBuilder.Options)) {
        var query = dbContext.Users.ToList();
      }
    }
  }

这里为了演示,我们提前创建了一个MySql数据库,并在项目中创建了一个对应的EF Core上下文。当前上下文中只有一个User实体,该实体只有2个属性UserId和UserName。

  public class MyDbContext : DbContext {

    public MyDbContext (DbContextOptions<MyDbContext> options) : base (options) {

    }

    public DbSet<User> Users { get; set; }
  }
  public class User
  {
    [Key]
    public Guid UserId { get; set;}
    public string UserName { get; set;}
  }

如何生成的SQL语句输出到控制台?

.NET Core中提供了非常完善的日志接口。这里为了和.NET Core的日志接口集成,我们需要实现2个接口,一个是日志提供器接口ILoggerProvider, 一个是日志接口ILogger

EFLoggerProvider.cs

  public class EFLoggerProvider : ILoggerProvider {
    public ILogger CreateLogger (string categoryName) => new EFLogger (categoryName);
    public void Dispose () { }
  }

EFLoggerProvider的代码非常的简单,就是直接返回一个我们后续创建的EFLogger对象。

EFLogger.cs

	public class EFLogger : ILogger {
    private readonly string categoryName;

    public EFLogger (string categoryName) => this.categoryName = categoryName;

    public bool IsEnabled (LogLevel logLevel) => true;

    public void Log<TState> (LogLevel logLevel, 
      EventId eventId,
      TState state, 
      Exception exception, 
      Func<TState, Exception, string> formatter) {
        var logContent = formatter (state, exception);
        Console.WriteLine ();
        Console.WriteLine (logContent);
      }
    }

    public IDisposable BeginScope<TState> (TState state) => null;
  }

这里我们主要使用了内置的formatter格式化了日志信息。

最后我们还需要将自定义的日志处理类和EF Core集成起来。这里我们需要复写上下文类的OnConfiguring方法。在其中通过UseLoggerFactory方法,将我们自定义的日志处理类和EF Core的日志系统关联起来。

	public class MyDbContext : DbContext {

    public MyDbContext (DbContextOptions<MyDbContext> options) : base (options) {

    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {

      var loggerFactory = new LoggerFactory ();
      loggerFactory.AddProvider(new EFLoggerProvider());
      optionsBuilder.UseLoggerFactory(loggerFactory);

      base.OnConfiguring(optionsBuilder);
    }

    public DbSet<User> Users { get; set; }
  }

下面我们启动项目,看一下效果。这里日志信息正确的显示出来了。

PS: 如果项目中使用了通用主机或者ASP.NET Core, 你也可以在服务配置部分,通过DbContextOptions参数配置。

services.AddDbContext<MyDbContext>(options =>
       options.UseSqlServer(Configuration.GetConnectionString("MyDb"))
          .UseLoggerFactory(new LoggerFactory()));

如何去除无关日志?

在前面的步骤中,我们成功的输出了查询语句,但是有一个问题是我们只想查看输出的SQL语句,其他的信息我们都不想要,那么能不能去除掉这些无关日志呢?答案是肯定的。

我们可以在Log方法中,通过分类名称,只输出Microsoft.EntityFrameworkCore.Database.Command分类下的日志,该日志即生成的SQL语句部分。

   public void Log<TState> (LogLevel logLevel, 
 		EventId eventId, 
 		TState state, 
 		Exception exception, 
 		Func<TState, Exception, string> formatter)
  {

    if (categoryName == DbLoggerCategory.Database.Command.Name &&
      logLevel == LogLevel.Information) {
      var logContent = formatter (state, exception);

      Console.WriteLine ();
      Console.ForegroundColor = ConsoleColor.Green;
      Console.WriteLine (logContent);
      Console.ResetColor ();
    }
  }

这里我们也做了一些其他的操作,通过修改控制台输出文本的颜色,高亮了生成的SQL语句。重新启动项目之后,效果如下。

如何显示敏感数据?

这里看似我们已经完成了EF Core的语句输出,但是在实际使用中,你还会遇到另外一个问题。

下面我们修改一下我们的主程序,我们尝试插入一条User信息。

  class Program {
    static void Main (string[] args) {

      var dbOptionBuilder = new DbContextOptionsBuilder<MyDbContext> ();
      dbOptionBuilder.UseMySql ("server=localhost;port=3306;database=EFCoreSampleDB;userid=root;pwd=a@12345");

      using (var dbContext = new MyDbContext (dbOptionBuilder.Options)) {
        dbContext.Users.Add(new User { UserId = Guid.NewGuid(), UserName = "Lamond Lu"});
        dbContext.SaveChanges();
      }
    }
  }

重新运行程序,你会得到一下结果。

这里你可能会问为什么不显示@p0, @p1参数的值。这里是原因是为了保护敏感数据,EF Core默认关闭的敏感数据的显示配置,如果你想要查看敏感数据,你需要通过DbContextOptionsBuilder对象的EnableSensitiveDataLogging方法修改敏感数据日志配置。

  protected override void OnConfiguring (DbContextOptionsBuilder optionsBuilder) {
    var loggerFactory = new LoggerFactory ();
    loggerFactory.AddProvider (new EFLoggerProvider ());
    optionsBuilder.EnableSensitiveDataLogging (true);
    optionsBuilder.UseLoggerFactory (loggerFactory);

    base.OnConfiguring (optionsBuilder);
  }

重新启动项目之后,你就能看到@p0, @p1参数的值了。

以上就是.net core实用技巧——将EF Core生成的SQL语句显示在控制台中的详细内容,更多关于.net core实用技巧的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
  • .net EF Core专题:EF Core 读取数据时发生了什么?
  • .net core EF Core调用存储过程的方式
  • 详解.Net Core 权限验证与授权(AuthorizeFilter、ActionFilterAttribute)
  • .NET Core类库System.Reflection.DispatchProxy实现简易Aop的方法
  • 在.NET Core类库中使用EF Core迁移数据库到SQL Server的方法
  • CodeFirst从零开始搭建Asp.Net Core2.0网站
  • .Net Core中使用ref和Span<T>提高程序性能的实现代码

相关文章

  • .net core实用技巧——将EF Core生成的SQL语句显示在控制台中

    .net core实用技巧——将EF Core生成的SQL语句显示在控制台中

    前言 笔者最近在开发和维护一个.NET Core项目,其中使用几个非常有意思的.NET Core相关的扩展,在此总结整理一下。 EF Core性能调优 如果你的项目中使用了EF Core,
    2020-09-24
  • asp .net core静态文件资源的深入讲解

    asp .net core静态文件资源的深入讲解

    前言 对静态资源的简单的一个概况,在《重新整理.net core 计1400篇》系列后面会深入。 正文 我们在加入中间件是这样写的: app.UseStaticFiles(); 默认是给wwwro
    2020-09-24
  • c# rabbitmq 简单收发消息的示例代码

    c# rabbitmq 简单收发消息的示例代码

    发布消息:(生产者) /// <summary> /// 发送消息 /// </summary> /// <param name="queue">队列名</param> /// <param name="message">消息
    2020-09-24
  • ASP.net百度主动推送功能实现代码

    ASP.net百度主动推送功能实现代码

    官方提供了curl、post、php、ruby的实现示例,并没有C#的官方示例。既然提供了post的方式,那么就可以用C#实现,下面是实现代码: ASP.net百度主动推送代码范例 p
    2020-09-24
  • ASP .NET Core API发布与部署以及遇到的坑和解决方法

    ASP .NET Core API发布与部署以及遇到的坑和解决方法

    最近在写.Net Core的API,由于之前没接触过Core,所以自己的想法很简单,感觉和.Net都是差不多的东西,发布部署还是按.Net的那一套来,可谓是困难重重,走了
    2020-09-24
  • 深入浅析ASP在线压缩access数据库的方法

    深入浅析ASP在线压缩access数据库的方法

    ASP在线压缩ACCESS数据库原理很简单:利用JRO.JetEngine的压缩功能建立一个新的数据库文件,然后把原来的删掉、替换!既然这样,压缩程序只需几行就ok了! 把下面的
    2020-09-24
  • 如何利用PHP实现上传图片功能详解

    如何利用PHP实现上传图片功能详解

    HTML文件 一、 设置编码UTF-8 对于中文网页需要使用<meta charset="utf-8">声明编码,否则会出现乱码。 二 、form表单 <form>标签用于为用户输入创建 HTML 表单,表
    2020-09-24
  • Openlayers实现点闪烁扩散效果

    Openlayers实现点闪烁扩散效果

    本文实例为大家分享了Openlayers实现点闪烁扩散效果的具体代码,供大家参考,具体内容如下 点闪烁样式: DOM的样式实现 /**橙色点扩散闪烁样式*/ .point_animati
    2020-09-24
  • vue使用openlayers实现移动点动画

    vue使用openlayers实现移动点动画

    本文实例为大家分享了vue使用openlayers实现移动点动画的具体代码,供大家参考,具体内容如下 做项目时,本来打算仿照官网的Example中动画制作,引入vue中后,发现它
    2020-09-24
  • SpringBoot后端接口的实现(看这一篇就够了)

    SpringBoot后端接口的实现(看这一篇就够了)

    摘要:本文演示如何构建起一个优秀的后端接口体系,体系构建好了自然就有了规范,同时再构建新的后端接口也会十分轻松。 一个后端接口大致分为四个部分组成:接口地
    2020-09-24

最新评论