sql server (sqlexpress) 启动不了_如何将EF Core生成的SQL语句显示在控制台中

01197f7ce1e986868150008a10aa491f.png

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

513b687b7ee9f52e219db5e1284c2e00.png

目录#

  • .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();            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 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; }    }

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

2eaec0b9d5667a8939eda3b4c15c3ea1.png

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语句。重新启动项目之后,效果如下。

360e2053d0a8d5bafc5ec0a8c3fc8468.png

如何显示敏感数据?#

这里看似我们已经完成了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();            }        }    }    

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

28d21a9da5c799dae22ee2f3b0930a28.png

这里你可能会问为什么不显示@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参数的值了。

8aee548364ed1666d3e49e2051dbc063.png

最后,咱给小编:

1. 点赞+关注

2. 点头像关注后多多评论,转发给有需要的朋友。

谢谢!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值