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.
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
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. –
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. –