Wie schlimm ist es, SqlConnections nicht zu entsorgen?

14

Persönlich breche ich in Hives aus, wenn ich ADO-Objekte, die IDisposable implementieren, nicht in using-Anweisungen setze. Bei meinem aktuellen Vertrag habe ich jedoch festgestellt, dass der von ihnen selbst entwickelte Code des Enterprise-Frameworks "Data Access Provider" nicht 1) IDisposable implementiert und 2) Dispose () für alles, was es verwendet, zu irgendeinem Zeitpunkt jemals aufruft. Benutzer haben sich viel über Leistungsprobleme in den Winforms-Anwendungen beschwert, die dieses Framework für den Datenzugriff stark nutzen, und obwohl es eine Menge anderer Probleme im Code gibt, die die Leistung beeinträchtigen könnten, schreit mich dieser nur an und ist mehr niedrig hängende Früchte als die anderen.

Was kann ich diesen Leuten sagen, um sie davon zu überzeugen, dass dies wirklich sehr, sehr schlecht ist?

AJ Johnson
quelle
5
Heh..meine Vermutung ist, dass es irgendwann nicht mehr nötig sein wird, zu überzeugen :)
Dr. Hannibal Lecter

Antworten:

6

Ich würde sagen , das Beste , was Sie tun können , ist , sie zu Microsofts Mustern zeigen und Praktiken in Bezug auf Dispose() hier . Lassen Sie sie sehen, welche Konsequenzen es hat, wenn sie dieses Tool, das direkt vor ihnen liegt, nicht nutzen.

Jesse C. Slicer
quelle
1
Ich wünschte nur, ich könnte eine Version finden, die oben nicht "Dies ist ein Inhalt im Ruhestand" schreit.
AJ Johnson
Weißt du, meine Augen haben das nur beschönigt. Aber jetzt, wo ich es sorgfältig lese, frage ich mich, welche Technologien die Leute "noch verwenden", die von dieser Seite zurückgezogen sind. Vielleicht CAS?
Jesse C. Slicer
Wenn ich es genauer betrachte, scheint mir das meiste davon immer noch relevant zu sein. Ich bin mir auch nicht sicher, warum es als im Ruhestand markiert ist.
AJ Johnson
10

Wenn Sie die Dispose-Methode für eine SQL-Verbindung nicht aufrufen, wird diese Verbindung nach Abschluss der Verwendung NICHT wieder an den Verbindungspool zurückgegeben.

Wenn Sie Leistungsprobleme haben, ist meine Vermutung, dass die maximale Anzahl von Verbindungen in Ihrer Datenbank geöffnet ist. Ein DBA könnte dies leicht bestätigen.

Microsoft's Best Practice fordert Sie auf, Ihren Verbindungscode in eine Using-Anweisung einzufügen, um sicherzustellen, dass die Verbindung gelöscht und die Verbindung wieder in den Pool zurückgegeben wird.

Walter
quelle
Das Aufrufen Closeist ausreichend, um die Freigabe an den Verbindungspool zurückzusetzen. Die Frage besagt nicht, dass dies Closenicht explizit verwendet wird.
user2864740
9

Der Datenbankverbindungspool ist in seiner Größe begrenzt. Wenn er voll ist, warten neue Verbindungen darauf, dass alte Verbindungen freigegeben werden. Wenn Sie sie nicht entsorgen, sobald Sie fertig sind, werden sie irgendwann veröffentlicht, wenn der Finalizer ausgeführt wird, aber das ist eine unbestimmte Zeit in der Zukunft ... Also, im besten Fall Es treten lange Verzögerungen auf, wenn neue Verbindungen hergestellt werden.

Im schlimmsten Fall haben sie möglicherweise den Verbindungspool deaktiviert. Vielleicht stellten sie fest, dass ihre App nach einer Weile "Wartezeit auf Verbindungsfehler" zurückgab und das Deaktivieren des Verbindungspools dieses Problem "löste". Dies ist jedoch viel schlimmer, da Sie jedes Mal eine ganz neue Verbindung erstellen - was überraschend ressourcenintensiv ist. Wenn Sie Hunderte von Verbindungen zur Datenbank geöffnet haben, ist es kein Wunder, dass Sie Leistungsprobleme feststellen.

Der richtige Weg, um all diese Probleme zu lösen, besteht darin, Ihre Verbindung zu entsorgen, sobald Sie damit fertig sind. Die beste Idee ist, die Verbindung so lange wie nötig offen zu halten und nicht länger.

Dean Harding
quelle
1
Es ist sogar ein bisschen schlimmer. Wenn der Pool ausreichend gesichert wird, schlagen möglicherweise viele Verbindungsversuche fehl, einschließlich Verbindungsversuchen von Verwaltungstools, und Sie können die Datenbank effektiv sperren.
Joel Coehoorn
3

Bei jeder ernsthaften Anwendung würde ich sagen, dass es ziemlich schlecht ist. Diese Objekte können nicht nur die Leistung eines Killers beeinträchtigen, sondern sind auch einfach unprofessionell. Die gute Nachricht ist, dass Microsoft Finalize in der Objekthierarchie implementiert.

~Object()
{
    this.Dispose(false);    
}

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    // ...
}

Nehmen Sie System.Data.SqlClient.SqlConnectionzum Beispiel:

System.ComponentModel.Component <- Implementiert das Entsorgungsmuster Finalize.
    |
System.Data.Common.DbConnection
    |
System.Data.SqlClient.SqlConnection

Die Objekte werden irgendwann entsorgt, aber die nicht deterministische Natur beeinträchtigt die Leistung.

ChaosPandion
quelle
0

Zum einen beenden Sie die Verbindung nicht. Es muss also entweder a) automatisch gelöscht werden oder b) durchlaufen und aktualisiert werden, obwohl der Client keine Verwendung dafür hat.

Ich würde annehmen, b) wegen des Performance-Hits, den Sie beschreiben. Dies ist jedoch wahrscheinlich nicht der einzige Grund.

Sie MÜSSEN Ihre Verbindungen schließen, vorzugsweise auf der Clientseite, aber Sie müssen auch eine Ausfallsicherung auf der Serverseite implementieren. Andernfalls haben Sie nur zusätzlichen Mist, den Ihr Datenbankserver verarbeiten muss, bis er bei Gott-weiß-wann veröffentlicht wird.


quelle