2008-09-13 14 views
48

Kann ich diesen Ansatz effizient nutzen?SqlCommand.Dispose schließt die Verbindung?

using(SqlCommand cmd = new SqlCommand("GetSomething", new SqlConnection(Config.ConnectionString)) 
{ 
    cmd.Connection.Open(); 
    // set up parameters and CommandType to StoredProcedure etc. etc. 
    cmd.ExecuteNonQuery(); 
} 

Meine Sorge ist: Wird die Dispose-Methode des SqlCommand (die aufgerufen wird, wenn die Verwendung von Block Verlassen) schließt das darunter liegende Objekt SqlConnection oder nicht?

+0

Nachdem der SqlCommand-com freigegeben wurde, wird seine Connection-Instanz nicht mehr gestartet (wird von nichts verwendet). Sobald die GarbageCollector die SqlConnection-Instanz abgeschlossen hat, wird die Verbindung nicht getrennt? Ich denke es wird sein, denn Verbindung wird hier nur mit cmd referenziert. – mecek

+0

Nun, in diesem Fall, @Mecek, wird der Speicher härter befreit, da er durch die Finalisierung geht, die ihn von gen0 zu gen1 befördert, denke ich. –

Antwort

97

Nein, die Entsorgung der SqlCommand wird die Verbindung nicht beeinflussen. Ein besserer Ansatz wäre es, auch als auch die SqlConnection in einem mit Block zu wickeln:

using (SqlConnection conn = new SqlConnection(connstring)) 
{ 
    conn.Open(); 
    using (SqlCommand cmd = new SqlCommand(cmdstring, conn)) 
    { 
     cmd.ExecuteNonQuery(); 
    } 
} 

Andernfalls wird die Verbindung ist unverändert durch die Tatsache, dass ein Befehl, der benutzt es wurde angeordnet (vielleicht ist das, was Sie wollen?). Aber bedenken Sie, dass auch eine Verbindung entsorgt werden sollte, und wahrscheinlich wichtiger als ein Befehl zu entsorgen.

EDIT:

I dieses gerade getestet:

SqlConnection conn = new SqlConnection(connstring); 
conn.Open(); 

using (SqlCommand cmd = new SqlCommand("select field from table where fieldid = 1", conn)) 
{ 
    Console.WriteLine(cmd.ExecuteScalar().ToString()); 
} 

using (SqlCommand cmd = new SqlCommand("select field from table where fieldid = 2", conn)) 
{ 
    Console.WriteLine(cmd.ExecuteScalar().ToString()); 
} 

conn.Dispose(); 

Der erste Befehl angeordnet wurde, wenn die Verwendung von Block verlassen wurde. Die Verbindung war noch offen und gut für den zweiten Befehl.

Also entsorgt der Befehl definitiv nicht die Verbindung, die er benutzte.

+0

Sie müssen die Verbindung vor dem Erstellen des Befehls nicht öffnen, oder? Machen Sie es sich ein wenig sauberer wie folgt aus: mit (SqlConnection conn = new SqlConnection (connString)) mit (SqlCommand cmd = new SqlCommand (cmdstring, conn)) { conn.Open(); cmd.ExecuteNonQuery(); conn.Close(); } –

+0

Ich denke, die Formatierung nicht kleben ... aber im Grunde zusammen die Verwendung von Anweisungen zusammen und loswerden eine Ebene der Verschachtelung.(Wenn Sie möchten) –

+7

Der Punkt des Beispiels ist nicht, eine einfachere Syntax zu zeigen, sondern zu demonstrieren, dass beide SqlCommands mit der gleichen Verbindung verwendet werden können und dann entsorgt werden können, ohne die Verbindung zu entsorgen. Die Verbindung muss geöffnet und zweimal verwendet werden, um dies zu demonstrieren (siehe Originalfrage). –

10

SqlCommand.Dispose wird nicht ausreichen, da viele SqlCommand (s) dieselbe SqlConnection (re) verwenden können. Zentriere deinen Fokus auf die SqlConnection.

-10

Ich benutze dieses Muster. Ich habe diese private Methode irgendwo in meiner App:

private void DisposeCommand(SqlCommand cmd) 
{ 
    try 
    { 
     if (cmd != null) 
     { 
      if (cmd.Connection != null) 
      { 
       cmd.Connection.Close(); 
       cmd.Connection.Dispose(); 
      } 
      cmd.Dispose(); 
     } 
    } 
    catch { } //don't blow up 
} 

Dann immer SQL-Befehle und Verbindungen in einem try-Block erstellen I (aber ohne in einem mit Block gewickelt ist) und hat immer eine finally-Block als:

Das Verbindungsobjekt, das eine Eigenschaft des Befehlsobjekts ist, macht einen Benutzungsblock in dieser Situation unpassend - aber dieses Muster erledigt die Aufgabe, ohne den Code zu überladen.

+0

Dies setzt voraus, dass Sie Ihre Verbindung nur einmal für diesen einzelnen Befehl verwenden. Daher müssen Sie eine neue Verbindung erstellen und sie jedes Mal öffnen, wenn Sie einen neuen Befehl ausführen müssen. Beim Erstellen und Öffnen von Verbindungen ist viel Aufwand erforderlich. –

+8

In meinen Augen ist das ein hässlicher Code, und es wäre viel sauberer, einfach die 'using'-Anweisung zu verwenden, die automatisch den Befehl entsorgt. – KristianB

+2

Downvoting - unnötige und weniger effektive Reimplementierung der 'using' Methode. – NickG