博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.NET Core实用技巧(一)如何将EF Core生成的SQL语句显示在控制台中
阅读量:4034 次
发布时间:2019-05-24

本文共 4971 字,大约阅读时间需要 16 分钟。

前言

笔者最近在开发和维护一个.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
(); 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
options) : base (options) { } public DbSet
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
(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func
formatter) { var logContent = formatter (state, exception); Console.WriteLine (); Console.WriteLine (logContent); } } public IDisposable BeginScope
(TState state) => null; }

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

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

public class MyDbContext : DbContext {        public MyDbContext (DbContextOptions
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
Users { get; set; } }

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

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

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

如何去除无关日志?

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

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

public void Log
(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func
formatter) { if (categoryName == "Microsoft.EntityFrameworkCore.Database.Command" && 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
(); 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 参数的值了。

转载地址:http://sezdi.baihongyu.com/

你可能感兴趣的文章
linux内核学习(4)建立正式内核的页式内存映射, 以x86 32位模式为例
查看>>
慢慢欣赏linux 查看硬盘情况
查看>>
慢慢欣赏linux vsftpd的使用
查看>>
慢慢欣赏linux 思考中的问题
查看>>
慢慢欣赏linux switch_to学习
查看>>
慢慢欣赏linux CPU占用率和负载
查看>>
设计模式学习
查看>>
慢慢欣赏linux seq_file
查看>>
慢慢欣赏linux 设备树device tree
查看>>
慢慢欣赏linux HZ与时钟中断频率的关联
查看>>
慢慢欣赏linux 文件黑洞和文件空洞
查看>>
慢慢欣赏linux 截断文件
查看>>
慢慢欣赏linux 数据类型
查看>>
中断学习之timer_interrupt powerpc实现
查看>>
慢慢欣赏linux 死锁检测
查看>>
慢慢欣赏linux exec加载执行程序
查看>>
慢慢欣赏linux 页框lru的作用
查看>>
慢慢欣赏linux glibc相关
查看>>
慢慢欣赏linux PCI-PCIE初始化总结
查看>>
慢慢欣赏linux PCI-PCIE定制化
查看>>