EF-Core und big-traffic führt zu max Poolgröße wurde erreicht Fehler
Verwenden wir ASP.NET Entity Framework-Kern für Abfragen unsere MSSQL-Datenbank-in unserem Web-API app. Manchmal, wenn wir große Verkehr, die Abfrage an die DB endet mit dieser Fehlermeldung:
Timeout ist abgelaufen. Das Zeitlimit wurde vor dem anfordern einer Verbindung aus dem pool. Dies stattgefunden haben könnte, weil alle zusammengefasste verbindungen wurden in verwendet und die maximale Poolgröße wurde erreicht.
Ich Frage mich, ob unserem Muster mit DbContext
und die Abfrage korrekt ist, oder wenn ich bin fehlen einige verwenden/entsorgen, - Muster und-Fehler wird verursacht durch ein memory leak (nach einiger recherche Las ich dann, ich sollte nicht verwenden, verwenden, da die Lebensdauer wird geleitet von den Rahmenbedingungen). Ich bin nach Dokumentation...
Mein connectionString:
"myConnection": "Server=xxx;Database=xxx;user id=xxx;password=xxx;Max Pool Size=200;Timeout=200;"
Mein Start.cs
public void ConfigureServices(IServiceCollection services)
{
.....
//scoped context
services.AddDbContext<MyDbContext>(
options => options.UseSqlServer(this.Configuration.GetConnectionString("myConnection")));
}
dann im Controller verwendete ich dbcontext von dependency injection:
public class MyController : Controller
public MyController (MyDbContext context)
{
this.Context = context;
}
public ActionResult Get(int id)
{
//querying
return this.Context.tRealty.Where(x=>x.id == id).FirstOrDefault();
}
Sollte ich so etwas wie:
using (var context = this.Context)
{
return this.Context.tRealty.Where(x => x.id == id).FirstOrDefault();
}
Aber ich denke, dass dies ist eine schlechte Muster, wenn ich mit dependency injection von DbContext
.
- Scheint, wie Sie haben Ihre eigene Frage beantwortet.
- Also sollte ich mit Verwendung wenn ich die Abfrage dbcontext wird Hinzugefügt, die durch dependency injection...
- Der DI-container sollte kümmern sich um die Entsorgung der Kontext, also Nein.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, dass problem verursacht wurde, indem Objekte aus der Datenbank Abfragen im Zusammenhang zu In-memory-cache. Ich hatte eine große LINQ-Abfrage auf Datenbank-Kontext mit einigen anderen Unterabfragen in. Ich rief
FirstOrDefault()
auf das Ende der Haupt-Abfrage, aber nicht in Unterabfragen. Controller war in Ordnung mit ihm, es materialisieren Abfragen standardmäßig.Und es war problem - Unterabfragen hielten Verbindung zum Datenbank-Kontext, wenn Sie wo speichern zu In-memory-cache. Wenn ich umgesetzt Redis verteilten cache, war es zunächst versagt, auf einige merkwürdige Fehler. Hilft es wenn ich Schreibe
ToList()
oderFirstOrDefault()
alle meine Unterabfragen, weil verteilte cache muss der materialisierten Objekte.Nun habe ich alle meine Fragen materialisiert explizit, und ich bekam keine max-pool-Größe wurde erreicht Fehler. Damit muss man vorsichtig sein, wenn die gespeicherten Objekte aus der Datenbank Abfragen im Zusammenhang zu In-memory-cache. Es ist notwendig, sich zu materialisieren, alle Abfragen zu vermeiden, halten Verbindung irgendwo im Speicher.
Können Sie die Lebensdauer des DbContext im Autostart.cs, sehen, ob das hilft:
Auch wenn Ihre Abfrage ist ein einfaches Lesen, Sie können entfernen Sie das tracking durch die Verwendung
.AsNoTracking()
.Einen anderen Weg, Ihren Durchsatz zu erhöhen ist, um zu verhindern, dass sperren durch die Verwendung eines Transaktions-block mit
IsolationLevel.ReadUncommitted
für einfach liest.Sie können auch die
Snapshot
isolation-level - das ist etwas mehr einschränken - wenn Sie nicht möchten, dass dirty reads.Edit : Wie der Autor der Frage erwähnt, der obige code ist (noch?) nicht möglich das EF-Core.
Einen workaround gefunden werden kann hier mit einer expliziten Transaktion:
Habe ich nicht getestet.
Edit 2: eine Weitere ungetestete snippet, wo Sie haben, Befehle ausgeführt zu set isolation level:
Mit Exec:
Edit 3: Nach dass thread, Transaktionen werden unterstützt .NET-Core-version 1.2 ab.
.AsNoTracking()
ist eine gute Idee, weil mein api ist nur zu Lesen, danke. Aber ich denke, dass problem liegt irgendwo in bad schließen von verbindungen, AsNoTracking sollte einfach schneller Abfragen. EF-Core-ich glaube nicht, verwenden SieTransactionScope
da es nicht unterstützt wird für jetzt linkTimeOut=200
in meinem connection-string, ich denke, es ist wirklich großen Wert für einfache get-Abfrage (unsere Anfragen werden schnell, bis die alle verbindungen verwendet werden, dann Fehler aufgetreten und die app ist Total tot. Wir können einfach starten Sie es.)Ich bin das hinzufügen einer alternativen Antwort, falls irgendjemand landet hier mit einem etwas anderen Ursache, wie bei meinem .NET-Core-MVC-Anwendung.
In meinem Szenario die Anwendung war die Herstellung dieser "timeout ist abgelaufen... max Poolgröße wurde erreicht" Fehler durch gemischte Nutzung von
async
/await
undTask.Result
innerhalb der gleichen Steuerung.Ich dies getan hatte, in einem Versuch, um die Wiederverwendung von code durch den Aufruf einer bestimmten asynchronen Methode in meinem Konstruktor, um eine Immobilie. Da Konstruktoren nicht erlauben asynchrone Aufrufe, ich war gezwungen zu verwenden
Task.Result
. Allerdings war ich mitasync Task<IActionResult>
Methoden zuawait
Datenbank Anrufe innerhalb des gleichen controller. Wir beschäftigen Microsoft Support, und ein Ingenieur half erklären, warum dies geschieht:Also in unserem Fall zog ich die
Task.Result
aus dem Konstruktor und zog Sie in einen privatenasync
Methode, wo wirawait
es. Dann, da ich nur wollen, dass es zur Ausführung des tasks einmal pro Nutzung der controller, Speicher ich das Ergebnis, dass die local-Eigenschaft, und führen Sie die Aufgabe innerhalb dieser Methode nur, wenn der Wert der Eigenschaft istnull
.In meiner Verteidigung, ich erwartet, dass der compiler mindestens werfen, eine Warnung sein, wenn das mischen von asynchronen und blocking code ist so problematisch. Jedoch, es scheint offensichtlich genug, um mich, im Nachhinein!
Ich hoffe, dies hilft jemand...