Konfigurieren von Parametern
Gilt für: .NET Framework .NET .NET Standard
Befehlsobjekte verwenden Parameter, um Werte an SQL-Anweisungen oder gespeicherte Prozeduren zu übergeben, und ermöglichen so Typüberprüfungen und Validierungen. Im Unterschied zu Befehlstext wird die Parametereingabe als Literalwert und nicht als ausführbarer Code behandelt. Dieses Verhalten hilft beim Schutz vor "SQL Injection"-Angriffen, bei denen ein Angreifer einen Befehl einfügt, der die Sicherheit auf dem Server in eine SQL-Anweisung kompromittiert.
Parametrisierte Befehle können außerdem die Leistung bei der Abfrageausführung verbessern, da sie den Datenbankserver dabei unterstützen, den eingehenden Befehl mit dem richtigen zwischengespeicherten Abfrageplan abzugleichen. Weitere Informationen finden Sie unter Zwischenspeichern und Wiederverwenden von Ausführungsplänen und Parameter und Wiederverwendung von Ausführungsplänen. Parametrisierte Befehle sind aber nicht nur aus Sicherheits- und Leistungsgründen vorteilhaft, sondern sie stellen auch eine bequeme Methode zum Organisieren von Werten dar, die an eine Datenquelle übergeben werden.
Ein DbParameter -Objekt kann mithilfe des zugehörigen Konstruktors erstellt werden, oder es wird durch Aufrufen der DbParameterCollection -Methode der Add
-Auflistung zur DbParameterCollection hinzugefügt. Die Add
-Methode verwendet als Eingabe je nach Datenanbieter Konstruktorargumente oder ein vorhandenes Parameterobjekt.
Bereitstellen der ParameterDirection-Eigenschaft
Beim Hinzufügen von Parametern müssen Sie für alle Parameter, die keine Eingabeparameter sind, die ParameterDirection -Eigenschaft bereitstellen. Die folgende Tabelle zeigt die ParameterDirection
-Werte, die Sie mit der ParameterDirection -Enumeration verwenden können.
Membername | Beschreibung |
---|---|
Input | Der Parameter ist ein Eingabeparameter. Dies ist der Standardwert. |
InputOutput | Der Parameter kann sowohl für die Eingabe als auch für die Ausgabe verwendet werden. |
Output | Der Parameter ist ein Ausgabeparameter. |
ReturnValue | Der Parameter steht für einen Eingabewert aus einem Vorgang, wie z. B. einer gespeicherten Prozedur, einer integrierten Funktion oder einer benutzerdefinierten Funktion. |
Arbeiten mit Parameterplatzhaltern
Die Syntax für Parameterplatzhalter ist abhängig von der jeweiligen Datenquelle. Beim Microsoft SqlClient-Datenanbieter für SQL Server werden die Benennung und Angabe von Parametern und Parameterplatzhaltern unterschiedlich behandelt. Der SqlClient-Datenanbieter verwendet benannte Parameter im Format @parametername
.
Angeben von Parameterdatentypen
Der Microsoft SqlClient-Datenanbieter für SQL Server verwendet für Parameter einen spezifischen Datentyp. Beim Angeben des Typs wird der Wert des Parameter
-Objekts in den Typ des Microsoft SqlClient-Datenanbieters für SQL Server konvertiert, bevor er an die Datenquelle übergeben wird. Der Typ eines Parameter
kann auch in generischer Form angegeben werden, indem die DbType
-Eigenschaft des Parameter
-Objekts auf einen bestimmten DbTypefestgelegt wird.
Der Typ eines Parameter
-Objekts des Microsoft SqlClient-Datenanbieters für SQL Server wird vom .NET Framework-Typ des Value
des Parameter
-Objekts oder vom DbType
des Parameter
-Objekts abgeleitet. Die folgende Tabelle zeigt den abgeleiteten Parameter
-Typ basierend auf dem als Parameter
-Wert übergebenen Objekt oder dem angegebenen DbType
.
.NET-Typ | DbType | SqlDbType |
---|---|---|
Boolean | Boolean |
Bit |
Byte | Byte |
TinyInt |
byte[] |
Binary |
VarBinary . Diese implizite Konvertierung schlägt fehl, wenn das Bytearray größer als die maximal zulässige Größe für den Typ VarBinary (8000 Byte) ist. Legen Sie für Bytearrays mit mehr als 8.000 Byte explizit den SqlDbType fest. |
Char | Das Ableiten eines SqlDbType aus char wird nicht unterstützt. | |
DateTime | DateTime |
DateTime |
DateTimeOffset | DateTimeOffset |
DateTimeOffset in SQL Server 2008. Das Ableiten eines SqlDbType aus DateTimeOffset wird erst ab SQL Server 2008 unterstützt. |
Decimal | Decimal |
Decimal |
Double | Double |
Float |
Single | Single |
Real |
Guid | Guid |
UniqueIdentifier |
Int16 | Int16 |
SmallInt |
Int32 | Int32 |
Int |
Int64 | Int64 |
BigInt |
Object | Object |
Variant |
String | String |
NVarChar . Diese implizite Konvertierung schlägt fehl, wenn die Zeichenfolge größer als die maximal zulässige Größe für den Typ NVarChar (4000 Zeichen) ist. Legen Sie für Zeichenfolgen mit mehr als 4000 Zeichen explizit SqlDbTypefest. |
TimeSpan | Time |
Time in SQL Server 2008. Das Ableiten eines SqlDbType aus TimeSpan wird erst ab SQL Server 2008 unterstützt. |
UInt16 | UInt16 |
Das Ableiten eines SqlDbType aus UInt16 wird nicht unterstützt. |
UInt32 | UInt32 |
Das Ableiten eines SqlDbType aus UInt32 wird nicht unterstützt. |
UInt64 | UInt64 |
Das Ableiten eines SqlDbType aus UInt64 wird nicht unterstützt. |
AnsiString |
VarChar |
|
AnsiStringFixedLength |
Char |
|
Currency |
Money |
|
Date |
Date in SQL Server 2008. Das Ableiten eines SqlDbType aus Date wird erst ab SQL Server 2008 unterstützt. |
|
SByte |
Das Ableiten eines SqlDbType aus SByte wird nicht unterstützt. |
|
StringFixedLength |
NChar |
|
Time |
Time in SQL Server 2008. Das Ableiten eines SqlDbType aus Time wird erst ab SQL Server 2008 unterstützt. |
|
VarNumeric |
Das Ableiten eines SqlDbType aus VarNumeric wird nicht unterstützt. |
|
Benutzerdefinierter Typ (ein Objekt mit SqlUserDefinedAggregateAttribute) | SqlClient gibt immer ein Objekt zurück | SqlDbType.Udt , wenn SqlUserDefinedTypeAttribute vorhanden ist. Anderenfalls Variant |
Hinweis
Beim Konvertieren von "decimal" in einen anderen Typ erhalten Sie nur eine annähernde Entsprechung, da der Wert auf die nächste Ganzzahl abgerundet wird. Wenn das Ergebnis der Konvertierung im Zieltyp nicht darstellbar ist, wird eine OverflowException ausgelöst.
Hinweis
Wenn Sie einen NULL-Parameterwert an den Server senden, müssen Sie DBNull und nicht null
(in Visual Basic Nothing
)+++ angeben. Der NULL-Wert im System ist ein leeres Objekt, das über keinen Wert verfügt. DBNull wird zur Darstellung von NULL-Werten verwendet.
Ableiten von Parameterinformationen
Parameter können auch mit der DbCommandBuilder
-Klasse aus einer gespeicherten Prozedur abgeleitet werden. Die SqlCommandBuilder
-Klasse stellt eine statische Methode (DeriveParameters
) bereit, die die Parameterauflistung eines Befehlsobjekts, das Parameterinformationen aus einer gespeicherten Prozedur verwendet, automatisch füllt. DeriveParameters
überschreibt alle vorhandenen Parameterinformationen für den Befehl.
Hinweis
Das Ableiten von Parameterinformationen geht mit einem Leistungsverlust einher, weil zum Abrufen der Informationen ein zusätzlicher Roundtrip durch die Datenquelle erforderlich ist. Wenn die Parameterinformationen zur Entwurfszeit bekannt sind, können Sie die Leistung der Anwendung verbessern, indem Sie die Parameter explizit festlegen.
Weitere Informationen finden Sie unter Generieren von Befehlen mit CommandBuilder-Objekten.
Verwenden von Parametern mit einem SqlCommand und einer gespeicherten Prozedur
Gespeicherte Prozeduren bieten zahlreiche Vorteile in datengesteuerten Anwendungen. Mit gespeicherten Prozeduren können Datenbankoperationen in einem einzelnen Befehl zusammengefasst, für eine überzeugende Leistung optimiert und mit zusätzlicher Sicherheit ausgestattet werden. Obwohl eine gespeicherte Prozedur aufgerufen werden kann, indem der Name der gespeicherten Prozedur gefolgt von Parameterargumenten als SQL-Anweisung übergeben wird, können Sie mithilfe der Parameters Auflistung des ADO.NET-Objekts DbCommand gespeicherte Prozedurparameter expliziter definieren und auf Ausgabeparameter und Rückgabewerte zugreifen.
Hinweis
Parametrisierte Anweisungen werden auf dem Server mit sp_executesql,
ausgeführt, sodass die Wiederverwendung von Abfrageplänen möglich ist. Lokale Cursor oder Variablen im sp_executesql
-Batch sind für den Batch, der sp_executesql
aufruft, nicht sichtbar. Änderungen am Datenbankkontext sind nur bis zum Ende der sp_executesql
-Anweisung gültig. Weitere Informationen finden Sie unter sp_executesql (Transact-SQL).
Wenn Sie Parameter mit einem SqlCommand verwenden, um eine gespeicherte SQL Server-Prozedur auszuführen, müssen die der Parameters -Auflistung hinzugefügten Parameternamen mit den Namen der Parametermarkierungen in der gespeicherten Prozedur übereinstimmen. Der Microsoft SqlClient-Datenanbieter für SQL Server unterstützt nicht den Fragezeichenplatzhalter (?), um Parameter an eine SQL-Anweisung oder eine gespeicherte Prozedur zu übergeben. Er behandelt die Parameter in der gespeicherten Prozedur als benannte Parameter und sucht nach den entsprechenden Parametermarkierungen. Nehmen wir z. B. an, die gespeicherte Prozedur CustOrderHist
ist mit einem Parameter mit dem Namen @CustomerID
definiert. Wenn Ihr Code die gespeicherte Prozedur ausführt, muss er ebenfalls einen Parameter mit dem Namen @CustomerID
verwenden.
CREATE PROCEDURE dbo.CustOrderHist @CustomerID varchar(5)
Beispiel
Dieses Beispiel zeigt, wie Sie eine gespeicherte SQL Server-Prozedur in der Northwind
-Beispieldatenbank aufrufen können. Der Name der gespeicherten Prozedur ist dbo.SalesByCategory
, und die Prozedur besitzt einen Eingabeparameter mit dem Namen @CategoryName
und dem Datentyp nvarchar(15)
. Der Code erstellt eine neue SqlConnection innerhalb eines verwendeten Blocks, sodass die Verbindung nach dem Ende der Prozedur verworfen wird. Es werden die Objekte SqlCommand und SqlParameter erstellt, und deren Eigenschaften werden festgelegt. Ein SqlDataReader führt den SqlCommand
aus und gibt den Resultset aus der gespeicherten Prozedur zurück, wobei die Ausgabe im Konsolenfenster angezeigt wird.
Hinweis
Statt die Objekte SqlCommand
und SqlParameter
zu erstellen und dann die Eigenschaften in separaten Anweisungen festzulegen, können Sie auch mit einem der überladenen Konstruktoren mehrere Eigenschaften in einer einzigen Anweisung festlegen.
static void GetSalesByCategory(string connectionString,
string categoryName)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
// Create the command and set its properties.
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "SalesByCategory";
command.CommandType = CommandType.StoredProcedure;
// Add the input parameter and set its properties.
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@CategoryName";
parameter.SqlDbType = SqlDbType.NVarChar;
parameter.Direction = ParameterDirection.Input;
parameter.Value = categoryName;
// Add the parameter to the Parameters collection.
command.Parameters.Add(parameter);
// Open the connection and execute the reader.
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine("{0}: {1:C}", reader[0], reader[1]);
}
}
else
{
Console.WriteLine("No rows found.");
}
reader.Close();
}
}
}