实体框架 DbContext 执行的日志查询

Posted

技术标签:

【中文标题】实体框架 DbContext 执行的日志查询【英文标题】:Log Queries executed by Entity Framework DbContext 【发布时间】:2014-07-11 08:53:21 【问题描述】:

我在 MVC 5 项目中使用 EF 6.0 和 LINQ。我想记录实体框架 DbContext 执行的所有 SQL 查询,以用于调试/性能测量。

在 Java/Hibernate 中,可以通过设置属性 hibernate.show_sql=true 来实现等效行为。实体框架中是否可能有类似的行为?

【问题讨论】:

How do I view the SQL generated by the entity framework? 的可能重复项 【参考方案1】:

Logging and Intercepting Database Operations MSDN 上的文章正是您想要的。

DbContext.Database.Log 属性可以设置为任何采用字符串的方法的委托。最常见的是,通过将其设置为该 TextWriter 的“Write”方法,它与任何 TextWriter 一起使用。当前上下文生成的所有 SQL 都将记录到该编写器。例如,以下代码会将 SQL 记录到控制台:

using (var context = new BlogContext())

    context.Database.Log = Console.Write;

    // Your code here...

【讨论】:

仅供参考:如果您使用context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);,那么它只会在调试模式下登录。在释放模式下,对 System.Diagnostics.Debug 的调用将被忽略。 或者你可以将这行代码包装到用[Conditional("Debug")]属性修饰的方法中 @Andrew,你能告诉我这个 Database.log 操作是在哪里调用的吗? 这似乎可行,但生成的 sql 查询是参数化的。在调试模式下,我将如何打印参数化值?【参考方案2】:

您可以使用此行将 SQL 查询仅记录到 Visual Studio“输出”窗口,而不是控制台窗口,同样仅在调试模式下。

public class YourContext : DbContext
   
    public YourContext()
    
        Database.Log = sql => Debug.Write(sql);
    

【讨论】:

【参考方案3】:

如果您有一个带有记录器的 .NET Core 设置,那么 EF 会将其查询记录到您想要的任何输出:调试输出窗口、控制台、文件等。

您只需要在 appsettings 中配置“信息”日志级别。例如,这会将 EF 记录到调试输出窗口:

"Logging": 
  "PathFormat": "Logs/log-Date.txt",
  "IncludeScopes": false,
  "Debug": 
    "LogLevel": 
      "Default": "Information",
      "System": "Information",
      "Microsoft": "Information"
    
  ,
  "Console": 
    "LogLevel": 
      "Default": "Information",
      "System": "Warning",
      "Microsoft": "Warning"
    
  ,
  "File": 
    "LogLevel": 
      "Default": "Information",
      "System": "Warning",
      "Microsoft": "Warning"
    
  ,
  "LogLevel": 
    "Default": "Information",
    "System": "Warning",
    "Microsoft": "Warning"
  

【讨论】:

【参考方案4】:

EF Core 日志记录自动与 .NET Core 的日志记录机制集成。示例如何使用它登录到控制台:

public class SchoolContext : DbContext

    //static LoggerFactory object
    public static readonly ILoggerFactory loggerFactory = new LoggerFactory(new[] 
              new ConsoleLoggerProvider((_, __) => true, true)
        );

    //or
    // public static readonly ILoggerFactory loggerFactory  = new LoggerFactory().AddConsole((_,___) => true);

    public SchoolContext():base()
    

    

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    
        optionsBuilder.UseLoggerFactory(loggerFactory)  //tie-up DbContext with LoggerFactory object
            .EnableSensitiveDataLogging()  
            .UseSqlServer(@"Server=.\SQLEXPRESS;Database=SchoolDB;Trusted_Connection=True;");
    

    public DbSet<Student> Students  get; set; 

如果您想登录到输出窗口,请改用:

public static readonly ILoggerFactory loggerFactory = new LoggerFactory(new[] 
      new DebugLoggerProvider()
);

https://www.entityframeworktutorial.net/efcore/logging-in-entityframework-core.aspx

【讨论】:

【参考方案5】:

如果有人使用 EF6.1+,有一个简单的方法。查看以下链接了解更多详情。

https://docs.microsoft.com/en-us/ef/ef6/fundamentals/configuring/config-file#interceptors-ef61-onwards

示例代码

<interceptors>
  <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework">
    <parameters>
      <parameter value="C:\Stuff\LogOutput.txt"/>
      <parameter value="true" type="System.Boolean"/>
    </parameters>
  </interceptor>
</interceptors>

【讨论】:

【参考方案6】:

实体框架核心 3

来自this article

创建工厂并设置过滤器。

var loggerFactory = LoggerFactory.Create(builder =>

    builder
    .AddConsole((options) =>  )
    .AddFilter((category, level) =>
        category == DbLoggerCategory.Database.Command.Name
        && level == LogLevel.Information);
);

在 OnConfiguring 方法中告诉 DbContext 使用工厂:

optionsBuilder.UseLoggerFactory(_loggerFactory);

【讨论】:

以上是关于实体框架 DbContext 执行的日志查询的主要内容,如果未能解决你的问题,请参考以下文章

实体框架 DbContext 过滤的计数查询使用变量非常慢

csharp 实体框架核心 - SQL查询控制台日志记录

创建实体框架上下文的实例在负载下减慢

将 POCO/实体添加到 DbContext 以进行自定义查询/过程,而无需先在实体框架代码中创建表

开发中遇到的问题---使用mybatis时 有一个sql查询不到结果 日志也显示查询为o 但是从日志中取出执行的sql到数据库客户端手动执行,可以查到数据

在Code第一实体框架中将DbContext转换为Datatable