当前位置: 移动技术网 > IT编程>开发语言>.net > .net core实用技巧——将EF Core生成的SQL语句显示在控制台中

.net core实用技巧——将EF Core生成的SQL语句显示在控制台中

2020年08月28日  | 移动技术网IT编程  | 我要评论
前言笔者最近在开发和维护一个.net core项目,其中使用几个非常有意思的.net core相关的扩展,在此总结整理一下。ef core性能调优如果你的项目中使用了ef 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; }
  }
  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 == dbloggercategory.database.command.name &&
      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语句显示在控制台中的详细内容,更多关于.net core实用技巧的资料请关注移动技术网其它相关文章!

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网