Konfigurieren von Parametern und Parameterdatentypen (ADO.NET)
Aktualisiert: November 2007
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. Dies dient zum Schutz vor Angriffen per SQL-Injection, bei denen ein Angreifer einen Befehl, der die Sicherheit auf dem Server gefährdet, in eine SQL-Anweisung einschleust.
Parametrisierte Befehle können zudem die Leistung der Abfrage beschleunigen, da sie den Datenbankserver dabei unterstützen, einen eingehenden Befehl genau auf einen passenden gespeicherten Abfrageplan abszustimmen. Weitere Informationen finden Sie unter Zwischenspeichern und Wiederverwenden von Ausführungsplänen und Parameter und Wiederverwendung von Ausführungsplänen in der SQL-Onlinedokumentation. Parametrisierte Befehle sind jedoch 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 Add-Methode der DbParameterCollection-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 |
---|---|
Der Parameter ist ein Eingabeparameter. Dies ist der Standardwert. |
|
Der Parameter kann sowohl für die Eingabe als auch für die Ausgabe verwendet werden. |
|
Der Parameter ist ein Ausgabeparameter. |
|
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. Die .NET Framework-Datenanbieter handhaben die Benennung und das Angeben von Parametern und Parameterplatzhaltern unterschiedlich. Diese Syntax wird an eine bestimmte Datenquelle angepasst, wie in der folgenden Tabelle beschrieben.
Datenanbieter |
Syntax für Parameterbenennung |
---|---|
Verwendet benannte Parameter im Format @Parametername. |
|
Verwendet mit einem Fragezeichen (?) gekennzeichnete Positionsparametermarkierungen. |
|
Verwendet mit einem Fragezeichen (?) gekennzeichnete Positionsparametermarkierungen. |
|
Verwendet benannte Parameter im Format :Parametername (oder Parametername). |
Angeben von Parameterdatentypen
Der Datentyp eines Parameters ist abhängig vom .NET Framework-Datenanbieter. Durch Angabe des Typs wird der Wert von Parameter in den Typ des .NET Framework-Datenanbieters 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 DbType festgelegt wird.
Der .NET Framework-Datenanbietertyp eines Parameter-Objekts wird vom .NET Framework-Typ des Value des Parameter-Objekts oder vom DbType des Parameter-Objekts hergeleitet. Die folgende Tabelle zeigt den hergeleiteten Parameter-Typ basierend auf dem als Parameter-Wert übergebenen Objekt oder dem angegebenen DbType.
.NET Framework-Typ |
DbType |
SqlDbType |
OleDbType |
OdbcType |
OracleType |
---|---|---|---|---|---|
bool |
Boolean |
Bit |
Boolean |
Bit |
Byte |
byte |
Byte |
TinyInt |
UnsignedTinyInt |
TinyInt |
Byte |
byte[] |
Binary |
VarBinary. Diese implizite Konvertierung schlägt fehl, wenn das Bytearray größer als die maximal zulässige Größe eines VarBinary (8000 Byte) ist.Legen Sie für Bytearrays mit mehr als 8000 Byte explizit den SqlDbType fest. |
VarBinary |
Binary |
Raw |
char |
|
Das Herleiten eines SqlDbType aus "char" wird nicht unterstützt. |
Char |
Char |
Byte |
DateTime |
DateTime |
DateTime |
DBTimeStamp |
DateTime |
DateTime |
DateTimeOffset |
DateTimeOffset |
"DateTimeOffset" in SQL Server 2008. Das Herleiten eines SqlDbType aus DateTimeOffset wird erst ab SQL Server 2008 unterstützt. |
DateTime |
||
Dezimal |
Dezimal |
Dezimal |
Dezimal |
Numeric |
Number |
double |
Double |
Float |
Double |
Double |
Double |
float |
Single |
Real |
Single |
Real |
Float |
Guid |
Guid |
UniqueIdentifier |
Guid |
UniqueIdentifier |
Raw |
Int16 |
Int16 |
SmallInt |
SmallInt |
SmallInt |
Int16 |
Int32 |
Int32 |
Int |
Int |
Int |
Int32 |
Int64 |
Int64 |
BigInt |
BigInt |
BigInt |
Number |
object |
Object |
Variant |
Variant |
Das Herleiten von einem OdbcType von "Object" wird nicht unterstützt. |
Blob |
string |
String |
NVarChar. Diese implizite Konvertierung schlägt fehl, wenn die Zeichenfolge die maximale Länge eines NVarChar (4000 Zeichen) überschreitet. Legen Sie für Zeichenfolgen mit mehr als 4000 Zeichen den SqlDbType explizit fest. |
VarWChar |
NVarChar |
NVarChar |
TimeSpan |
Time |
"Time" in SQL Server 2008. Das Herleiten eines SqlDbType aus TimeSpan wird erst ab SQL Server 2008 unterstützt. |
DBTime |
Time |
DateTime |
UInt16 |
UInt16 |
Das Herleiten eines SqlDbType aus UInt16 wird nicht unterstützt. |
UnsignedSmallInt |
Int |
UInt16 |
UInt32 |
UInt32 |
Das Herleiten eines SqlDbType aus "UInt32" wird nicht unterstützt. |
UnsignedInt |
BigInt |
UInt32 |
UInt64 |
UInt64 |
Das Herleiten eines SqlDbType aus "UInt64" wird nicht unterstützt. |
UnsignedBigInt |
Numeric |
Number |
|
AnsiString |
VarChar |
VarChar |
VarChar |
VarChar |
|
AnsiStringFixedLength |
Char |
Char |
Char |
Char |
|
Currency |
Money |
Currency |
Das Herleiten eines OdbcType aus Currency wird nicht unterstützt. |
Number |
|
Date |
"Date" in SQL Server 2008. Das Herleiten eines SqlDbType aus Date wird erst ab SQL Server 2008 unterstützt. |
DBDate |
Date |
DateTime |
|
SByte |
Das Herleiten eines SqlDbType aus SByte wird nicht unterstützt. |
TinyInt |
Das Herleiten eines OdbcType aus "SByte" wird nicht unterstützt. |
SByte |
|
StringFixedLength |
NChar |
WChar |
NChar |
NChar |
|
Time |
"Time" in SQL Server 2008. Das Herleiten eines SqlDbType aus Time wird erst ab SQL Server 2008 unterstützt. |
DBTime |
Time |
DateTime |
|
VarNumeric |
Das Herleiten eines SqlDbType aus VarNumeric wird nicht unterstützt. |
VarNumeric |
Das Herleiten eines OdbcType aus "VarNumeric" wird nicht unterstützt. |
Number |
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, muss nicht null, sondern DBNull angegeben werden (Nothing in Visual Basic). Der NULL-Wert im System ist ein leeres Objekt ohne Wert. Zur Darstellung von NULL-Werten wird DBNull verwendet. Weitere Informationen zu NULL-Werten bei Datenbanken finden Sie unter Behandlung von NULL-Werten (ADO.NET). |
Ableiten von Parameterinformationen
Parameter können auch mit der DbCommandBuilder-Klasse aus einer gespeicherten Prozedur abgeleitet werden. Sowohl die SqlCommandBuilder-Klasse als auch die OleDbCommandBuilder-Klasse stellen die statische Methode DeriveParameters bereit, die automatisch die Parameterauflistung eines Befehlsobjekts füllt, das Parameterinformationen aus einer gespeicherten Prozedur verwendet. Beachten Sie, dass DeriveParameters alle vorhandenen Parameterinformationen für den Befehl überschreibt.
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 dazu finden Sie unter Generieren von Befehlen mit 'CommandBuilder'-Objekten (ADO.NET).
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 die beste Leistung optimiert und mit zusätzlicher Sicherheit ausgestattet werden. Während eine gespeicherte Prozedur problemlos aufgerufen werden kann, indem der Name der gespeicherten Prozedur gefolgt von Parameterargumenten als SQL-Anweisung übergeben wird, ermöglicht die Verwendung der Parameters-Auflistung des DbCommand-Objekts von ADO.NET eine genauere Definition der Parameter der gespeicherten Prozedur sowie den Zugriff auf Ausgabeparameter und Rückgabewerte.
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 dazu finden Sie in der SQL Server-Onlinedokumentation. |
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 .NET Framework-Datenanbieter für SQL Server unterstützt keine Fragezeichenplatzhalter (?) für die Übergabe von Parametern an eine SQL-Anweisung oder gespeicherte Prozedur. 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. |
Shared Sub GetSalesByCategory(ByVal connectionString As String, _
ByVal categoryName As String)
Using connection As New SqlConnection(connectionString)
' Create the command and set its properties.
Dim command As SqlCommand = New SqlCommand()
command.Connection = connection
command.CommandText = "SalesByCategory"
command.CommandType = CommandType.StoredProcedure
' Add the input parameter and set its properties.
Dim parameter As 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()
Dim reader As SqlDataReader = command.ExecuteReader()
If reader.HasRows Then
Do While reader.Read()
Console.WriteLine("{0}: {1:C}", _
reader(0), reader(1))
Loop
Else
Console.WriteLine("No rows returned.")
End If
End Using
End Sub
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();
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();
}
}
Verwenden von Parametern mit einem "OleDbCommand" oder "OdbcCommand"
Wenn Sie Parameter mit einem OleDbCommand oder einem OdbcCommand verwenden, muss die Reihenfolge der der Parameters-Auflistung hinzugefügten Parameter mit der Reihenfolge der in der gespeicherten Prozedur definierten Parameter übereinstimmen. Der .NET Framework-Datenanbieter für OLE DB und der .NET Framework-Datenanbieter für ODBC behandeln Parameter in einer gespeicherten Prozedur als Platzhalter und wenden Parameterwerte der Reihe nach an. Außerdem müssen der Parameters-Auflistung zuerst die Parameter für die Rückgabewerte hinzugefügt werden.
Der .NET Framework-Datenanbieter für OLE DB und der .NET Framework-Datenanbieter für ODBC unterstützen keine benannten Parameter für die Übergabe von Parametern an eine SQL-Anweisung oder gespeicherte Prozedur. In diesem Fall muss der Fragezeichenplatzhalter (?) verwenden. Dies wird im folgenden Beispiel dargestellt.
SELECT * FROM Customers WHERE CustomerID = ?
Dementsprechend muss die Reihenfolge, in der Parameter-Objekte der Parameters-Auflistung hinzugefügt werden, genau der Position des als Platzhalter für den Parameter fungierenden Fragezeichens (?) entsprechen.
Beispiel zu "OleDb"
Dim command As OleDbCommand = New OleDbCommand( _
"SampleProc", connection)
command.CommandType = CommandType.StoredProcedure
Dim parameter As OleDbParameter = command.Parameters.Add( _
"RETURN_VALUE", OleDbType.Integer)
parameter.Direction = ParameterDirection.ReturnValue
parameter = command.Parameters.Add( _
"@InputParm", OleDbType.VarChar, 12)
parameter.Value = "Sample Value"
parameter = command.Parameters.Add( _
"@OutputParm", OleDbType.VarChar, 28)
parameter.Direction = ParameterDirection.Output
OleDbCommand command = new OleDbCommand("SampleProc", connection);
command.CommandType = CommandType.StoredProcedure;
OleDbParameter parameter = command.Parameters.Add(
"RETURN_VALUE", OleDbType.Integer);
parameter.Direction = ParameterDirection.ReturnValue;
parameter = command.Parameters.Add(
"@InputParm", OleDbType.VarChar, 12);
parameter.Value = "Sample Value";
parameter = command.Parameters.Add(
"@OutputParm", OleDbType.VarChar, 28);
parameter.Direction = ParameterDirection.Output;
Beispiel zu "Odbc"
Dim command As OdbcCommand = New OdbcCommand( _
"{ ? = CALL SampleProc(?, ?) }", connection)
command.CommandType = CommandType.StoredProcedure
Dim parameter As OdbcParameter = command.Parameters.Add("RETURN_VALUE", OdbcType.Int)
parameter.Direction = ParameterDirection.ReturnValue
parameter = command.Parameters.Add( _
"@InputParm", OdbcType.VarChar, 12)
parameter.Value = "Sample Value"
parameter = command.Parameters.Add( _
"@OutputParm", OdbcType.VarChar, 28)
parameter.Direction = ParameterDirection.Output
OdbcCommand command = new OdbcCommand( _
"{ ? = CALL SampleProc(?, ?) }", connection);
command.CommandType = CommandType.StoredProcedure;
OdbcParameter parameter = command.Parameters.Add( _
"RETURN_VALUE", OdbcType.Int);
parameter.Direction = ParameterDirection.ReturnValue;
parameter = command.Parameters.Add( _
"@InputParm", OdbcType.VarChar, 12);
parameter.Value = "Sample Value";
parameter = command.Parameters.Add( _
"@OutputParm", OdbcType.VarChar, 28);
parameter.Direction = ParameterDirection.Output;
Siehe auch
Konzepte
'DataAdapter'-Parameter (ADO.NET)