Frage zur Speicherverwaltung von slqconnection bei Verwendung von using

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Joe1968.

    Frage zur Speicherverwaltung von slqconnection bei Verwendung von using

    Hallo zusammen,

    ich leide gerade an ständigen Timeout-Fehlern beim Erstellen neuer SQL-Connections, da ich offenbar die maximale pooling-Grenze erreiche.
    Gelernt habe ich, dass ich die Connection mit using erstellen muss, damit beim Verlassen nach end using der Speicher wieder aufgeräumt wird.

    Jetzt ein paar Fragen an die Experten, die ich mir noch nicht beantworten konnte:
    - ich erstelle einen sqlcommand mit new und einen sqldatareader (ohne new) innerhalb von using. Wird der Speicherplatz nach Verlassen ebenfalls automatisch aufgeräumt oder erst nach Verlassen der function?
    - Ich verlasse die function innerhalb von using mit einem return Wert. Wird dadurch auch automatisch aufgräumt oder verbleiben Reste im Speicher, die mich wieder irgendwann die pooling Grenze erreichen lassen?

    Gibt es eine gute Seite im Netz zum Thema Speicherwalwaltung?

    Viele Grüße
    Joe
    OK, vielen Dank dafür.
    Das mit dem Using Block für die anderen beiden Objekte macht natürlich Sinn.

    Wenn ich Variablen in einem Using-Block erzeuge, sind diese nach End Using nicht mehr vorhanden, wie ich gerade ausprobiert habe. Werden also alle in einem Using Block erzeugten Variablen beim Erreichen von End Using durch den jeweiligen Destruktor automatisch zerstört und der Speicher freigegeben?
    Ein Using Block ist wie ein try block, oder ein if block ein eigener Scope innerhalb einer Funktion. d.h. Variablen die innerhalb von Using erzeugt werden, sind auch nur innerhalb von Using bekannt. Hast du z.B. innerhalb eines Usings noch ein if, und erzeugst darin eine Variable, ist diese auch nur dort drinnen gültig. Innerhalb des Usings aber außerhalb des Ifs kannst du diese nicht verwenden. Und das ganz unabhängig davon, ob diese nun Disposable ist oder nicht.

    Teste es einfach so:
    Erstelle eine Funktion, und schachtele mehrere ifs ineinander. Und nun erzeuge in jedem if eine neue variable und teste wo sie denn nun verfügbar ist. Dieses verhalten überträgt sich wie schon gsagt, auf using, try, switch usw.
    Ich finde es super, dass Du Dir die Zeit nimmst, das so gut zu erklären :)

    Ich muss mich um die Speicherfreigaben dann grundsätzlich gar nicht kümmern, wenn die Variablen ihren Gültigkeitsbereich verlassen oder ist es besserer Programmierstil, die Objekte trotzdem einem Dispose zu unterziehen bzw. Speicherbereiche anderer Variablen freizugeben?

    Dein Beispiel probiere in der Zwischenzeit aus...
    Bei variablen, die nicht mehr verwendet werden können und keine Objekte sind oder halten, die Disposed werden müssen, ja. Diese werden, so der GC will, irgendwann automatisch aufgeräumt. Wenn es sich dabei jedoch um Objekte handelt, die eben Ressourcen halten die explizit Disposed werden müssen, bleiben die ohne einen Aufruf von Dispose (bzw. ohne Benutzung von Using) im Speicher liegen bis das Programm beendet wird.

    Joe1968 schrieb:

    ich leide gerade an ständigen Timeout-Fehlern beim Erstellen neuer SQL-Connections, da ich offenbar die maximale pooling-Grenze erreiche.
    Gelernt habe ich, dass ich die Connection mit using erstellen muss, damit beim Verlassen nach end using der Speicher wieder aufgeräumt wird.
    vlt. haste da was nicht so gutes gelernt.
    Ich zB benutze in einem Repository nur eine Connection - ich erstelle die einmal und hebe sie auf zur wiederholten Verwendung. Beim Datenabruf öffne ich sie, und anschließend schließe ich sie - dassis wichtig.
    Kannste ja mal probieren, ob das bei deim Problem hilft - könnte darauf hindeuten, dass ständiges Neu-Erstellen im Falle Connections auch Nachteile haben kann.
    Aber für meinen "Aufbewahrungs-Pattern" ernte ich auch Widerspruch, und ein offensichtlicher Nachteil ist, dass man so nicht in einer MultiThreading-Umgebung arbeiten kann.
    So, habe mal in zwei meiner Projekte Eure Tips umgesetzt und muss sagen, dass ich es besser finde, die sqlconnection bei jedem Datenbankzugriff erneut zu erstellen. Die Performance leidet darunter nicht und ich konnte auch sonst keine negativen Effekte feststellen. Es hatte anfänglich auf jeden Fall Charme, nur eine Verbindung zu benutzen und diese immer wieder zu verwenden. Auch habe ich getestet, die Verbindung für die Dauer der Laufzeit offen zu lassen. Ich arbeite bei den Zugriffen mit Datareadern und da ein Datareader die ganze Verbindung lockt, muss ich immer eine zweite erstellen, wenn innerhalb des using-scope einen weiteren datareader öffnen muss.

    Deswegen habe ich mich dazu entschlossen, jeden Datenzugriff in diese sopes zu betten:
    using cnn as new sqlconnection
    using com as new sqlcommen
    using reader as sqldatareader
    und das TimeOut-Problem ist weg?



    Joe1968 schrieb:

    innerhalb des using-scope einen weiteren datareader öffnen muss

    ah - und du machst doch hoffentlich nicht etwas, wo du mit einem DataReader eine ParentTable durchgehst, und dann für jeden gelesenen Datensatz einen weiteren DataReader abfährst für die untergeordneten Datensätze dieses Datensatzes?

    Sorry, war einige Zeit im Urlaub.

    1. Ja, das Timeout-Problem ist behoben. Es lag anscheinend wirlich daran, dass die Objekte im Speicher nicht freigegeben wurden. Da das Programm immer läuft, wird irgendwann diese Pooling-Grenze erreicht sein.
    2. Ich gehe mit dem Datareader die Ergebnisse durch, erzeuge aber den weiteren Datareader innerhalb dieses scope nicht für untergeordnete Datensätze, sondern für andere Abfragen. Anscheinend ist der Datareader aber tatsächlich nicht die richtige Wahl, wenn er die Datenverbindung blockiert. Ich versuche es mal komplett ohne Datareader, und eher mit einer Datatable.