【问题标题】:Log Entity Framework .Net Core 2.2 EF to debug output window记录 Entity Framework .Net Core 2.2 EF 以调试输出窗口
【发布时间】:2019-05-22 14:49:21
【问题描述】:

使用 .Net Core 2.2 中的实体框架,我想将 EF 生成的所有 SQL 语句记录到 Visual Studio 中的“调试输出”窗口。

在 .Net Framework 中,我只需将这一行添加到 DbContext 构造函数中:

Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

在 EF 中,我正在尝试以下操作。它编译,并且调用了 OnConfiguring 方法,但没有数据库调用记录到我的调试输出窗口。我错过了什么?

public class MyContext : DbContext
{
    private ILoggerFactory GetLoggerFactory()
    {
        IServiceCollection serviceCollection = new ServiceCollection();
        serviceCollection.AddLogging(builder => builder
            .AddDebug()
            .AddFilter(DbLoggerCategory.Database.Command.Name, LogLevel.Debug));
        return serviceCollection.BuildServiceProvider()
                .GetService<ILoggerFactory>();
    }

    public MyContext(DbContextOptions<MembershipContext> options) : base(options)
    {
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseLoggerFactory(GetLoggerFactory());
    }
}

我的 appsettings.json 包含以下内容:

  "Logging": {
"LogLevel": {
  "Default": "Debug"
}

},

我的 Startup.cs 在 ConfigureServices 方法中包含这一行:

services.AddDbContext<MyContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("MyConnectionSTring")));

Startup.cs 也包含以下答案之一,但它不会导致 EF SQL 打印到输出窗口:

    public ILogger<Startup> Logger { get; set; }

    public Startup(IConfiguration configuration, ILogger<Startup> logger)
    {
        Configuration = configuration;
        Logger = logger;

        //the following line gets printed to my debug output window:
        logger.LogDebug("this is a debug message");
    }

【问题讨论】:

  • 你试过AddConsole() 吗?它不一样,但它有助于隔离问题
  • @PanagiotisKanavos 是的,我做到了。没有控制台窗口打开。可执行文件是一个 web api。当我运行它时,会使用默认的 GET 路径打开一个浏览器实例,但没有控制台窗口。
  • 您打算使用哪个日志框架?您想记录确切的 SQL 语句还是只记录结构?
  • @Hermann.Gruber 我不明白这个问题(.Net Core 的新手)。我想记录 EF 生成的 sql 语句。如果我需要添加一些内容来选择日志框架,请告诉我。

标签: c# entity-framework .net-core


【解决方案1】:

我无法在我的 EFCore 3 应用程序中使用 .AddDebug()。我将 nuget 包 Microsoft.Extensions.Logging.Debug 添加到我的项目中并且能够使用它。我现在可以在输出窗口中看到生成的 SQL 命令(显示来自 Debug 的输出)。

在上下文中创建一个字段:

public static readonly ILoggerFactory _loggerFactory
                    = LoggerFactory.Create(builder => builder.AddDebug().AddFilter((category, level) => level == LogLevel.Information && !category.EndsWith("Connection")));

并将该字段添加到您的 optionsBuilder:

 optionsBuilder.UseLoggerFactory(_loggerFactory);

【讨论】:

  • 这应该是公认的答案。这是迄今为止将 EF 日志信息获取到 EF Core 中的调试控制台的最简单方法,并且对您编写它的方式所做的更改最少。
【解决方案2】:

您还需要将 ILogger 接口添加到 Startup.cs

     public Startup(IConfiguration configuration, ILogger<Startup> logger, IHostingEnvironment hostingEnvironment)
        {   
            Configuration = configuration;
            Logger = logger;
            HostingEnvironment = hostingEnvironment;
        }

        public ILogger<Startup> Logger { get; }

我使用 Serilog,它适用于 appsetting 中的以下选项

    "Serilog": {
    "MinimumLevel": {
      "Default": "Debug"
    }

【讨论】:

  • 这无济于事。有没有我需要安装记录器的步骤?
  • 我猜是的。也许您想尝试使用您的 aspnetcore 应用程序设置 serilog 的分步教程:carlos.mendible.com/2019/01/14/…
  • 感谢您提及 Serilog,我最终使用了它。
【解决方案3】:

感谢您的 cmets 和答案。这里的问题在我的耳朵之间。我最初在我的问题中发布的代码有效;它将原始 SQL 记录到实体 SQL 查询的调试输出窗口。

事实上,如果应用程序使用 asp.net 核心(这个是使用的,它是一个 web api 应用程序),则需要的东西要少得多。默认情况下,Visual Studio 2017 在 Program.cs 中插入以下代码作为项目模板的一部分:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)  
            .UseStartup<Startup>();

对 CreateDefaultBuilder 的调用添加了 3 种类型的日志记录——控制台、调试、事件源——并且还从 appsettings.json 中获取“日志记录”部分。我原来的问题中的“LoggerFactory”是多余的,不需要。

我正在测试和失败的代码在使用数据库上下文时正在使用 System.Data.Common.DbCommand 执行存储过程,该过程不会将信息传递给连接到 DbContext 的记录器。我需要手动记录 System.Data.Common.DbCommand sql 语句(这在 .Net Framework 中也需要,但我已经忘记了这么多年了)。

当我在我的 DbContext 中创建一个 DbSet 并使用 Entity SQL 对其进行选择时,例如:

var log = _myContext.Log.FirstOrDefault(o => o.Id > 0);

这成功地将原始 SQL 记录到我的调试输出窗口,例如:

Microsoft.EntityFrameworkCore.Database.Command:Information: 
Executed DbCommand (6ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [o].[Id], [o].[Browser], [o].[Client], [o].[Date], [o].[Exception], 
[o].[Host], [o].[Level], [o].[Logger], [o].[Message], [o].[StackTrace], [o].[Thread], 
[o].[User]
FROM [Log] AS [o]
WHERE [o].[Id] > 0

【讨论】:

    【解决方案4】:

    如果有帮助,你可以试试这个。谢谢

     public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .ConfigureLogging(logger => {
                    logger.AddDebug()
                          .AddFilter(DbLoggerCategory.Database.Command.Name, LogLevel.Information);
                    //logger.AddConsole(); //UnComment out this line if you did not use CreateDefaultBuilder
                });
    

    【讨论】:

    • 在 .Net Core 2.2 中,方法 loggerFactory.AddDebug() 已过时。
    • 当我测试这个时,它在输出窗口中记录了查询。我希望这会有所帮助。只需编辑您的 program.cs
    猜你喜欢
    • 2019-05-10
    • 2019-11-03
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    相关资源
    最近更新 更多