Ich möchte diese Situation klären.
Gemäß den Microsoft-Richtlinien empfiehlt es sich, gegebenenfalls eine Close
Methode bereitzustellen . Hier ist ein Zitat aus den Framework-Designrichtlinien
Erwägen Sie die Bereitstellung einer Methode Close()
zusätzlich zu der Dispose()
Standardterminologie in diesem Bereich, wenn close die Standardterminologie ist. Dabei ist es wichtig, dass Sie die Close
Implementierung identisch mit Dispose
...
In den meisten Fällen sind Methoden Close
und Dispose
Methoden gleichwertig. Der Hauptunterschied zwischen Close
und Dispose
im Fall von SqlConnectionObject
ist:
Eine Anwendung kann Close
mehr als einmal aufrufen . Es wird keine Ausnahme generiert.
Wenn Sie die Dispose
Methode aufgerufen haben, wird der
SqlConnection
Objektstatus zurückgesetzt. Wenn Sie versuchen, eine Methode für ein entsorgtes SqlConnection
Objekt aufzurufen , erhalten Sie eine Ausnahme.
Das gesagt:
- Wenn Sie das Verbindungsobjekt einmal verwenden, verwenden Sie
Dispose
.
- Wenn das Verbindungsobjekt wiederverwendet werden muss, verwenden Sie die
Close
Methode.
con.Open() con.Close();
2con.Open(); // reuse
3.con.Dispose(); // use one time con.Open(); // error
Wie immer lautet die Antwort: es kommt darauf an. Verschiedene Klassen werden
IDisposable
auf unterschiedliche Weise implementiert , und es liegt an Ihnen, die erforderlichen Nachforschungen anzustellen.Es wird
SqlClient
empfohlen, Folgendes zu tun:Sie sollten die Verbindung anrufen
Dispose
(oderClose
*)! Warten Sie nicht , bis der Garbage Collector Ihre Verbindung bereinigt hat. Dadurch werden die Verbindungen im Pool (zumindest) bis zum nächsten GC-Zyklus gebunden. Wenn Sie aufrufenDispose
, ist ein Aufruf nicht erforderlichClose
, und da dasusing
Konstrukt dieDispose
korrekte Handhabung so einfach macht , gibt es wirklich keinen Grund zum AufrufenClose
.Verbindungen werden automatisch zusammengefasst, und das Anrufen
Dispose
/Close
auf der Verbindung schließt die Verbindung nicht physisch (unter normalen Umständen). Versuchen Sie nicht, Ihr eigenes Pooling zu implementieren.SqlClient
Bereinigt die Verbindung, wenn sie aus dem Pool abgerufen wird (z. B. Wiederherstellen des Datenbankkontexts und der Verbindungsoptionen).* Wenn Sie anrufen
Close
, stellen Sie sicher, dass Sie dies auf ausnahmesichere Weise tun (dh in einem Catch oder schließlich Block).quelle
conn.Close(); // Optional
Es ist nicht optional. Es ist überflüssig und unnötig. Sie entsorgen das Objekt zweimal und dies wird von einigen Code-Analyse-Tools als Warnung markiert.using (var x = ..) { x.Dispose(); }
, in welchem Fallx
wirklich "zweimal entsorgt" wird.Sie müssen Dispose () aufrufen!
Dispose () wird vom Entwickler aufgerufen, der Garbage Collector ruft Finalize () auf. Wenn Sie Dispose () für Ihre Objekte nicht aufrufen, werden nicht verwaltete Ressourcen, die sie verwendet haben, erst entsorgt, wenn der Garbage Collector vorbeikommt und sie finalisiert (und wer weiß, wann dies geschehen wird).
Dieses Szenario wird als nicht deterministische Finalisierung bezeichnet und ist eine häufige Falle für .net-Entwickler. Wenn Sie mit Objekten arbeiten, die IDisposable implementieren, rufen Sie Dispose () auf!
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
Während es viele Fälle gibt (wie bei SqlConnection), in denen Sie Disponse () für ein Objekt aufrufen und bei seiner Verbindung einfach Close () aufrufen oder ein Dateihandle schließen, ist es fast immer die beste Wahl, Dispose () aufzurufen! es sei denn, Sie planen, das Objekt in naher Zukunft wiederzuverwenden.
quelle
Dispose
.Dispose()
wenn Sie nichtusing()
mit einer Klasse arbeiten, die implementiertIDisposable
. Wenn die aufgerufene Klasse IDisposable implementiert und Sie ihre Verwendung auf der darin enthaltenen Seite verpackt habenusing()
, können Sie mit demDispose()
(Wortspiel beabsichtigt, also erschießen Sie mich) entsorgen . Die Verwendung von AFAIKClose()
wird jedoch für alles empfohlen, was explizit verwendetOpen()
wird.Close
eine Verbindung hergestellt haben, setzt Postgres die Verbindungskennung automatisch aufnull
. Von da an kann man keineDispose
SQL-Verbindungskennung mehr setzen, die bereits auf gesetzt istnull
.Denn
SqlConnection
aus der Sicht der Verbindung selbst sind sie gleichwertig. Laut Reflector werdenDispose()
AufrufeClose()
sowie einige zusätzliche speicherfreie Operationen ausgeführt - hauptsächlich durch Setzen von Mitgliedern auf Null.Für Stream sind sie tatsächlich gleichwertig.
Stream.Dispose()
ruft einfach Close () auf.quelle
Component
dem anscheinend nichts unternommen wird, um zu versuchen, anzurufenClose()
. Ich kann in keiner dieser Benachrichtigungen etwas sehenDBConnection
oderSqlConnection
das hängt damit zusammen. Es hat jedoch eine privateDisposeMe()
, auf die nirgendwo verwiesen wird .Dieser schnelle Rat wurde zu einer langen Antwort. Es tut uns leid.
Wie Tyler in seiner netten Antwort betonte, ist das Aufrufen
Dispose()
eine großartige Programmierpraxis. Dies liegt daran, dass diese Methode alle erforderlichen Ressourcen freisetzen soll, damit keine nicht benötigten offenen Ressourcen vorhanden sind. Wenn Sie beispielsweise Text in eine Datei geschrieben haben und die Datei nicht schließen konnten (die Ressource freigeben), bleibt sie geöffnet, und niemand anderes kann darauf schreiben, bis der GC vorbeikommt und das tut, was Sie haben sollten getan.In einigen Fällen wird es nun "Finalisierungs" -Methoden geben, die spezifischer für die Klasse sind, mit der Sie sich befassen, z. B.
StreamWriter.Close()
die überschrieben werdenTextWriter.Close()
. In der Tat sind sie normalerweise besser für die jeweilige Situation geeignet: Ein StreamWriterClose()
beispielsweise spült den Stream und den zugrunde liegenden Encoder, bevorDispose()
das Objekt bearbeitet wird ! Cool!Beim Durchsuchen von MSDN werden Sie jedoch feststellen, dass selbst Microsoft manchmal durch die Vielzahl von Schließern und Entsorgern verwirrt ist. Auf dieser Webseite wird zum Beispiel in einigen Beispielen
Close()
vor dem Impliziten aufgerufenDispose()
(siehe using-Anweisung, wenn Sie nicht verstehen, warum es implizit ist), und in einem Fall kümmern sie sich insbesondere nicht darum. Warum sollte das so sein? Auch ich war ratlos.Der Grund, warum ich dachte (und ich betone, dies ist eine originelle Forschung und ich könnte sicherlich den Ruf verlieren, wenn ich mich irre), ist, dass dies
Close()
fehlschlägt und eine Ausnahme ergibt, während Ressourcen offen bleiben, währendDispose()
sie sicherlich befreit werden . Weshalb einDispose()
sollten immer einen wahrenClose()
Anruf (sorry für das Wortspiel).Und ja, ich denke, Microsoft ist auf dieses eine Beispiel gestoßen. Vielleicht würde dieser Zeitstempel niemals in die Datei geschrieben werden.
Ich repariere morgen meinen alten Code.
Bearbeiten: Entschuldigung Brannon, ich kann Ihre Antwort nicht kommentieren, aber sind Sie sicher, dass es eine gute Idee ist, anzurufen
Close()
einenfinally
Block ? Ich denke, eine Ausnahme davon könnte den Rest des Blocks ruinieren, der wahrscheinlich wichtigen Bereinigungscode enthalten würde.Antwort an Brannon's: Großartig, vergessen Sie nicht, anzurufen,
Close()
wenn es wirklich benötigt wird (z. B. beim Umgang mit Streams - Sie wissen nicht viel über SQL-Verbindungen in .NET).quelle
Schreiben Sie auf iDisposable und rufen Sie dazu dispose auf. Dadurch wird die Methode aufgerufen, die für die Implementierung von "iDisposable.Dispose" konfiguriert ist, unabhängig davon, wie die Funktion benannt ist.
quelle
IDisposable.Dispose
, aber das heißt nicht, dass das der Name ist. Beachten Sie, dass es in vb.net möglich ist, eine Funktion an mehrere Schnittstellenelemente mit Namen zu binden, die nicht mit denen der Funktion verknüpft sein müssen.using (myObj as IDisposable)
Im Allgemeinen haben wir Probleme mit Close (), Abort () und Dispose (), aber ich möchte Ihnen einen Unterschied zwischen ihnen erklären.
1) ABORT: - Ich werde nicht empfehlen, dies zu verwenden, da der Client beim Aufruf von abort die Verbindung löscht, ohne dies dem Server mitzuteilen, sodass der Server einige Zeit (ca. 1 Minute) warten muss. Wenn Sie eine Massenanforderung haben, können Sie abort () nicht verwenden, da dies zu einer Zeitüberschreitung für Ihren begrenzten Verbindungspool führen kann.
2) Schließen: - Schließen ist ein sehr guter Weg, um die Verbindung zu schließen, da beim Schließen der Verbindung der Server aufgerufen wird und der Server bestätigt wird, auch auf dieser Seite zu schließen.
Hier noch eine Sache zu sehen. In einigen Fällen, wenn ein Fehler generiert wird, ist es keine gute Möglichkeit, Code endgültig in diese connection.close () zu schreiben, da zu diesem Zeitpunkt der Kommunikationsstatus fehlerhaft ist.
3) Entsorgen: - Es handelt sich um eine Art des Schließens, aber nach dem Schließen der Verbindung können Sie sie nicht wieder öffnen.
Also versuche es so,
quelle
client != null
ist falsch / irreführend, da nicht alle Verwendungen geschützt sind. Ich bin mir auch nicht sicher, wie Code in den Status "Diese Verbindung ist nicht geöffnet und sollte geschlossen werden" gelangen kann.