Ist sqlcommand.disponse () erforderlich, wenn die assoziierte SQLConnection entsorgt wird?
-
05-07-2019 - |
Frage
Normalerweise verwende ich einen solchen Code:
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
{
var command = connection.CreateCommand();
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
Wird mein command
automatisch entsorgt? Oder nicht und ich muss es einwickeln using
Block? Ist es erforderlich, zu entsorgen? SqlCommand
?
Lösung
Mach das einfach:
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
Nicht anrufen, das den Befehl entsetzt, wird nichts schlechtes tun. Die Anrufung wird jedoch entsorgen Verklemmen Sie den Anruf zum Finalizer, Anrufen zu machen, entsorgen Sie eine Leistungsverbesserung.
Andere Tipps
Die sicherste Richtlinie besteht darin, immer anzurufen Dispose()
auf einem Objekt, wenn es impliziert IDisposable
, entweder explizit oder über einen Block mithilfe von Block. Es kann Fälle geben, in denen es nicht erforderlich ist, aber es ohnehin anrufen sollte, sollte niemals Probleme verursachen (wenn die Klasse korrekt geschrieben ist). Außerdem wissen Sie nie, wann eine Implementierung sich ändern kann, was bedeutet, dass der Anruf, der bisher nicht erforderlich war, jetzt definitiv erforderlich ist.
Im Beispiel, das Sie angegeben haben, können Sie einen zusätzlichen inneren Block für den Befehl hinzufügen und den äußeren mithilfe von Block für die Verbindung beibehalten.
Ja, Sie sollten, selbst wenn die Implementierung derzeit nicht viel tut, Sie wissen nicht, wie sie in Zukunft verändert werden wird (neuere Rahmenversionen zum Beispiel). Im Allgemeinen sollten Sie alle Objekte entsorgen, die implementiert werden IDisposable
auf der sicheren Seite sein.
Wenn die Operation jedoch aufgeschoben wird und Sie den vollständigen Umfang nicht kontrollieren (zum Beispiel bei asynchrone Arbeit SqlDataReader
oder so) können Sie die festlegen CommandBehavior
zu CloseConnection
sobald der Leser fertig ist, ist die Verbindung für Sie ordnungsgemäß geschlossen/entsorgt.
Sie können diese Art von Dingen mithilfe der Dinge herausfinden Reflektor oder Dotpeek oder https://referencesource.microsoft.com/.
Ich hatte eine kleine Ausgrabung (ich würde vorschlagen, dass Sie sich selbst graben, um sich des Restes jedoch ganz sicher zu sein, da ich mich nicht so sehr bemüht habe), und es sieht so aus mit dieser Verbindung. Außerdem sieht es nicht so aus, als ob die Entsorgung eines Befehls tatsächlich so viel tut. Es setzt ein Feld auf Null, löst sich von einem Container (dies kann ein verwaltetes Speicherleck verhindern) und erhöhen ein Ereignis (dies könnte wichtig sein, aber ich kann nicht sehen, wer dieses Ereignis hört).
In beiden Fällen ist es eine gute Praxis, dieses Zeug in einem verwendeten Block zu verwenden oder sicherzustellen, dass Sie es mit einem Entsetztmuster in dem Objekt entsorgen, das die Verbindung hält (wenn Sie den Befehl für eine Weile festhalten möchten).
In der Praxis können Sie überspringen Dispose
. Es befreien keine Ressourcen. Es unterdrückt nicht einmal die Abschlüsse, da die SQLCommand Constructor macht das.
Theoretisch könnte Microsoft die Implementierung ändern, um eine nicht verwaltete Ressource zu halten, aber ich würde hoffen, dass sie mit einer API herauskommen würden, die das beseitigt Component
Basisklasse lange bevor sie das tun würden.
Meiner Meinung nach rufen Sie an Dispose
für beide SqlConnection
und SqlCommand
ist eine gute Praxis, verwenden Sie den folgenden Code
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
try{
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
}
catch(Exception ex){ //Log exception according to your own way
throw;
}
finally{
command.Dispose();
connection.Close();
connection.Dispose();
}