124

At 3:15 from the end of this ".NET Core 2.0 Released!" video, Diego Vega shows a demo of new features in Entity Framework Core 2.0. As part of that, a dump of the underlying SQL is shown in the console app.

enter image description here

I have seen many answers on Stack Overflow suggesting that people use an SQL profiler to view the underlying queries. But now I'm curious: how can you do what Diego Vega did, and get the query to show right there in the application?

Update for .NET 6+: EF logging is enabled by default in development. See this GitHub issue

Update: Diego added "Microsoft.EntityFrameworkCore.Database.Command": "Information" to appsettings.Development.json. See How do you show underlying SQL query in EF Core? for more details.

RickAndMSFT
  • 20,912
  • 8
  • 60
  • 78
Gigi
  • 28,163
  • 29
  • 106
  • 188
  • 2
    Apparently he's using [EF Core Logging](https://learn.microsoft.com/en-us/ef/core/miscellaneous/logging), most likely with filter `if (eventId.Id == Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.CommandExecuted.Id)` – Ivan Stoev Aug 26 '17 at 09:37
  • 4
    Just add "Microsoft.EntityFrameworkCore.Database.Command": "Information" to appsettings.Development.json – RickAndMSFT Mar 16 '21 at 20:03

12 Answers12

158

Update for .NET 6 and later: EF logging is enabled by default in development.

Just add "Microsoft.EntityFrameworkCore.Database.Command": "Information" to appsettings.Development.json so it's only logged in dev mode. You typically don't want to log every query in a production app.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDB-2;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
     ,"Microsoft.EntityFrameworkCore.Database.Command": "Information"
    }
  },
  "AllowedHosts": "*"
}

The SQL output shows in the command window or VS output window.

enter image description here

See SQL Logging of Entity Framework Core in the official docs. In older versions, it was a bug that it didn't log by default, see this GitHub issue.

RickAndMSFT
  • 20,912
  • 8
  • 60
  • 78
  • 2
    Best answer for me. Thanks a lot – Uwe Keim May 02 '21 at 17:10
  • 2
    Finally! been searching for the answer to this problem for so long. By far the easiest solution. – AGB May 17 '21 at 10:01
  • Any idea on how to do it with Serilog? – sinsedrix May 17 '21 at 15:01
  • 2
    Is this EF Core 5 only? – xr280xr Oct 06 '21 at 16:45
  • 1
    Excellent answer. – zeeqzaq Nov 23 '21 at 01:00
  • 2
    A word of caution here, in VS 2022 the increased amount of logging will cause massive performance degradation while debugging. I'd recommend enabling it only when necessary, unless you're debugging loading spinners. – joakimriedel Mar 21 '22 at 10:10
  • @joakimriedel The logging is the same in any VS version. Do you mean that you recommend disabling it in VS22 since it's enabled by default? xr280xr instructions work for EF Core 2.x and higher. In .NET 6, EF logging is enabled by default. – RickAndMSFT Mar 21 '22 at 23:27
  • @RickAndMSFT yes I noticed that my app was running very slow during debugging (each API request from client was ~10 times slower) after upgrading to vs2022 and net6, disabling the logging did wonders. Now I only toggle it when I actually want to debug SQL queries. Only downside is that I would always like the verbose logging in CLI commands, but I often forget to change the appsettings before running them.. – joakimriedel Mar 23 '22 at 07:41
  • @RickAndMSFT note that performance with/without logging is about the same when running without debugging (~27/22 ms for this particular API call), in debugger without logging ~110 ms, debugger with query logging enabled ~870 ms. Might be a VS2022 bug or some heavy synchronization going on internally while debugging, I'm surprised to see such a huge difference – joakimriedel Mar 23 '22 at 16:41
  • 1
    Any idea where this is supposed to show in VSCode? – crthompson May 10 '22 at 15:10
  • 1
    @crthompson If running from the CLI (e.g. with `dotnet watch`), you may want to direct logging to the console. See [Simple Logging Configuration](https://learn.microsoft.com/en-us/ef/core/logging-events-diagnostics/simple-logging#configuration): `optionsBuilder.LogTo(Console.WriteLine)`. – Edward Brey May 27 '22 at 18:50
  • 1
    This solution does not work when I create the DbContext instance manually. Any solution? – MrDave1999 Aug 10 '22 at 15:29
  • Also noticed that in the "Show output from:" dropdown in the output window, will only show your executing project if your launchSettings.json is setup correctly. – Erick Boshoff Aug 25 '22 at 10:33
  • Does it show query for specific database or it always looks like SQLServer query? – cikatomo Oct 19 '22 at 01:54
  • Thanks for this. But I can't for the life of me figure out why this isn't turned on for Debug builds by default. – Jonathan Wood Dec 09 '22 at 17:52
  • >But I can't for the life of me figure out why this isn't turned on for Debug builds by default. – Jonathan Wood It is, have you read my answer? – RickAndMSFT Dec 10 '22 at 18:57
  • @RickAndMSFT Do you have a missing comma in the proposed code. I've tried fixing it, but the system doesn't allow such a minimal edit. FYI. – Sergio Apr 20 '23 at 06:38
  • @Sergio, it's there at the start of the line, that way you only need to add one line, not edit the preceding line then add a new line. – RickAndMSFT Apr 26 '23 at 05:40
  • OMG! @RickAndMSFT you're right! I'm sorry. – Sergio Apr 27 '23 at 06:17
103

Hi you can do something like following to display Entity Framework Core generated sql code in output window. In your DbContext class:

public static readonly Microsoft.Extensions.Logging.LoggerFactory _myLoggerFactory = 
    new LoggerFactory(new[] { 
        new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() 
    });

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

The debug logger writes messages in the debug output window only when a debugger is attached.

You will have to do following:

  • using Microsoft.Extensions.Logging;
  • Install nuget package: Microsoft.Extensions.Logging.Debug
ˈvɔlə
  • 9,204
  • 10
  • 63
  • 89
Mohammad
  • 1,498
  • 2
  • 12
  • 15
  • 3
    What if you're using Database First (`Scaffold-DbContext`) and your `DbContext` is subject to being regenerated which will overwrite any changes you make to `OnConfiguring` directly? – xr280xr Jul 13 '20 at 23:10
  • 1
    Just that easy. All other solutions out there are unnecessarily complicated.Thanks – PepeDeLew Mar 09 '21 at 09:32
  • 1
    Easier way, see my answer below: Just add "Microsoft.EntityFrameworkCore.Database.Command": "Information" to appsettings.Development.json so it's only logged in dev mode. – RickAndMSFT Apr 11 '21 at 23:36
  • Any idea on how to do it with Serilog? – sinsedrix May 17 '21 at 14:59
  • 1
    Thanks, works perfectly in asp net core 2.2 – Árthur Feb 11 '22 at 14:21
42

I use EF Core 3.x, this works for me:

services.AddDbContext<LibraryContext>(options => options
    .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()))
    .UseSqlServer(Configuration.GetConnectionString("LibraryDemoSql")));

