SqlCommand.Dispose() nicht die Entsorgung der SqlParameters in es - Speicherverlust - C#.NET
Ich habe eine windows forms-Anwendung mit MS SQL Server 2005 als back-end. Ich habe code geschrieben in der form zu nennen, einige gespeicherte Prozeduren mithilfe der SqlConnection, SqlCommand-Objekte, und ich ordnungsgemäß entsorgen alles.
Habe ich entsorgt sqlcommand-Objekt durch Aufruf
oSqlCommand.Dispose()
Aber ich war Zeuge meiner Anwendung verbraucht sehr viel Speicher. Ich im Grunde pass großer XML-Dateien als SqlParameters.
Entschied ich mich schließlich zu Speicher-Profil mit Hilfe RedGate Speicher-profiler, und ich bemerkte, dass die System.Data.SqlClient.SqlParameters
werden nicht entsorgt.
Irgendwelche Erkenntnisse dazu?
Dank
NLV
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sehe ich das:
und so:
Allerdings sind diese gegenseitig ausschließen! Wenn Sie anrufen
.Dispose()
direkt, du machst es falsch. Das heißt, Sie lassen die Möglichkeit offen, eine Ausnahme machen das Programm überspringt den Anruf an denDispose()
Methode. Die "richtige" Art der Entsorgung von einem Befehl erzeugt einen using-block verwenden, etwa so:Nun, ich entnehme der Frage, das ist nicht das Haupt-problem im moment, aber es ist ein Punkt Wert Hause fahren.
Als für die Frage, Parameter: SqlParameters nicht implementieren IDisposable. Daher entsorgen Sie Sie nicht direkt. Sie sind ein ganz verwaltet Ressource, und das bedeutet, dass Sie ar ecleaned bis der garbage collector irgendwann nachdem Sie nicht mehr erreichbar. Sie müssen nicht alles tun, um Sie zu reinigen sich selbst.
Wenn Sie ernsthaft zeigen, dass ein SqlParameter-Objekt hängen, um lange, nachdem Sie sollten, sind Sie mit einem Verweis auf Sie irgendwo. Zum Beispiel, vielleicht sind Sie "caching" alten SqlCommand-Objekte irgendwo, was wiederum halten Sie sich auf alle Ihre Parameter. Tun Sie das nicht. Finden und beseitigen, was noch Referenzen die SqlParameters, und der garbage collector reinigen Sie Sie für Sie.
Update:
Nach re-Lektüre Ihrer Frage, es klingt wie die xml-Parametern am Ende auf dem Large Object Heap. Der garbage collector in .Net ist Generationen – es doesn ' T clean up alles jedes mal, wenn es läuft. Als ein Objekt bewegt sich auf einer höheren generation, ist es wahrscheinlicher, zu hängen, um eine Weile. Der Large Object Heap ist im Grunde die Letzte generation, und es nicht aufgeräumt ist viel. Mehr als das, es wird nicht komprimiert immer, sind solche, die im Laufe der Zeit-Fragmente. Dies kann zu einem Programm zu halten, um viel mehr Daten als benötigt. Was Sie tun müssen, ist zu versuchen, einen Weg zu finden, um zu verhindern, dass das laden des gesamten xml-Daten für einen parameter in den Speicher, so dass es nie macht es für den large object heap. Verwenden Sie einen Datei-stream oder etwas ähnliches statt.
Seit
SqlParameter
ist nichtIDisposable
es ist nicht ein Problem der Entsorgung; und normalerweise es wäre wenig sinnvoll, Aufräumen der Verweise etc, da ist es noch unter den gleichen GC.Wenn klingt wie Sie versehentlich gehalten, ein Verweis auf die
SqlCommand
. Aber wenn Sie sicher, dass Sie fertig sind, könnten Sie versuchen, explizit die Einstellung jeder.Value
zunull
und die BerufungClear()
auf der Liste Parameter. Aber das ist wirklich nur Maskierung die Tatsache, dass Sie das festhalten auf einem Toten Befehl.Entsorgen Sie die nicht Entsorgen Sie es Parameter, nur verfügt über interne SqlMetaData cache... es ist btw normal, dass die Parameter nicht automatisch entsorgt, weil Sie nicht passieren konnten, in etwas, das nicht sollte angeordnet werden, nachdem die Entsorgung der Befehl... + SqlParameter ist nicht die Umsetzung Entsorgen, entweder weil es hält keine nicht verwaltete Ressourcen ....
Ohne zu testen das ich mir denken kann, zwei Dinge, die Ihnen helfen könnten. Mit der
SqlParameters
könnten Sie diefinalize()
Methode, die Ressourcen freisetzen. Auch sind Sie laufen alle Ihre Sql-Befehle über eineusing
block? Wenn das so ist, wenn der using-block beendet ist, Ihre Ressourcen sollten freigegeben werden und es wird entfernen Sie Ihre memory-leak-Probleme.Habe ich dieses Muster ist in mehreren Projekten ohne Probleme
ref: http://msdn.microsoft.com/en-us/library/5czye81z%28VS.80%29.aspx
Gibt es mehrere Dinge, die Sie tun können, wenn Sie sich sicher sind, dass es die SqlParameter die halten die Letzte Referenz.
Ersten, versuchen Sie, geben Sie Ihre XML als string (und die Verwendung von OPENXML in einem sproc zu umgehen), nur um zu sehen, ob eine einfache Objekt-und mehr Kontrolle helfen.
Zweiten, machen Sie Ihre eigenen SqlParameter-s, bewahren Sie diese in einem Wörterbuch zu tun, und dann etwas wie:
Dann, nachdem Sie den Befehl ausführen, und entsorgen Sie den Befehl und schließen Sie (falls noch offen) und entsorgen Sie die Verbindung, gehen Sie in Ihr Wörterbuch, explizit zuweisen null als SqlParameter.Wert (oder nehmen Sie die string-ref aus .Der Wert wird in einer lokalen var, String zuweisen.Leere auf .Wert und dann null zuweisen, lokale var -- das ist nur, wenn SqlParameter.Wert beschwert sich gerade über null. Dann null zuweisen, die dictionary-Element (das war ein ref auf ein SqlParameter -) und dann null zuweisen Wörterbuch.
In einem einfachen Fall können Sie halten einen ref, nur um den einen, entscheidenden SqlParameter und überspringen Sie das Wörterbuch. Der entscheidende Punkt ist, zu halten explizit zuweisen von null-Werten - die letzten ref, um die Zeichenfolge und dann auf den letzten ref zu SqlParameter, die es.
Denken Sie daran, dass es gibt mehrere Dinge beteiligt. Es beginnt mit nicht Parsen von XML im mid-tier überhaupt - nur senden Sie es nach unten zu SQL und enden mit explizit mediensystemen verweisen. Wenn Sie Ihren code so, dass es tatsächlich gebaut wird, dass XML-on-the-fly machen, als eine große straight-string zu versuchen.
Wenn dies allein nicht niedriger Speicher Druck dann müssen Sie zwingen explizite GC-Sammlungen, aber für die, die Sie haben zu tun abit für das Lesen und planen von angemessenen Abständen, da GC kostet viel, d.h. wenn Sie beginnen GC-in nach jeder Anfrage wie einen verrückten Kaninchen, die Sie zu zahlen haben eine Menge CPU-Zyklen.
Auch, da Sie nicht sagen, wie groß die Daten tatsächlich ist und auf welcher Art von hardware Sie läuft, und wenn Ihr mid-tier unter dem IIS laufen, ist es schwer zu spekulieren über mögliche weitere Optionen, wie IIS laufen mehrere worker-Prozesse und nur recyceln, wenn Sie zu sehr aufgebläht. Für wirklich große Speicher-Verbrauch und echte pass-through mid-tier (also kein cache-Ansammlungen), die schneller sein können als das hantieren mit gc, aber wir sprechen wirklich riesige Daten in Auftrag zu geben, dass Bereich.