zoukankan      html  css  js  c++  java
  • .NET Core实用技巧(一)如何将EF Core生成的SQL语句显示在控制台中

    目录

    • .NET Core实用技巧(一)如何将EF Core生成的SQL语句显示在控制台中

    前言

    笔者最近在开发和维护一个.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个属性UserIdUserName

        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参数的值了。

  • 相关阅读:
    NVIDIA驱动瘫痪再重装的问题
    ubuntu 14.04下NVIDIA驱动及cuda toolkit安装
    ubuntu下sogou输入法的输入框只显示英文不显示中文的解决方法
    ubuntu14.04下安装opencv3.2
    ubuntu14.04 卸载 boost
    编译错误: /usr/lib may be hidden by files in /home/username/anaconda/lib
    爬虫抓取网页内容
    学生手册成绩分析以学院为单位进行划分
    VisualSVN 设置SVN客户端必须填写日志才能提交
    Linux系统上java应用(例如spring boot)启动慢的原因之一
  • 原文地址:https://www.cnblogs.com/lwqlun/p/13551149.html
Copyright © 2011-2022 走看看