C# ADO.NET: Aufruf von gespeicherten Prozeduren und SqlDataReader
Aufrufen von SQL‑Server‑gespeicherten Prozeduren und Streaming‑Lesen von Abfrageergebnissen mit SqlDataReader, wichtige Kernpunkte:
SqlCommand.CommandType = CommandType.StoredProcedurekennzeichnet die Ausführung einer gespeicherten Prozedur- Übergeben von Parametern für gespeicherte Prozeduren mit
SqlParameter ExecuteReader(CommandBehavior.CloseConnection)zum Einlesen des Datenstroms- SqlDataReader ist ein vorwärtsgerichteter, schreibgeschützter Stream‑Reader und muss nach der Nutzung unbedingt geschlossen werden
Definition der gespeicherten Prozedur
Sie müssen die gespeicherte Prozedur zuerst in der Datenbank anlegen, bevor Sie sie aufrufen können.
create proc myProc
@id int
as
select * from [dbo].[Article] where id>@id
go
-- Testaufruf
exec myProc @id=5Code-Sprache: JavaScript (javascript)
Dieser Code akzeptiert den Parameter @id und liest alle Datensätze aus der Tabelle Article, deren id größer als der übergebene Wert ist.
Aufruf gespeicherter Prozeduren in C#
Mit ExecuteReader erhalten Sie einen SqlDataReader, über den Sie mehrere Datensätze einlesen können.
string connectionString = "Data Source=.;Initial Catalog=db;Integrated Security=SSPI;";
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = conn;
sqlCom.CommandText = "myProc";
sqlCom.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter("@id", SqlDbType.Int, 8);
param.Value = 4;
param.Direction = ParameterDirection.Input;
sqlCom.Parameters.Add(param);
SqlDataReader reader = sqlCom.ExecuteReader(CommandBehavior.CloseConnection);
StringBuilder sb = new StringBuilder();
while (reader.Read())
{
sb.AppendLine(reader[0] + "-" + reader[1]);
}
reader.Close();
MessageBox.Show(sb.ToString());
}Code-Sprache: C# (cs)
Ressourcenfreigabe des Readers mit using, um Ressourcenlecks zu vermeiden
string connectionString = "Data Source=.;Initial Catalog=db;Integrated Security=SSPI;";
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand sqlCom = new SqlCommand("myProc", conn))
{
sqlCom.CommandType = CommandType.StoredProcedure;//gibt an, dass es sich um eine gespeicherte Prozedur handelt
// Eingabeparameter hinzufügen
sqlCom.Parameters.Add("@id", SqlDbType.Int).Value = 4;
// CommandBehavior.CloseConnection: Verbindung wird automatisch geschlossen, sobald der Reader geschlossen wird
using (SqlDataReader reader = sqlCom.ExecuteReader(CommandBehavior.CloseConnection))
{
StringBuilder sb = new StringBuilder();
while (reader.Read())
{
// reader[0] erste Spalte, reader[1] zweite Spalte; alternativ reader["Spaltenname"] möglich
sb.AppendLine($"{reader[0]}-{reader[1]}");
}
MessageBox.Show(sb.ToString());
}
// Ein manueller Aufruf von reader.Close() ist nicht nötig; using gibt Ressourcen automatisch frei
}
}Code-Sprache: C# (cs)
Die drei Enumerationswerte von CommandType
CommandType.Text: Ausführen normaler SQL‑AnweisungenCommandType.StoredProcedure: Ausführen gespeicherter ProzedurenCommandType.TableDirect: Direktes Einlesen einer Datentabelle
Wenn Sie
StoredProcedurenicht festlegen, behandelt das Programm den Prozedurnamen wie eine normale SQL‑Anweisung und löst einen Fehler aus!
Parameterrichtungen bei SqlParameter
ParameterDirection.Input: Eingabeparameter (Wertübergabe, am häufigsten verwendet)ParameterDirection.Output: AusgabeparameterParameterDirection.InputOutput: Bidirektionaler Ein‑ und AusgabeparameterParameterDirection.ReturnValue: Rückgabewert der gespeicherten Prozedur
Funktion von CommandBehavior.CloseConnection
Wird bei SqlDataReader die Methode Close() aufgerufen oder das Objekt freigegeben, wird die zugehörige SqlConnection automatisch geschlossen.
Einsatzfall: Eine Methode gibt ein Reader‑Objekt zurück; die Verbindung wird automatisch zurückgegeben, sobald der Aufrufer das Einlesen abgeschlossen hat.
Wichtige Eigenschaften von SqlDataReader
- Vorwärts‑ und schreibgeschützt: Nur vorwärts traversieren mit
Read(), kein Zurückspringen und keine Datenänderung möglich - Verbindung wird belegt: Solange der Reader geöffnet ist, kann die Datenbankverbindung keine weiteren Operationen ausführen
- Ressourcen müssen freigegeben werden: Entweder manueller Aufruf von
reader.Close()oder vorzugsweise automatische Freigabe überusing - Zwei Varianten zum Spaltenzugriff:
csharp reader[0]; // Zugriff über Index reader["Title"]; // Zugriff über Feldname (bessere Lesbarkeit)
Wichtige Hinweise
- Vergessen,
CommandType.StoredProcedurezu setzen → Ausführungsfehler - Groß‑/Kleinschreibung oder Schreibweise von Parametern stimmen nicht mit der gespeicherten Prozedur überein → Parameter passen nicht
- Reader wird nicht geschlossen → Datenbankverbindung bleibt belegt, der Verbindungspool läuft leer
- Neue Datenbankabfrage innerhalb von
while(reader.Read()): Eine Verbindung unterstützt nicht mehrere gleichzeitig aktive Reader - Fehlende Parameter oder falsche Parametertypen bei der gespeicherten Prozedur → Laufzeitfehler
Vergleich
| Ausführmethode | Einsatzszenario | Rückgabeobjekt |
|---|---|---|
| ExecuteNonQuery | Gespeicherte Prozeduren für Einfügen, Ändern, Löschen | int Anzahl betroffener Zeilen |
| ExecuteScalar | Rückgabe einer einzelnen Zeile und Spalte (Aggregatabfragen) | object |
| ExecuteReader | Mehrzeilige Datensätze zurückgeben | SqlDataReader (Streaming‑Lesevorgang) |
SqlDataReader