.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语句显示在控制台中的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Jenkins来发布和代理.NetC
- 下一篇: await,async 我要把它翻个底朝