Credit: https://stackoverflow.com/a/59663606/2185783

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
maximus
  • 1,290
  • 1
  • 14
  • 18
  • 2
    Where can you see the SQL query then ? I don't see it in output window. – Muflix Aug 22 '20 at 11:57
  • 2
    Hi @Muflix, this depends on where you run it. My app is a Web API app, I run it inside Rider's IIS Express configuration, the SQL logs show up in "Run" window. – maximus Aug 24 '20 at 03:28
  • @maximus, thanks for that confirmation! It made me realize I needed to change my Project->Properties->Debug->Launch setting to Project, instead of IIS Express. Now I have that "console" window open to see the queries. – computercarguy Mar 03 '21 at 23:31
  • Easier way, see my answer below: Just add "Microsoft.EntityFrameworkCore.Database.Command": "Information" to appsettings.Development.json so it's only logged in dev mode. – RickAndMSFT Apr 11 '21 at 23:36
  • 2
    This may introduce a memory leak. See the concern [here](https://stackoverflow.com/a/68183414/9746445). – Tulshi Das Apr 27 '22 at 05:40
38

EF Core >= 5

Simple logging

Entity Framework Core (EF Core) simple logging can be used to easily obtain logs while developing and debugging applications. This form of logging requires minimal configuration and no additional NuGet packages.

LogTo Console

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(Console.WriteLine);

LogTo debug window

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(message => Debug.WriteLine(message));

LogTo file

private readonly StreamWriter _logStream = new StreamWriter("mylog.txt", append: true);

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(_logStream.WriteLine);

public override void Dispose()
{
    base.Dispose();
    _logStream.Dispose();
}

public override async ValueTask DisposeAsync()
{
    await base.DisposeAsync();
    await _logStream.DisposeAsync();
}
dani herrera
  • 48,760
  • 8
  • 117
  • 177
21

https://learn.microsoft.com/en-us/ef/core/miscellaneous/logging

In the OnConfiguring method of DbContext you can set your logger, log in console is a predefined type, just use this NuGet. Note that using Factory pattern is a best practice for the logger instances.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLoggerFactory(MyLoggerFactory) // Warning: Do not create a new ILoggerFactory instance each time
        .UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EFLogging;Trusted_Connection=True;ConnectRetryCount=0");
Florian Fankhauser
  • 3,615
  • 2
  • 26
  • 30
  • 1
    Easier way, see my answer below: Just add "Microsoft.EntityFrameworkCore.Database.Command": "Information" to appsettings.Development.json so it's only logged in dev mode. – RickAndMSFT Apr 11 '21 at 23:36
11

I'm sure the accepted answer works, but I wanted to know how to do this using DI so...

private readonly ILoggerFactory loggerFactory;  

public MyDataContext(DbContextOptions<MyDataContext> options, ILoggerFactory loggerFactory)
        : base(options)
{
    this.loggerFactory = loggerFactory;
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)  
{
    // Allow null if you are using an IDesignTimeDbContextFactory
    if (loggerFactory != null)
    { 
        if (Debugger.IsAttached)
        {
            // Probably shouldn't log sql statements in production
            optionsBuilder.UseLoggerFactory(this.loggerFactory); 
        }
    }
} 
rstackhouse
  • 2,238
  • 24
  • 28
11

Logging to the output window in visual studio in .Net Core 3

Use AddDebug to write to the output debug window.

services.AddDbContext<LibraryContext>(options => options
            .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddDebug()))
            .UseSqlServer(Configuration.GetConnectionString("key")));
