Keine Möglichkeit, SqlConnection zu schließen

Ich weiß, das ist eine alte Frage. Tausende von Aussagen auf Google sagen, Connection will be closed in Dispose() . Doch wer hat das wirklich verstanden?

Ich habe festgestellt, dass eine SqlConnection keine Möglichkeit ist zu schließen . Ich habe ein einfaches Programm (mit Zeilennummer links).

  class Program { static void Main(string[] args) 1 { 2 var connectionString = "Data Source=localhost;Initial Catalog=master;Integrated Security=SSPI;"; 3 using (var conn = new SqlConnection(connectionString)) 5 { 6 using (var cmd = new SqlCommand("create table #mytable(col1 int);", conn)) 7 { 8 conn.Open(); 9 cmd.ExecuteNonQuery(); 10 } 11 conn.Close(); 12 conn.Dispose(); 13 } 14 GC.Collect(); 15 } } 

Und ich habe eine T-SQL-statement zur Überprüfung der aktiven Verbindung

 exec sp_who2 

Ich trat Zeile für Zeile mit dem Debugger, mittlerweile habe ich die aktive Verbindung mit sp_who2 überprüft.

Jeder erwartet, dass die Verbindung auf Linie 11 geschlossen werden soll. Richtig? Allerdings ist die Verbindung nach Zeile 11 im sleep .

Okay, manuell entsorgen auf der nächsten Zeile. Aber nach Zeile 12 ist die Verbindung noch im sleep .

Okay, nächste Zeile ist die Selbstentsorgung. Aber nach Zeile 13 ist die Verbindung noch im sleep .

Okay, es kann mit dem GC . Also habe ich explizit GC.Collect() , um zu versuchen, das conn object zu sammeln. Aber nach Zeile 14 ist die Verbindung noch im sleep .

Die Verbindung ist nach Zeile 15 geschlossen . Das bedeutet das Ende des Programms.

Im obigen Programm wird eine #mytable erstellt. Allerdings wird die Temp-Tabelle nur fallen gelassen, wenn die Verbindung geschlossen ist. Das Problem, dem wir gegenüberstehen, ist too many temp tables are in the database . (Ja, ich weiß, dass Temp-Tische nach Gebrauch fallen gelassen werden sollten.)

Ich habe auch versucht

  1. Verwenden Sie { } , um einen neuen Bereich zu erstellen, um die Verbindung zu wickeln. Das Ergebnis ist das gleiche.

  2. Erstellen Sie einen neuen Thread, um eine Verbindung zum DB-server herzustellen. Das Ergebnis ist auch das gleiche.

  3. benutze while(true) { Thread.Sleep(1000); GC.Collect(); } while(true) { Thread.Sleep(1000); GC.Collect(); } while(true) { Thread.Sleep(1000); GC.Collect(); } am Ende der Main Methode. Das Ergebnis ist auch das gleiche.

Keiner von ihnen kann die SqlConnection schließen. Wie schließt man eine Verbindung?

Verbindungspooling in ADO.NET ist standardmäßig aktiviert. Dies bedeutet, dass, wenn Sie "entsorgen" Ihre Verbindung, sind Sie nur wieder in den Pool. Wenn du das Programm beendest, wirst du offensichtlich endlich alles aus dem Pool freigeben. Wenn du das vermeiden willst, musst du das Verbindungspaket ausschalten.

Um zu deaktivieren, füge das Pooling=false Argument zu deiner Verbindungszeichenfolge hinzu:

 var connection = new SqlConnection( @"Data Source=(local)\SQLEXPRESS;Initial Catalog=TEST;Integrated " + "Security=SSPI;Pooling=false;");