2009-10-12 12 views
5

die Methode Gegeben:Warum ist SqlConnection nicht entsorgt/geschlossen?

internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) 
{ 
    var dataset = new DataSet(); 

    SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb 
          ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) 
          : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"]); 
    SqlCommand sqlcmd = sqlc.CreateCommand(); 
    sqlcmd.CommandText = commandText; 
    var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); 
    adapter.Fill(dataset); 


    return dataset; 
} 

Warum SQLC (der SqlConnection) nicht angeordnet sind/schließen, nachdem der Rufmethode außerhalb des Gültigkeitsbereichs oder SQLC geht keine weiteren Artikeln?

EDIT 1: Auch sie sich mit der Verpackung, kann ich immer noch die Verbindung zu sehen mit (I Connection Pooling ausgeschaltet haben):

SELECT DB_NAME(dbid) as 'Database Name', 
COUNT(dbid) as 'Total Connections' 
FROM sys.sysprocesses WITH (nolock) 
WHERE dbid > 0 
GROUP BY dbid 

EDIT 2: Haben Sie etwas mehr Debuggen mit Hilfe, die ich von hier bekommen habe - die Antwort war, dass jemand eine Verbindungszeichenfolge mit Pooling fest codiert hat. Danke für all die Hilfe - wenn ich könnte, würde ich alle Antworten als Antworten markieren.

Antwort

19

C# 's Garbage Collection ist nicht deterministisch, aber die Sprache hat eine deterministische Struktur zur Entsorgung wie diese Ressource zur Verfügung stellen:

using (SqlConnection connection = new SqlConnection(...)) 
{ 
    // ... 
} 

Dies wird einen try/finally Block schaffen, dass das Verbindungsobjekt zu gewährleisten, ist so angeordnet, unabhängig davon, was passiert in der Methode. Sie sollten wirklich alle Instanzen von Typen, die IDisposable implementieren, in einen using-Block wie diesen einbinden, da dies eine verantwortungsvolle Ressourcenverwaltung (von nicht verwalteten Ressourcen wie Datenbankverbindungen) gewährleistet und Ihnen die deterministische Kontrolle bietet, nach der Sie suchen.

+0

+1 für saubere Antwort, besser als meins. –

1

Es wird sein, nach der Garbage Collection ist es Arbeit. Gleiches gilt für das Öffnen eines Dateistreams zum Schreiben, ohne es zu schließen. Es könnte "gesperrt" werden, obwohl die Codes nicht mehr gültig waren.

2

Da C# eine Garbage Collection-Sprache ist und die Garbage Collection nicht deterministisch ist. Tatsache ist, dass Ihre sqlconnection entsorgt wird. Sie können nur nicht wählen wann.

SQL-Verbindungen sind eine begrenzte Ressource, und es ist leicht möglich, dass Sie genug von ihnen erstellen, um zu enden. Schreiben Sie es wie folgt statt:

internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) 
{ 
    var dataset = new DataSet(); 

    using (SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb 
          ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) 
          : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"])) 
    using (SqlCommand sqlcmd = sqlc.CreateCommand()) 
    { 
     sqlcmd.CommandText = commandText; 
     var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); 
     adapter.Fill(dataset); 

    } 
    return dataset; 
} 

Obwohl in diesem Fall, dass Sie damit durchkommen könnte, weil die .Fill() method is a strange beast:

Wenn die IDbConnection vor Fill geschlossen wird aufgerufen wird, wird es geöffnet zum Abrufen von Daten und dann geschlossen.

Das bedeutet also, dass der Datenadapter sich darum kümmern sollte, wenn Sie mit einer geschlossenen Verbindung beginnen. Ich bin viel mehr besorgt, dass Sie Ihren SQL-Befehl als einfache Zeichenfolge übergeben. In Ihren Abfragen müssen von Zeit zu Zeit Benutzerparameter vorhanden sein. Dies bedeutet, dass Sie diese Daten direkt in die Befehlszeichenfolge verketten. Tu das nicht !! Verwenden Sie stattdessen die Paramters-Auflistung von SqlCommand.

1

Ich glaube, es hat etwas mit SqlConnection Pooling zu tun.Was Sie tun können, und wir oft bei der Arbeit tun, ist den gesamten Aufruf in eine using-Anweisung zu wickeln, die dazu führt, dass er die dispose() -Methode aufruft, die Verbindung schließt und das Objekt entsorgt

Sie könnten dann etwas tun dies stattdessen:

1

Ich stimme mit allen Antworten hier plus eine Verbindung kann ein breiterer Bereich als nur eine Methode sein. Wenn Sie Ihre bestehende Verbindung an verschiedenen Orten verwenden müssen, ändert sich das Szenario ein wenig. Rufen Sie immer Dispose für alle Objekte auf, die IDisposable implementieren, nachdem Sie sie nicht mehr verwenden. Dies ist eine gute Vorgehensweise, damit Sie nicht mit unbenutzten Objekten enden, die der Garbage Collector nicht entscheiden kann, was mit ihnen zu tun ist.

Verwandte Themen