.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个属性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 == "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<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语句显示在控制台中的更多相关文章
- LinqToSql EntityFramework(ef)查看生成的sql语句
var dc=new DBDataContext(); TextWriter tw = new StringWriter(); dc.Log = tw; var list = dc.News.Skip ...
- MySQL官方.NET Core驱动已出,支持EF Core
千呼万唤始出来MySQL官方.NET Core驱动已出,支持EF Core. 昨天MySQL官方已经发布了.NET Core 驱动,目前还是预览版,不过功能已经可用. NuGet 地址:https:/ ...
- NET Core驱动已出,支持EF Core
NET Core驱动已出,支持EF Core 千呼万唤始出来MySQL官方.NET Core驱动已出,支持EF Core. 昨天MySQL官方已经发布了.NET Core 驱动,目前还是预览版,不过功 ...
- [翻译 EF Core in Action 1.9] 掀开EF Core的引擎盖看看EF Core内部是如何工作的
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- .net core 利用日志查看ef生成的SQL语句
EF Core 没有直接提供像 EF6 那样方便的在日志中记录最终生成的 SQL 的功能,可以通过官方提供的日志记录(Microsoft.Extensions.Logging)实现. 一. 使用 Mi ...
- Cookies 初识 Dotnetspider EF 6.x、EF Core实现dynamic动态查询和EF Core注入多个上下文实例池你知道有什么问题? EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)
Cookies 1.创建HttpCookies Cookie=new HttpCookies("CookieName");2.添加内容Cookie.Values.Add(&qu ...
- DbCommandInterceptor抓取EF执行时的SQL语句
EF6.1也出来不少日子了,6.1相比6.0有个很大的特点就是新增了System.Data.Entity.Infrastructure.Interception 命名空间,此命名空间下的对象可以允许我 ...
- EF 6.x、EF Core实现dynamic动态查询和EF Core实现多个上下文实例池你了解多少?
前言 很长一段时间没有写博客了,今天补上一篇吧,偶尔发现不太愿意写博客了,太耗费时间,不过还是在坚持当中,毕竟或许写出来的东西能帮到一些童鞋吧,接下来我们直奔主题.无论是在在EF 6.x还是EF Co ...
- [翻译 EF Core in Action 2.3] 理解EF Core数据库查询
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
随机推荐
- python map() filter() reduce()函数的用法以及实例
map() 看一下我的终端咋说: map()的函数用法: map(function, iterable, ...) 看一下具体例子: 注意的是一定要强制转化一下才能输出 也可以写匿名函数: (mark ...
- abs,all,any函数的使用
''' abs函数:如果参数为实数,则返回绝对值 如果参数为复数,则返回复数的模 ''' a = 6 b = -6 c = 0 # print("a = {0} , b = {1} , c ...
- 服务没有报告任何错误。 请键入 NET HELPMSG 3534 以获得更多的帮助。
解决: 删除data文件夹 然后按顺序执行: sc delete mysql mysqld --initialize-insecure mysqld -install mysql net start ...
- MR程序的几种提交运行模式
本地模式运行 1-在windows的eclipse里面直接运行main方法 将会将job提交给本地执行器localjobrunner 输入输出数据可以放在本地路径下 输入输出数据放在HDFS中:(hd ...
- MySQL的utf8问题
作者:brightwang 原文:https://www.jianshu.com/p/ab9aa8d4df7d 有时候用MySQL存储一些特殊字符时,有出现乱码问题. 我用的是UTF-8编码的客户端, ...
- 安装Hive 使用beeline 链接 出现 User: AAA is not allowed to impersonate BBB
AAA 指的是 hdfs 文件系统的用户 BBB 是hive 设置的 hiveserver2 配置文件中的登陆用户名 在hadoop 配置如下 <property> <name> ...
- Taurus.MVC 2.3.4 :WebAPI 文档集成测试功能升级:WebAPI批量自动化测试功能。
前言: 最近升级了一下Taurus.MVC,现在最新版本是:Taurus.MVC 2.3.4,源码版本和nuget同步. 下面分三个步骤介绍下新版本的WebAPI批量自动化测试功能. 1.启用WebA ...
- 当Django模型迁移时,报No migrations to apply 问题时
前言:当更改model时在次迁移是不是经常报此类错误,解决以下两点便可以更新成功 1. 删除修改模型对应的app应用下的migrations中的生成文件 2. 进入数据库,找到django_migra ...
- RabbitMq之消息确认
最近阅读了rabbitmq的官方文档,然后结合之前面试时被问到关于消息队列的问题来探索一下关于消息队列的消息确认机制. 其实消息确认就是消费者确认消息被消费了, 生产者确认消息已经发送到了消息队列中了 ...
- Python 告诉你疫情扩散有多可怕
今年(2020年)是注定要铭记史册的一年,从年初开始新冠疫情,席卷了全球,中国人民众志成城,为战胜疫情做出了巨大牺牲.最近北京疫情形式又变得严峻,面对疫情我们不能掉以轻心.今天我们模拟一下病毒的扩散过 ...