2009-05-26 8 views
6

Was ist die beste Vorgehensweise für SQL-Verbindungen?Verwalten von SQL Server-Verbindungen

Derzeit bin ich folgend:

using (SqlConnection sqlConn = new SqlConnection(CONNECTIONSTRING)) 
{ 
    sqlConn.Open(); 
    // DB CODE GOES HERE 
} 

Ich habe gelesen, dass dies eine sehr effektive Art und Weise SQL-Verbindungen zu tun. Standardmäßig ist das SQL-Pooling aktiv, so wie ich es verstehe ist, dass, wenn der using-Code endet, das SqlConnection-Objekt geschlossen und entsorgt wird, aber die eigentliche Verbindung zur DB in den SQL-Verbindungspool eingetragen wird. Liege ich damit falsch?

Antwort

13

Das ist das meiste davon. Einige zusätzliche Punkte zu beachten:

  • Woher bekommen Sie Ihre Verbindungszeichenfolge? Sie möchten nicht, dass das überall hart-kodierte und Sie müssen es möglicherweise sichern.
  • Sie haben oft andere Objekte als auch zu erstellen, bevor Sie wirklich die Verbindung verwenden (SqlCommand, SqlParameter, DataSet, SqlDataAdapter) und Sie so lange wie möglich warten wollen die Verbindung zu öffnen. Das vollständige Muster muss dies berücksichtigen.
  • Sie möchten sicherstellen, dass der Datenbankzugriff in eine eigene Datenschichtklasse oder -baugruppe erzwungen wird. Es ist also üblich, dies als einen privaten Funktionsaufruf auszudrücken:

.

private static string connectionString = "load from encrypted config file"; 
private SqlConnection getConnection() 
{ 
    return new SqlConnection(connectionString); 
} 

Und dann Ihre Probe wie folgt schreiben:

using (SqlConnection sqlConn = getConnection()) 
{ 
    // create command and add parameters 

    // open the connection 
    sqlConn.Open(); 

    // run the command 
} 

Diese Probe nur in der Datenzugriffsklasse bestehen kann. Eine Alternative ist es, es internal zu markieren und die Datenschicht über eine gesamte Baugruppe zu verteilen. Die Hauptsache ist, dass eine saubere Trennung Ihres Datenbankcodes strikt durchgesetzt wird.

Eine echte Implementierung könnte wie folgt aussehen:

public IEnumerable<IDataRecord> GetSomeData(string filter) 
{ 
    string sql = "SELECT * FROM [SomeTable] WHERE [SomeColumn] LIKE @Filter + '%'"; 

    using (SqlConnection cn = getConnection()) 
    using (SqlCommand cmd = new SqlCommand(sql, cn)) 
    { 
     cmd.Parameters.Add("@Filter", SqlDbType.NVarChar, 255).Value = filter; 
     cn.Open(); 

     using (IDataReader rdr = cmd.ExecuteReader()) 
     { 
      while (rdr.Read()) 
      { 
       yield return (IDataRecord)rdr; 
      } 
     } 
    } 
} 

Hinweis, dass ich auch in der Lage die Schaffung der cn und cmd Objekte zu „stapeln“ und damit Verschachtelung reduzieren und nur einen Umfang Block erstellen.

Schließlich ein Wort der Vorsicht über die Verwendung der yield return Code in diesem spezifischen Beispiel. Wenn Sie die Methode aufrufen und Ihre DataBinding oder andere Verwendung nicht sofort abschließen, kann die Verbindung lange geöffnet bleiben. Ein Beispiel hierfür ist die Verwendung einer Datenquelle im Ereignis Load einer ASP.NET-Seite. Da das eigentliche Datenbindungsereignis erst später auftritt, können Sie die Verbindung viel länger offen halten, als Sie benötigen.

+0

Punkt 1: Ich speichere meine Verbindungszeichenfolgen im Abschnitt der app/web.config. Punkt 2: Ist das etwas, über das ich mir Gedanken machen sollte? Ich mache normalerweise SqlConnection, dann öffne es, dann erstelle ich meinen sqlCommand und nehme dann von dort aus. Punkt 3: Wir machen unseren gesamten DB-Zugriff von einer Klasse lib. Ich mag es nicht, DB-Zugriff von der Kernanwendung zu machen. Lohnt es sich, die Methode getConnection zu erstellen? – Neale

+0

Da Sie eine Klassenbibliothek für alle Datenbankzugriffe verwenden, ist es einfach, die Verbindungszeichenfolge in die Datei .config der Klasse lib und nicht in die .config-Datei einzufügen, die für die gesamte App global ist. Dies sollte gut genug sein, um eine saubere Datenschichttrennung zu erzwingen, aber gleichzeitig gibt es keinen Grund, die Methode auch öffentlich zu machen. Das sollte die Punkte 1 und 3 betreffen. Für Punkt 2 tut es wahrscheinlich nichts weh, es für eine oder zwei zusätzliche Zeilen offen zu haben, aber es hilft auch nicht. Ich bearbeite einen anderen Grund, warum du es vielleicht so machen willst. –

+0

Ihr 'yield return' Beispiel ist leicht irreführend. Eine Funktion, die um 'yield return' aufgebaut ist, startet erst beim ersten Aufruf von 'MoveNext()' auf dem 'IEnumerator'. Selbst wenn Sie die Funktion aufrufen, wird die Verbindung nicht geöffnet, bis Sie mit dem Iterieren der Ergebnisse beginnen. –

1

Ihr Verständnis der Verwendung ist korrekt, und diese Methode der Verwendung ist die empfohlene Vorgehensweise. Sie können auch in Ihrem Code call aufrufen.

+1

Danke. Die Art und Weise, dass ich es verstehe, dass wenn die "Verwendung" beendet ist und das SqlConnection.Dispose(); das ruft ultimate SqlConnection.Close() – Neale

+0

Ihr Verständnis von "Verwendung" ist ebenfalls korrekt. –

+0

@Neale - Ja, SqlConnection.Dispose() wird Schließen aufrufen, wenn es erforderlich ist. Wenn die Verbindung bereits geschlossen wurde, gibt sie das Handle einfach an den ado.net-Provider zurück, der es dann freigibt, es in einen Pool zu legen oder es tatsächlich zu schließen. –

2

Microsofts Patterns and Practices Bibliotheken sind ein ausgezeichneter Ansatz für die Handhabung der Datenbankkonnektivität. Die Bibliotheken kapseln die meisten Mechanismen beim Öffnen einer Verbindung ein, was wiederum Ihr Leben einfacher macht.

0

Auch: Geöffnet spät, früh zu schließen.

Öffnen Sie die Verbindung erst, wenn vor dem Aufrufen der Datenbank keine weiteren Schritte mehr möglich sind. Und schließen Sie die Verbindung, sobald Sie fertig sind.