这篇文章主要介绍了如何将EF Core生成的SQL语句显示在控制台中,帮助大家更好的理解和学习.net 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; }
}
如何生成的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参数配置。
如何去除无关日志?
在前面的步骤中,我们成功的输出了查询语句,但是有一个问题是我们只想查看输出的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;
&