Reputation: 3841
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");
}
Upvotes: 6
Views: 9794
Reputation: 139
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);
Upvotes: 9
Reputation: 3841
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
Upvotes: 2
Reputation: 339
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
});
Upvotes: 2
Reputation: 140
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"
}
Upvotes: 2