Ядро EF EnableSensitiveDataLogging работает не так, как ожидалось

#c# #.net #asp.net-core #.net-core #entity-framework-core

#c# #.net #asp.net-core #.net-core #entity-framework-core

Вопрос:

Я использую EF Core 2.1.1 с использованием MySQL, и у меня есть следующий код для включения ведения журнала ef core, переведенного в SQL-запросы

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
      optionsBuilder.EnableSensitiveDataLogging();
}
  

Я ничего не вижу в журналах, хотя и не знаю почему.

Комментарии:

1. Вы пытались вызвать это в Configure services? Вот так: services.AddDbContext<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")).EnableSensitiveDataLogging())

2. Да, я тоже это пробовал

Ответ №1:

Используя EF Core 2.2 с Visual Studio 2019 и SQL Server, я смог заставить параметр EnableSensitiveDataLogging работать, используя следующую конфигурацию.

В вашем классе Startup.cs,

Добавьте службу ведения журнала в свой метод ConfigureServices. Я фильтрую ведение журнала по командам базы данных и уровню регистрации информации,

 services.AddLogging(loggingBuilder => {
    loggingBuilder.AddConsole()
        .AddFilter(DbLoggerCategory.Database.Command.Name, LogLevel.Information);
    loggingBuilder.AddDebug();
});

  

Теперь обновите свой DbContext, чтобы включить ведение журнала конфиденциальных данных,

 services.AddDbContext<MyDbContext>(options => {
    options.UseSqlServer(_configuration.GetConnectionString("MyDbConnection"));
    options.EnableSensitiveDataLogging(true);
});

  

После настройки запуска вы увидите, что команды SQL и их конфиденциальные данные отображаются в нашем окне вывода в Visual Studio (Debug…Windows…Вывод), как показано ниже,

 Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (3ms) 
    [Parameters=[@p1='aaa' (Nullable = false) (Size = 450), 
                 @p2='bbb' (Size = 4000), 
                 @p0='New Column Value' (Size = 4000)], 
    CommandType='Text', CommandTimeout='30']

SET NOCOUNT ON;
UPDATE [MyTableName] SET [MyColumnName] = @p0
WHERE [Id] = @p1 AND [OtherColumn] = @p2;
SELECT @@ROWCOUNT;

  

Мне потребовалось некоторое время, чтобы разобраться и в этом. Я также не смог заставить конфиденциальные данные отображаться в журнале, используя OnConfiguring в классе DbContext.

Надеюсь, это поможет, даже если он использует SQL Server, а не MySQL.

ОБРАТИТЕ ВНИМАНИЕ! Обязательно отключите ведение журнала конфиденциальных данных при развертывании в рабочей среде.

Комментарии:

1. Спасибо вам, спасибо вам, спасибо вам! Я очень долго искал этот «правильный», «рабочий» ответ. Любая другая конфигурация, которую я выполнил, может работать, НО я получаю сообщение об ошибке, что при КАЖДОМ запросе создается экземпляр объекта loggin. А для API это должно быть ОЧЕНЬ МНОГО!

2. RE: Обязательно отключите ведение журнала конфиденциальных данных при развертывании в рабочей среде. Вы можете включить его условно, например: if (env.IsDevelopment()) { options.EnableSensitiveDataLogging(); } для Web (ASP.NET ) приложения, то env есть IWebHostEnvironment . ИЛИ, например, с функциями Azure: if (builder.GetContext().EnvironmentName == "Development") { options.EnableSensitiveDataLogging(); } Предполагая, что вы используете Startup.cs и получаете IFunctionsHostBuilder в своем методе настройки посредством внедрения зависимостей.

3. В .NET 6 вам нужно: options.EnableSensitiveDataLogging(builder.Environment.IsDevelopment());

Ответ №2:

Вы должны использовать LoggerFactory приложения при создании параметров.

Не забудьте установить Microsoft.Расширения.Ведение журнала.Консоль (пакет Nuget)

 new ServiceCollection()
.AddTransient(provider => {
                var options = new DbContextOptionsBuilder<MyDbContext>()
                .EnableSensitiveDataLogging(true)
                .UseLoggerFactory((ILoggerFactory)provider.GetService(typeof(ILoggerFactory)))
                .UseMySql(config.GetConnectionString("DefaultConnection"))
                    .Options;
                return new MyDbContext(options);
            })