Search code examples
c#entity-frameworkasp.net-coredbcontextilogger

How do I set up a DbContext to log errors to ILogger?


I have an ASP.NET Core application, and in my Startup.cs file, in the ConfigureServices(IServiceCollection services) function, I'm trying to write something like this:

//...

namespace MyNamespace
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //...

            services.AddDbContext<ModelDbContext>(options =>
            {
                options.UseSqlServer(_configuration.GetConnectionString("Model"),
                    sqlServerOptionsAction => sqlServerOptionsAction.EnableRetryOnFailure());
                options.LogTo(
                    filter: (eventId, _) => eventId.Id == CoreEventId.ExecutionStrategyRetrying,
                    logger: (eventData) =>
                    {
                        var retryEventData = (ExecutionStrategyEventData)eventData;
                        var exceptions = retryEventData.ExceptionsEncountered;
                        var exception = exceptions[exceptions.Count - 1];
                        logger.LogWarning(exception,
                            "Database error occurred. Retry #{ExceptionsCount} with delay {RetryEventDataDelay} due to error: {ExceptionMessage}",
                            exceptions.Count, retryEventData.Delay, exception.Message);
                    });
            }, ServiceLifetime.Transient);

            //...
        }

        //...
    }
}

However, I don't know how to make this line above work:

logger.LogWarning(exception,
    "Database error occurred. Retry #{ExceptionsCount} with delay {RetryEventDataDelay} due to error: {ExceptionMessage}",
    exceptions.Count, retryEventData.Delay, exception.Message);

The problem is that I don't have a reference to an instance of ILogger, so I don't know how to call the LogWarning function in that context.

So my question is:

  • What should I do to configure the DbContext with a reference to an ILogger instance?
    • Can I somehow use IServiceCollection services to construct an instance of ILogger? It feels a bit wrong to do that inside the ConfigureServices(IServiceCollection services) function. Or is there another better way?

Solution

  • You can use the other overload of AddDbContext, which provides the application's IServiceProvider which you can get logger from it, but somehow this overload is documented as less preferred.

    The other way is just inject ILogger into your DbContext via the constructor, and configure your logging in DbContext.OnConfiguring to log into the injected logger.