Protokollieren aller Datenbankabfragen in Asp.Net Boilerplate 4.3 .Net Core 2.1

Oft gibt es im Projekt einen unverständlichen Fehler, für den eine maximale Protokollierung aller Abfragen in der Datenbank erforderlich ist . Der Artikel hilft denjenigen, die eines ihrer ersten Projekte auf dem Asp.Net Boilerplate schreiben (auf dem Server bereitstellen) .

Dieser Artikel richtet sich an Personen, die neu in der Asp.Net Boilerplate-Technologie sind und auf einen seltsamen Fehler im Zusammenhang mit der Datenbank gestoßen sind. Bei Verwendung von PostgreSQL kann dies beispielsweise das erste Projekt sein. Die Motivation für das Schreiben des Artikels war, dass die Lösung für dieses Problem im Internet nicht so einfach zu finden ist, selbst auf Englisch, ganz zu schweigen von der Tatsache, dass die gefundenen Lösungen nicht alle Fragen zu diesem Problem vollständig beantworten.

Produktversion: Asp.Net Boilerplate 4.3, .NET Core 2.1

Wenn Sie die folgenden Schritte ausführen : In Ihrer Hauptprotokolldatei werden alle Anforderungen an die angemeldete Datenbank angezeigt.

Schritt 1


Sie müssen einen Logger erstellen. Auf der Boilerplate-Plattform ist bereits ein interner Logger konfiguriert. Es kann standardmäßig Log4Net sein. Es besteht keine Notwendigkeit, Manipulationen mit ihm vorzunehmen. Stattdessen reicht es aus, eine Logger-Klasse zu erstellen, die Sie als Handler aller Protokollnachrichten aus der Datenbank registrieren.

Schritt 1.1


Projekt * .EntityFrameworkCore. Hier müssen wir 2 Klassen erstellen. Ein Logger, der nur eines tut, gibt zum einen alle Nachrichten aus der Datenbank in das Systemprotokoll aus. Nennen wir es MyLogger. Und der Anbieter dieses Loggers, der MyLogger erstellt. Der Anbieter heißt MyLoggerProvider.

Wir erstellen eine Datei mit dem folgenden Code (eine Datei zur Vereinfachung, obwohl natürlich jede Datei eine Klasse haben sollte):

public class MyLoggerProvider : ILoggerProvider { private Castle.Core.Logging.ILogger _logger; public MyLoggerProvider(Castle.Core.Logging.ILogger logger) { _logger = logger; } public ILogger CreateLogger(string categoryName) { return new MyLogger(_logger); } public void Dispose() { } } public class MyLogger : ILogger { private Castle.Core.Logging.ILogger _logger; public MyLogger(Castle.Core.Logging.ILogger logger) { _logger = logger; } public IDisposable BeginScope<TState>(TState state) { return null; } public bool IsEnabled(LogLevel logLevel) { return true; } public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) { if (IsEnabled(logLevel)) { var msg = formatter(state, exception); _logger.Info("DB-REQUEST: " + msg); } } } 

Wenn Sie genau hinschauen, können Sie sehen, wie ein anderer Logger an MyLoggerProvider und dann an MyLogger weitergeleitet wird. Es stellt sich schon der dritte heraus! Das Fazit ist, dass dieses dritte die Klasse der Ebene der Protokollierungsinfrastruktur ist, die aus den Eingeweiden der Boilerplate bezogen werden muss, mit deren Hilfe die Nachrichten im Protokoll gespeichert werden. Siehe unten.

Schritt 2


Wechseln Sie im Rahmen desselben * .EntityFrameworkCore-Projekts zur Datei * DbContextConfigurer.cs und nehmen Sie in beiden Configure () -Methoden die folgenden Änderungen vor:

2.1) Fügen Sie einen loggerfactory-Parameter vom Typ LoggerFactory hinzu

2.2) Fügen Sie dem Methodenkörper zwei Zeilen hinzu:

 builder.UseLoggerFactory(loggerFactory); builder.EnableSensitiveDataLogging(true); 

Die Bedeutung von UseLoggerFactory besteht darin, die Verwendung von loggerFactory zu aktivieren, die in den Parametern für die Protokollierung der Datenbank übergeben wird. Es ist sehr wichtig, sich daran zu erinnern, dass wir hier die Datenbankprotokollierung aktivieren.

