The other day I was having to dig into some performance issues around a process that is using Entity Framework Core. As part of the process, I need to see the queries generated by Entity Framework Core to make sure they were not the source of the issue (they were not). I’m going to be making these changes using the Contacts project from my ASP.NET Core Basics repo if you want to see where I started from.
First, we will cover adding a logging provider. Next, I’m going to show you what I came up with and then I will show you the method suggested by the Microsoft docs (which I didn’t find until later).
Logging Providers
First, we need to do pick how we want the information logged. A good starting place is using one of the Microsoft provides which can be found on NuGet. Right-click on the project you want to add the logging to and click Manage NuGet Packages.
In the search box enter Microsoft.Extensions.Logging for a list of good list of logging options. For this post, we will be using the console logger provided by Microsoft. Select Microsoft.Extensions.Logging.Console and then click the Install button on the upper right side of the screen.
First Go
For my first try at this, all the change are in the ConfigureServices
function of the Startup
class. The following is the code I added at the end of the function that will log all the queries to the console window (if you are using IIS Express then use the Debug logger instead).
var scopeFactory = services.BuildServiceProvider() .GetRequiredService<IServiceScopeFactory>(); using (var scope = scopeFactory.CreateScope()) { using (var context = scope.ServiceProvider .GetRequiredService<ContactsContext>()) { var loggerFactory = context.GetInfrastructure() .GetService<ILoggerFactory>(); loggerFactory.AddProvider(new ConsoleLoggerProvider((_, __) => true, true)); } }
This code is creating a scope to get an instance of the ContactsContext
and then using the context to get it’s associated logger factory and adding a console logger to it. This isn’t the cleanest in the world but gets the job done especially if this is just for a quick debug session and not something that will stay.
Microsoft Way
While the above works I ended up finding a logging page in the Entity Framework Core docs. After undoing the changes made above open the ContactsContext
(or whatever your DBContext is) and add a class level static variable for a logger factory. This class level variable will be used to prevent memory and performance issues that would be caused by creating a new instance of the logging classes every time a context is created.
public static readonly LoggerFactory LoggerFactory = new LoggerFactory(new[] {new ConsoleLoggerProvider((_, __) => true, true)});
Next, add/update an override to the OnConfiguring
to use the logger factory defined above. The following is the full function in my case.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseLoggerFactory(LoggerFactory); }
The Output
Either way, the following is an example of the output you will get with logging on.
The query is highlighted in the red box above. As you can see there is a lot of output, but there are options for filtering which are detailed in the docs.
Wrapping Up
Entity Framework Core does a great job, but the above gives you an option to check in on what it is doing. If you are using SQL Server you could also get the queries using SQL Server Profiler.
Also published on Medium.