Skip to content

Latest commit

 

History

History
139 lines (95 loc) · 8.37 KB

File metadata and controls

139 lines (95 loc) · 8.37 KB
title description author ms.date uid
Using Microsoft.Extensions.Logging - EF Core
Logging from EF Core using Microsoft.Extensions.Logging in ASP.NET Core and other application types
ajcvickers
10/15/2020
core/logging-events-diagnostics/extensions-logging

Using Microsoft.Extensions.Logging in EF Core

Microsoft.Extensions.Logging is an extensible logging mechanism with plug-in providers for many common logging systems. Both Microsoft-supplied plug-ins (e.g Microsoft.Extensions.Logging.Console) and third-party plug-ins (e.g. Serilog.Extensions.Logging) are available as NuGet packages.

Entity Framework Core (EF Core) fully integrates with Microsoft.Extensions.Logging. However, consider using simple logging for a simpler way to log, especially for applications that don't use dependency injection.

ASP.NET Core applications

Microsoft.Extensions.Logging is used by default in ASP.NET Core applications. Calling xref:Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContext%2A or xref:Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContextPool%2A makes EF Core automatically use the logging setup configured via the regular ASP.NET mechanism.

Other application types

Other application types can use the GenericHost to get the same dependency injection patterns as are used in ASP.NET Core. xref:Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContext%2A or xref:Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContextPool%2A can then be used just like in ASP.NET Core applications.

Microsoft.Extensions.Logging can also be used for applications that don't use dependency injection, although simple logging can be easier to set up.

Microsoft.Extensions.Logging requires creation of a xref:Microsoft.Extensions.Logging.LoggerFactory. This factory should be stored as a static/global instance somewhere and used each time a DbContext is created. For example, it is common to store the logger factory as a static property on the DbContext.

[!code-csharpMain]

public static readonly LoggerFactory MyLoggerFactory
    = new LoggerFactory(new[] { new ConsoleLoggerProvider((_, __) => true, true) });

Warning

In EF Core 2.1, It is very important that applications do not create a new LoggerFactory instance for each DbContext instance. Doing so will result in a memory leak and poor performance. This has been fixed in EF Core 3.0 and above.


This singleton/global instance should then be registered with EF Core on the xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder. For example:

[!code-csharpMain]

Getting detailed messages

Tip

OnConfiguring is still called when AddDbContext is used or a DbContextOptions instance is passed to the DbContext constructor. This makes it the ideal place to apply context configuration regardless of how the DbContext is constructed.

Sensitive data

By default, EF Core will not include the values of any data in exception messages. This is because such data may be confidential, and could be revealed in production use if an exception is not handled.

However, knowing data values, especially for keys, can be very helpful when debugging. This can be enabled in EF Core by calling xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.EnableSensitiveDataLogging. For example:

[!code-csharpEnableSensitiveDataLogging]

Detailed query exceptions

For performance reasons, EF Core does not wrap each call to read a value from the database provider in a try-catch block. However, this sometimes results in exceptions that are hard to diagnose, especially when the database returns a NULL when not allowed by the model.

Turning on xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.EnableDetailedErrors%2A will cause EF to introduce these try-catch blocks and thereby provide more detailed errors. For example:

[!code-csharpEnableDetailedErrors]

Configuration for specific messages

The EF Core xref:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.ConfigureWarnings%2A API allows applications to change what happens when a specific event is encountered. This can be used to:

  • Change the log level at which the event is logged
  • Skip logging the event altogether
  • Throw an exception when the event occurs

Changing the log level for an event

Sometimes it can be useful to change the pre-defined log level for an event. For example, this can be used to promote two additional events from LogLevel.Debug to LogLevel.Information:

[!code-csharpChangeLogLevel]

Suppress logging an event

In a similar way, an individual event can be suppressed from logging. This is particularly useful for ignoring a warning that has been reviewed and understood. For example:

[!code-csharpSuppressMessage]

Throw for an event

Finally, EF Core can be configured to throw for a given event. This is particularly useful for changing a warning into an error. (Indeed, this was the original purpose of ConfigureWarnings method, hence the name.) For example:

[!code-csharpThrowForEvent]

Filtering and other configuration

See Logging in .NET for guidance on log filtering and other configuration.

EF Core logging events are defined in one of:

  • xref:Microsoft.EntityFrameworkCore.Diagnostics.CoreEventId for events common to all EF Core database providers
  • xref:Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId for events common to all relational database providers
  • A similar class for events specific to the current database provider. For example, xref:Microsoft.EntityFrameworkCore.Diagnostics.SqlServerEventId for the SQL Server provider.

These definitions contain the event IDs, log level, and category for each event, as used by Microsoft.Extensions.Logging.