N-ate
  • 6,051
  • 2
  • 40
  • 48
  • The output window is "Debug". The console is the console window when running as a console application. – N-ate Sep 01 '20 at 17:38
11

If you looking for just the Underlying Sql, then dani herrera answer is great.

But from EF Core 5(I am not sure of earlier versions), there is a feature called Debug View which I am sure, you will love it. This is not exactly what the question is asking for, but this debug view has lots useful info that you cannot ignore.

Here are a few ways to get to that.

  1. Place a Break Point at context and look for Debug View as follows.

ef core context model debug view

I have shown short view, now you try long view. Here you find a good info about the objects the context is holding.

  1. If you have a IQueryable then try the following. This should be useful as well. Note here, the query is not yet sent to the database. So here you will get the query EF Core is about to send to the database.

ef core IQueryable Debug View

Also note that you can call ToQueryString() on the IQueryable object to get the same query!

queryable.ToQueryString()
  1. Last but not the least, try debug view on the Change Tracker object on the context.

Debug View On Change Tracker on Ef Core Context

The figure shows the state just before the save changes is called. Observer what happens after the save changes method is called(press F10, then observer again).

VivekDev
  • 20,868
  • 27
  • 132
  • 202
8

For people using EF Core 5, your query will have a Query property and also a ToQueryString() method that can be called to retrieve the query string. Note that these property/method only apply to a query, not the result - often there is no interim query variable as they're run immediately, so it is easiest to split a query that is formed and run into two steps to debug it:

//before
return db.Person.Where(p => p.Name == "John").ToList();

//after; q has Query/ToQueryString()
var q = db.Person.Where(p => p.Name == "John");
return q.ToList();

enter image description here

Image courtesy of Eamon Keene's blog which also details how to set up logging

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • 1
    Easy and robust solution. It works in .net 6 also. – Denny Jacob Apr 12 '22 at 21:00
  • It works… as far as it goes. However, EF creates all sorts of queries (via ChangeTracker) that you will never have access to the actual query string. It's better to just turn on SQL logging. – Auspex May 09 '23 at 12:55
5

If you are writing an API or App service based on the ASP.NET Core MVC framework, you can enable SQL logging in your Startup.cs class like this

public void ConfigureServices(IServiceCollection services)
{
    ...

    Action<DbContextOptionsBuilder> dbOptionsContextBuilder = builder => 
        {
        builder.UseSqlServer(Configuration.DbConnection)  // Configuration.DbConnection is the db connection string
               .UseLoggerFactory(ConsoleLoggerFactory);   // Logs out SQL
        };

    services.AddDbContext<YourDatabaseContext>(dbOptionsContextBuilder);


    ...
}

where ConsoleLoggerFactory has been defined earlier something like this:

private static readonly LoggerFactory ConsoleLoggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider((_, __) => true, true) });
Peter
  • 5,455
  • 7
  • 46
  • 68
1

Many answers here work like a charm, but not if you are using NLog.

If you are using NLog like me you can just do:

optionsBuilder.UseLoggerFactory(new NLogLoggerFactory());
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
hmojica
  • 603
  • 8
  • 11
1

If you're using Serilog:

Program.cs

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseSerilog()
        .MinimumLevel.Override("Microsoft.EntityFrameworkCore", Serilog.Events.LogEventLevel.Information)
            .WriteTo.Console(restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Verbose))
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Liam Kernighan
  • 2,335
  • 1
  • 21
  • 24