在实体框架核心中获取DbContext.SaveChanges的生成的SQL

时间:2019-05-26 05:19:26

标签: entity-framework-core

在Entity Framework Core中,是否可以看到在SaveChanges()上调用DbContext方法时将应用的SQL?

4 个答案:

答案 0 :(得分:1)

您可以使用控制台记录器“ EF Core记录自动与.NET Core的记录机制集成” 您可以在这里阅读: https://www.entityframeworktutorial.net/efcore/logging-in-entityframework-core.aspx

答案 1 :(得分:1)

您可以使用DbContextOptionsBuilder.UseLoggerFactory(loggerFactory)方法记录所有sql输出。通过使用如下所示的构造函数Injection

public class DemoContext : ObjContext
{
    private readonly ILoggerFactory _loggerFactory;

    public DemoContext() { }

    public DemoContext(ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);

        optionsBuilder.UseLoggerFactory(_loggerFactory);
    }
}

using (var context = new DemoContext(_loggerFactory))
{
    var Employees = context.Employee.ToList();
}

我建议查看查看所生成SQL的其他几种方法是使用反射创建一个ObjectQuery object,然后调用ToTraceString()方法来实际存储查询结果。

using (var context = new EntityContext())
{
    var query = context.Customers.Where(c => c.Id == 1); 
    var sql = ((System.Data.Objects.ObjectQuery)query).ToTraceString();  
}

使用SQL日志记录

对于任何采用字符串的方法,都可以将DbContext.Database.Log property设置为委托。

将SQL登录到控制台。

using (var context = new EntityContext())
{
    context.Database.Log = Console.Write; 
}

将SQL登录到Visual Studio“输出”面板。

using (var context = new EntityContext())
{
    context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s); 

}

答案 2 :(得分:1)

这里the docs是在Core 3中创建LoggerFactory的简要说明。

var loggerFactory = LoggerFactory.Create(builder =>
{
    builder
        .AddFilter("Microsoft", LogLevel.Warning)
        .AddFilter("System", LogLevel.Warning)
        .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
        .AddConsole()
        .AddEventLog();
});

您可能需要添加对Microsoft.Extensions.Logging.Console的引用。

使用DbContextOptionsBuilder启用上下文记录。

optionsBuilder.UseLoggerFactory(loggerFactory)

我将重复来自here的警告:

应用程序不要为每个上下文实例创建一个新的ILoggerFactory实例,这一点非常重要。这样做会导致内存泄漏和性能下降。

因此,他们建议使用单例/全局实例:

public static readonly ILoggerFactory MyLoggerFactory =
    LoggerFactory.Create(builder => { builder.AddConsole(); });

答案 3 :(得分:0)

在 ASP.NET MVC Web 应用程序中记录 EF Core 的 SQL 有点棘手。与实体框架不同,EF Core 缺少易于使用的 DBContext.Database.Log 属性。正如@DharmaTurtle 提到的,您可以使用 LoggerFactory.Create,这可以工作,但它确实创建了一个 separate ILoggerFactory,而不是应用程序的其余部分用于日志记录的(一个显然没有使用 appsettings.json 的选项。)

如果您想对 ASP.NET MVC Web 应用程序的其余部分使用的 DBContext 使用相同的日志工厂,则需要采用以下方法:

  1. 创建 DbContext 的派生类(或者,如果已完成,请适当修改现有类)。注意:这个例子只会在调试版本中记录 SQL,而不是发布版本。

    public class DbContextWithLogging : Microsoft.EntityFrameworkCore.DbContext
    {
        ILoggerFactory _loggerFactory;
        IConfiguration _configuration; // Provides access to appsettings.json
    
        public DbContextWithLogging(ILoggerFactory loggerFactory, IConfiguration configuration)
            => (_loggerFactory, _configuration) = (loggerFactory, configuration);
    
        protected override void OnConfiguring(DbContextOptionsBuilder builder)
        {
            #if DEBUG
            builder.UseLoggerFactory(_loggerFactory);
            // This line causes parameter values to be logged:
            builder.EnableSensitiveDataLogging();
            #endif
        }
    }
    

    注意:此方法与在 AddDbContext 中调用 Startup.ConfigureServices 不兼容,因此如果已经调用了 AddDbContext,请禁用/删除它。就我而言,DbContext 的现有派生类有一个接受 (DbContextOptions<BarreleyeDbContext> options) 的构造函数,我将其删除。

  2. 在您的 Startup.ConfigureServices 方法中,配置日志记录(例如打印到控制台)并启用自定义 DbContext:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddLogging((ILoggingBuilder builder) => {
            builder.AddConsole();
        });
    
        // In ASP.NET Core apps, a Scope is created around each server request.
        // So AddScoped<X, Y>() will recreate class Y for each HTTP request.
        services.AddScoped<DbContext, DbContextWithLogging>();
    
        ... // leave the rest as before
    }
    
  3. 任何使用 DbContext(例如控制器或 Repository 模式中的“repositories”)都应该通过构造函数注入自动获取它。

  4. EF Core 在打印 SQL 时使用 LogLevel.Information,因此您需要启用 Information 级别。如果您查看 appsettings.json 文件,您会希望看到如下内容:

      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Information",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
    

    特别是,EF Core 日志过滤可以通过像

    这样的键来控制
     "Microsoft.EntityFrameworkCore": "Information",
    

    但如果缺少此键,则使用 "Microsoft" 键代替。

    这可能不起作用! 查找名为 appsettings.Development.json 的第二个文件 - 请注意,Visual Studio 可能会将这个文件隐藏在 appsettings.json 的“内部”。如果 appsettings.Development.json 存在,其内容将覆盖 appsettings.json(以单个键的粒度)。

一旦它开始工作,您将看到类似这样的日志信息(是的,SELECT 语句以及 INSERT、UPDATE 和 DELETE 都被记录了下来):

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (0ms) [Parameters=[@__p_0='297'], CommandType='Text', CommandTimeout='30']
      SELECT e.id, e.config, e.end_date, e.entity_name, e.entity_type, e.location, e.start_date
      FROM entities AS e
      WHERE e.id = @__p_0
      LIMIT 1