Was bedeutet „eine Verbindung öffnen“ eigentlich?
-
27-09-2019 - |
Frage
Ich habe versucht jemand, warum Datenbankverbindungen implementieren IDisposable, zu erklären, als ich merkte, ich weiß nicht wirklich, was „Öffnen eine Verbindung“ eigentlich bedeuten.
Also meine Frage ist - was praktisch tut c # tun, wenn es eine Verbindung öffnet?
Danke.
Lösung
Es gibt tatsächlich zwei bei der Umsetzung eine Verbindung beteiligten Klassen (eigentlich mehr, aber ich bin zu vereinfachen).
Eine davon ist die IDbConnection
Implementierung (SQLConnection
, NpgsqlConnection
, OracleConnection
, etc.), dass Sie in Ihrem Code verwenden. Die andere sind ein „echtes“ Verbindungsobjekt, das zur Montage intern ist, und der Code nicht sichtbar. Wir werden jetzt dieses „RealConnection
“ nennen, obwohl sein eigentlicher Name unterscheidet sich mit verschiedenen Implementierungen (zum Beispiel in Npgsql, was der Fall ist, wo ich am meisten vertraut mit der Umsetzung bin, wird die Klasse genannt NpgsqlConnector
).
Wenn Sie Ihre IDbConnection
erstellen, es hat keinen RealConnection
. Jeder Versuch, etwas zu tun mit der Datenbank fehl. Wenn Sie es Open()
dann passiert folgendes:
- Wenn Pooling aktiviert ist, und es gibt eine
RealConnection
im Pool, deque es und es dieRealConnection
für dieIDbConnection
machen. - Wenn Pooling aktiviert ist, und die Gesamtzahl der
RealConnection
Objekte in Existenz ist größer als die maximale Größe, eine Ausnahme aus. - Andernfalls eine neue
RealConnection
erstellen. Initialise es, die irgendeine Art von Netzwerkverbindung (z TCP / IP) oder Datei-Handle (für so etwas wie Access) öffnen beinhalten wird, gehen Sie durch die Protokoll-Datenbank für Handshake (variiert je nach Datenbanktyp) und die Verbindung autorisieren. Dies wird dann derRealConnection
für dieIDbConnection
.
Operationen durch auf dem IDbConnection
geführt werden, in dem Betrieb einge die RealConnection
tut auf seiner Netzwerkverbindung (oder was auch immer). Die Ergebnisse sind in Objekte gedreht IDataReader
Umsetzung und so weiter, um eine einheitliche Schnittstelle für die Programmierung zu geben.
Wenn ein IDataReader
mit CommandBehavior.CloseConnection
erstellt wurde, dann ist das Datareader erhält „Eigentum“ des RealConnection
.
Wenn Sie anrufen Close()
dann eine der folgenden Ereignisse eintritt:
- Wenn die Bündelung und wenn der Pool nicht voll ist, dann wird das Objekt in der Warteschlange für den Einsatz setzt mit späteren Operationen.
- Andernfalls ist die
RealConnection
durchführen werden alle protokolldefinierten Verfahren zum Beenden der Verbindung (Signalisierung an die Datenbank, dass die Verbindung zum Herunterfahren wird) und schließt die Netzwerkverbindung usw. Das Objekt kann dann der Umfang herausfallen und verfügbar werden für die Garbage collection.
Die Ausnahme wäre, wenn der CommandBehavior.CloseConnection
Fall geschehen ist, in diesem Fall ist es die Close()
oder Dispose()
auf dem IDataReader
aufgerufen wird, dass Trigger dies.
Wenn Sie rufen Dispose()
dann das gleiche passiert wie pro Close()
. Der Unterschied ist, dass Dispose()
wird als „clean-up“ und kann mit using
arbeiten, während Close()
könnte durch eine spätere Open()
in der Mitte der Lebensdauer und anschließend verwendet werden.
Durch die Verwendung des RealConnection
Objekts und der Tatsache, dass sie vereinigt sind, das Öffnen und Schließen von Verbindungen ändert etwas relativ schwer zu relativ leicht. Daher anstatt es wichtig ist, Verbindungen für eine lange Zeit offen zu halten, den Aufwand zu öffnen, sie zu vermeiden, wird es wichtig, sie für so kurze Zeit wie möglich offen zu halten, da die RealConnection
beschäftigt sich mit dem Aufwand für Sie, und je mehr schnell Sie sie verwenden, desto effizienter die gepoolten Verbindungen zwischen den Anwendungen gemeinsam genutzt bekommen.
Beachten Sie auch, dass es okay ist ein Dispose()
IDbConnection
, dass Sie bereits Close()
aufgerufen haben (es ist eine Regel, dass es immer sicher sein sollte Dispose()
, was auch immer der Staat zu nennen, in der Tat, auch wenn es bereits genannt wurde). Daher, wenn Sie manuell Close()
aufrufen würde, würde es immer noch gut sein, die Verbindung in einem using
habenBlock, Fälle zu fangen, wo Ausnahmen vor dem Aufruf von Close()
passieren. Die einzige Ausnahme ist, wo Sie die Verbindung tatsächlich wollen, offen bleiben; sagen Sie ein IDataReader
mit CommandBehavior.CloseConnection
erstellt wurden, zurückkehren, in dem Fall, dass Sie die IDbConnection
nicht entsorgen, aber entsorgen die Leser.
ausfällt Sie die Verbindung verfügen, dann ist die RealConnection
nicht an den Pool für die Wiederverwendung zurückgegeben werden, oder seine Abschaltverfahren gehen. Entweder ist der Pool wird seine Grenze erreicht, oder die Anzahl der zugrunde liegenden Verbindungen bis zu dem Punkt erhöhen die Leistung der Beschädigung und Blockierung mehr von geschaffen. Schließlich wird die finaliser auf RealConnection
genannt werden kann und führen zu dieser befestigt ist, aber Finalisierung nur reduziert den Schaden und kann nicht auf sie verlassen werden. (Die IDbConnection
braucht keine finaliser, wie es die RealConnection
ist, dass die nicht verwaltete Ressource hält und / oder Bedürfnisse der Abschaltung zu tun).
Es ist auch anzunehmen, dass es eine andere Anforderung ist für die Entsorgung einzigartig für die Umsetzung der IDbConnection
darüber hinaus, und es sollte noch selbst entsorgt werden, wenn die oben genannten Leitungen analysieren Sie es nicht nötig, zu glauben (die Ausnahme ist, wenn CommandBehavior.CloseConnection
leitet alle Entsorgungs Belastung für die IDataReader
, aber dann ist es ebenso wichtig, dass die Leser zu entsorgen).
Andere Tipps
Gute Frage.
Aus meinem (etwas eingeschränkt Wissen) der „unter der Motorhaube“ Arbeits einer SQL-Verbindung, sind viele Schritte beteiligt ist, wie zum Beispiel:
Die Schritte unter der Haube
- Physikalische Buchse / Rohr geöffnet wird (gegeben Treiber, zB ODBC)
- Handshake mit SQL Server
- Verbindungszeichenfolge / Berechtigungsnachweise auf Anfrage
- Transaktions Scoping
Nicht zu erwähnen, Connection Pooling, glaube ich, gibt es eine Art von alogrithm beteiligt (wenn die Verbindungszeichenfolge übereinstimmt für einen bereits vorhandenen Pool, wird die Verbindung zum Pool hinzugefügt, ansonsten neu erstellt wird)
IDiposable
Im Hinblick auf die SQL-Verbindungen realisieren wir IDisposable so, dass, wenn wir dispose aufrufen (entweder über die using-Direktive oder explizit), wird die Verbindung wieder in den Verbindungspool platziert. Dies steht in krassem Gegensatz zu nur dem einfachen alten SQLConnection.close (.) - wie all dies tut, ist nah es vorübergehend, behält sich aber, dass die Verbindung zur späteren Verwendung
Von meinem Verständnis, .Close () schließt die Verbindung zur Datenbank, während .Dispose () ruft .Close () und und Veröffentlichungen nicht verwalteten Ressourcen.
Diese Punkte im Auge, zumindest aber es ist eine gute Praxis IDisposable umzusetzen.
Das Hinzufügen Antworten oben ... Der Schlüssel ist, dass auf „Öffnen der Verbindung“ Ressourcen zugewiesen werden, dass mehr als die Standard-Garbage-Collection wird zu erholen, nämlich eine offene Buchse / Rohr / IPC von Schokoladenriegel besorgt. Die Methode Dispose () reinigt diese nach oben.