Entity Framework Core: Log-Abfragen für eine einzige db-context-Instanz
EF-Core (oder jede ORM für diese Angelegenheit) ich möchte, um zu verfolgen die Anzahl der Abfragen, die ORM für die Datenbank während eine operation an meiner software.
Habe ich benutzt SQLAlchemy unter Python frühere, und auf das stack-dies ist faily einfach einzurichten. Ich haben in der Regel unit-tests, die behaupten, auf die Anzahl der Anfragen für ein Szenario, gegen eine in-memory SQLite Datenbank.
Nun möchte ich das gleiche tun mit EF-Core, und habe mir die Protokollierung Dokumentation.
In meinem test-setup code ich tun wie die Dokumentation sagt:
using (var db = new BloggingContext())
{
var serviceProvider = db.GetInfrastructure<IServiceProvider>();
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
loggerFactory.AddProvider(new MyLoggerProvider());
}
Aber ich laufen in Probleme, die ich vermute, sind die Ergebnisse der folgenden (auch von den docs):
Brauchen Sie nur zu registrieren, den logger mit einem einzigen context-Instanz.
Sobald Sie sich registriert haben, wird es für alle anderen Instanzen
der Kontext, in derselben AppDomain.
Die Probleme sehe ich in meinen tests zeigt an, dass mein logger Umsetzung wird gemeinsam von mehreren Kontexten (dies ist in übereinstimmung mit den docs, da ich Sie lese). Und da a) mein test runner führt tests in parallell und b) meine gesamte test-suite erstellt Hunderte von db - Kontexte- es funktioniert nicht sehr gut.
Frage/Fragen:
- Ist, was ich will möglich?
- I. e. registriere ich einen logger mit einem db-Kontext ist nur, dass db-context-Instanz?
- Gibt es andere Möglichkeiten das zu erreichen, was ich versuche zu tun?
- Was ist Ihr test-runner;
NUnit
,MsTest
,XUnit
? - Xunit-Test-runner
- Haben Sie das herausgefunden? Ich habe versucht, die Filterung für
Microsoft.EntityFrameworkCore.Storage.Internal.SqliteRelationalConnection
aber nicht alles bekommen. - Würde einschließlich Thread.CurrentThread.ManagedThreadId in Ihren logs helfen?
- Haben Sie versucht, miniprofiler.com
- werde es versuchen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Call
DbContextOptionsBuilder.UseLoggerFactory(loggerFactory)
Methode log alle SQL-Ausgabe von einem bestimmten context-Instanz. Sie konnte Spritzen, ein logger-Werk in den Kontext der Konstruktor.Hier ist ein Beispiel:
In der Regel, ich benutze diese Funktion für die manuelle Prüfung. Um die original-Kontext-Klasse sauber, eine abgeleitete überprüfbare Kontext deklariert ist überschrieben mit
OnConfiguring
Methode:Es ist genug, um log-SQL-Abfragen. Vergessen Sie nicht, bringen Sie eine geeignete logger (wie die Konsole) zu
loggerFactory
bevor Sie übergeben es an Zusammenhang.Teil II: Pass-Protokolle, um xUnit-Ausgang und ReSharper test output-Fenster
Erstellen wir ein
loggerFactory
in einer test-Klasse-Konstruktor:Der test-Klasse ist abgeleitet von
BaseTest
unterstützt das schreiben anxUnit
Ausgabe:Den meisten schwierige Teil ist die Umsetzung einer logging-Anbieter akzeptieren
IWriter
als parameter:Wir hier getan haben! Alle SQL-logs wird gezeigt, in Reiter/Resharper test output-Fenster.
_loggerFactory
um es so zu benutzen:new TestContext(_loggerFactory)
?ILoggerFactory
Umsetzung. Registrieren Sie sich inStartup
:services.AddLogging();
. Dann injizieren Sie dieILoggerFactory
Schnittstelle per Konstruktor an die Klasse, welche Anrufenew TestContext(_loggerFactory)
..GetService<ILoggerFactory>()
Anruf, dann alles, was Sie brauchen, ist die übergabe der Fabrik anTestContext
Konstruktor.using (var context = new TestContext(_loggerFactory))
- ok, ich glaube, ich kann meine Frage selbst beantwortet, bevor Sie führen Sie den test aus, den Sie Draht, ServiceCollection und seine von dort erhalten Sie die Referenz. Ich werde es geben ein anderes gehen._loggerFactory
ist in einer test-Klasse-KonstruktorLesen Sie diese:
docs.microsoft.com/en-us/ef/core/miscellaneous/logging
Wenn Sie sich einloggen möchten, um statische destination (z.B. Konsole) Ilja Antwort funktioniert, aber wenn Sie möchten, melden Sie zuerst benutzerdefinierte Puffer, wenn jeder dbContext sammelt log-Nachrichten an seinen eigenen Puffer (und dass, was Sie gerne tun würden, im multiuser-service), dann UPSSS - Speicher-Lecks (und das memory leak ist etwa 20 mb pro fast leeres Modell)...
Wenn EF6 hatte einfache Lösung zum abonnieren eines Log-Ereignisses in einer Linie, jetzt Spritzen Sie Ihre Anmeldung auf diese Weise:
schreiben Sie die pooling-monster.
P. S. Jemand sagen, zu Ef-Core-Architekten, dass Sie Falsches Verständnis von DI-und diejenigen, die Lust auf service Locator-Punkte, die Sie als "Container" und fließend UseXXX, dass Sie leihen sich von ASP.Kern ist, nicht ersetzen können "vulgär DI von constructor"! Mindestens log Funktion sollte normalerweise injizierbare durch Konstruktor.
*P. P. S. Lesen Sie auch diese https://github.com/aspnet/EntityFrameworkCore/issues/10420 . Dies bedeutet, dass das hinzufügen von LoggerFactory brach Zugriff auf InMemory data provider. Dies ist eine Abstraktion, Leck, wie es ist. EF-Core hat Probleme mit der Architektur.
ILoggerFactory pooling-code:
Können Sie mit einem begrenzten Kontext. Ich verwendete EF-Coed zuerst erstellen Sie zwei unterschiedliche Kontexte
Kunden eingegrenzten Kontext wird nicht protokolliert alle Abfragen
API eingegrenzten Kontext protokolliert die Abfragen
diese melden sich die Abfrage, um die debug-Ausgabe-Fenster in VS