6

Using Entity Framework in .Net Core 2.2, I'd like to log all SQL statements generated by EF to the Debug Output window in Visual Studio.

In .Net Framework I simply had to add this line to the DbContext constructor:

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

In EF I'm trying the following. It compiles, and the OnConfiguring method does get called, but no database calls are logged to my Debug Output window. What am I missing?

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());
    }
}

My appsettings.json contains this:

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

},

And my Startup.cs contains this line in the ConfigureServices method:

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

Startup.cs also contains this per one of the answer below, but it does not cause EF SQL to get printed to the output window:

    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");
    }
4
  • 1
    Have you tried with AddConsole() ? It's not the same but it will help to isolate the problem Commented May 22, 2019 at 15:21
  • @PanagiotisKanavos yes I did. No console window opens. The executable is a web api. When I run it a browser instance opens with the default GET path, but there is no console window. Commented May 22, 2019 at 15:22
  • 2
    Which Logging Framework do you intend to use? Do you want to have the exact SQL statements logged or only the structure? Commented May 22, 2019 at 15:23
  • @Hermann.Gruber I don't understand the question (new to .Net Core). I want to log the sql statements that EF generates. If there is something I need to add to choose a Logging Framework please let me know. Commented May 22, 2019 at 15:23

4 Answers 4

9

I could not use .AddDebug() in my EFCore 3 application. I added nuget package Microsoft.Extensions.Logging.Debug To my project and was able to use it. I now see the generated SQL commands in the Output Window (Show output from Debug).

Create a field in the context:

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

and add the field to your optionsBuilder:

 optionsBuilder.UseLoggerFactory(_loggerFactory);
Sign up to request clarification or add additional context in comments.

2 Comments

This should be the accepted answer. This is by far the simplest way to get EF logging info into the debug console in EF Core, with the minimum change to how you'd write it otherwise.
Agreed, this works, is simple and straight forward. My only concern is, do I need to surround this with #IF DEBUG statement? How would this behave in prod code?
2

you also need to add the ILogger Interface to the Startup.cs

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

        public ILogger<Startup> Logger { get; }

I use Serilog and it works with following options in the appsetting just fine

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

3 Comments

That does nothing. Is there a step I'm missing where I need to install a logger?
I guess yes. Maybe you want to try this step by step tutorial for setting up serilog with your aspnetcore app: carlos.mendible.com/2019/01/14/…
Thanks for mentioning Serilog, I wound up using that.
2

You can try this if it will help. Thanks

 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
            });

enter image description here

2 Comments

in .Net Core 2.2 the method loggerFactory.AddDebug() is obsolete.
When i tested this, it logged the query in the output window.I hope this will help. Just edit your program.cs
2

Thank you for the comments and answers. The issue here was between my ears. The code I originally posted in my question works; it logs raw SQL to the debug output window for Entity SQL queries.

In fact, a lot less is needed if the application uses asp.net core (which this one does, it is a web api application). By default Visual Studio 2017 inserts the following bit of code in Program.cs as part of the project template:

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

The call to CreateDefaultBuilder adds 3 types of logging--Console, Debug, EventSource--and also fetches the "Logging" section from appsettings.json. The "LoggerFactory" stuff in my original question is redundant and not needed.

The code I was testing and failing with, while it used the database context, was executing a stored procedure using System.Data.Common.DbCommand, which does not pass information to the logger hooked up to the DbContext. I need to log System.Data.Common.DbCommand sql statements manually (this is also needed in .Net Framework, but it has been so many years since I've touched this I'd forgotten).

When I created a DbSet in my DbContext and did a select against it using Entity SQL, eg:

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

this successfully logs the raw SQL to my debug output window, eg:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.