Die Bedeutung von EnableSensitiveDataLogging besteht darin, die Protokollierung nicht nur von Datenbankabfragen zu ermöglichen, sondern auch alle Daten in diesen Abfragen aufzuzeichnen. Ohne diese Einstellung können Sie die Daten in den Abfragen nicht sehen - sie werden durch Fragezeichen ersetzt.

Schritt 3


Im Rahmen desselben * .EntityFrameworkCore-Projekts wechseln wir zur Datei * DbContextFactory.cs.

3.1) Fügen Sie eine neue Methode hinzu:

 private LoggerFactory GetDbLoggerFactory() { return new LoggerFactory(new[] { new MyLoggerProvider(NullLogger.Instance) }); } 

3.2) In der CreateDbContext () -Methode:
Weil Da wir zuvor beiden Configure () - Implementierungen einen neuen Parameter hinzugefügt haben, sollte hier ein Fehler angezeigt werden. Es ist Zeit, diesen neuen Parameter anzugeben - wir registrieren GetDbLoggerFactory () mit einem Komma. Das heißt, Der Wert des neuen loggerFactory-Parameters wird von der neuen Methode aus Abschnitt 3.1 zurückgegeben.

Schritt 4


Im Rahmen desselben * .EntityFrameworkCore-Projekts wechseln wir zur Datei * EntityFrameworkModule.cs.

4.1) Fügen Sie eine neue Methode hinzu:

 private LoggerFactory GetDbLoggerFactory() { return new LoggerFactory(new[] { new MyLoggerProvider(Logger) }); } 

4.2) In der PreInitialize () -Methode:

Weil Da wir zuvor beiden Configure () - Implementierungen einen neuen Parameter hinzugefügt haben, sollte hier auch ein Fehler angezeigt werden. Wir geben einen neuen Parameter ähnlich wie in Abschnitt 3.2 an - wir registrieren GetDbLoggerFactory () mit einem Komma. Das heißt, Der Wert des neuen loggerFactory-Parameters wird von der neuen Methode aus Abschnitt 4.1 zurückgegeben.

Ergebnis


In der Hauptprotokolldatei (standardmäßig Logs.txt) sehen Sie alle Abfragen, denen die DB-REQUEST-Zeichenfolge vorangestellt ist (von hier aus können Sie nach Daten im Protokoll suchen).

Allgemeines Verständnis der Lösung


Jetzt werde ich erklären, was wir getan haben. Eine Erklärung finden Sie am Ende des Artikels, weil Oft sind die Leser daran interessiert, bereits etwas Bestimmtes zu tun.

In der Klasse * DbContextFactory sowie * EntityFrameworkModule erstellen wir unsere LoggerFactory, in deren Parametern wir den erstellten MyLoggerProvider angeben. Als Infrastrukturklasse, die sich im ersten Fall direkt anmeldet (* DbContextFactory), übergeben wir den NullLogger.Instance-Stub, sodass keine Einträge vorhanden sind. Im zweiten Fall (* EntityFrameworkModule) übergeben wir den Logger, der sich bereits im Abp-Modul befindet. Dies ist das Logger-Feld. Es ist bereits initialisiert und kann damit protokolliert werden. Dementsprechend kann unser MyLogger mit dieser Klasse in die Datei Logs.txt schreiben.

Die gesamte Logik besteht darin, dass diese loggerFactory-Factory als Log Factory für die Arbeit mit der Datenbank installiert wird. Sobald ein Logger benötigt wird, wird er vom Werk erstellt. Und dies ist unser MyLogger, der seinerseits alles protokolliert, was zu Logs.txt kommt (oder die Quelle, für die die Ausgabe Ihrer Hauptprotokolle konfiguriert ist).

Wie Sie sehen, ist nicht alles so einfach und die Abstraktionsebenen frieren manchmal ein, besonders für Anfänger! Stellen Sie Ihre Fragen in den Kommentaren.

Hinweis:

- Die Lösung wurde erstellt, um den Logger einzuschalten, den Fehler zu verstehen und ihn auszuschalten. Es ist nicht für den Langzeitgebrauch ausgelegt.

Source: https://habr.com/ru/post/de444660/


All Articles