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

Time:01-24

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?

CodePudding user response:

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.

CodePudding user response:

"The problem is that I don't have a reference to an instance of ILogger" Let me start by this. You can use ILogger<TCategoryName> Interface, used to enable activation of a named ILogger from dependency injection.

This means that you can use dependency injection in any class, even StartUp.cs or DbContext to initiate an instance of ILogger.

public class Startup
{
    private readonly ILogger<Startup> _logger;

    public IConfiguration Configuration { get; }

    public Startup(ILogger<Startup> logger, IConfiguration configuration)
    {
        _logger = logger;
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        _logger.LogInformation("ConfigureServices called");
    }
}
  •  Tags:  
  • Related