Configuration des paramètres et des types de données des paramètres
Les objets de commande utilisent des paramètres pour passer des valeurs à des instructions SQL ou à des procédures stockées, en fournissant la vérification et la validation des types. Contrairement au texte de la commande, l'entrée de paramètre est traitée comme une valeur littérale et non pas comme du code exécutable. Cela vous permet de vous protéger des attaques « par injection de code SQL », dans lesquelles un attaquant insère une commande qui compromet la sécurité sur le serveur dans une instruction SQL.
Les commandes paramétrées améliorent également les performances d'exécution des requêtes car elles permettent au serveur de base de données de faire correspondre la commande entrante avec un plan de requête mis en cache approprié. Pour plus d’informations, consultez Mise en cache et réutilisation du plan d'exécution et Réutilisation des paramètres et du plan d'exécution. Outre les avantages relatifs à la sécurité et aux performances, les commandes paramétrées fournissent une méthode pratique d'organisation des valeurs passées à une source de données.
Un objet DbParameter peut être créé à l'aide de son constructeur ou en l'ajoutant à la propriété DbParameterCollection en appelant la méthode Add
de la collection DbParameterCollection . La méthode Add
prendra comme entrée des arguments de constructeur ou un objet Parameter existant, selon le fournisseur de données.
Approvisionnement de la propriété ParameterDirection
Lorsque vous ajoutez des paramètres, vous devez fournir une propriété ParameterDirection pour les paramètres autres que les paramètres d'entrée. Le tableau ci-dessous indique les valeurs ParameterDirection
que vous pouvez utiliser avec l'énumération ParameterDirection .
Nom du membre | Description |
---|---|
Input | Le paramètre est un paramètre d'entrée. Il s’agit de la valeur par défaut. |
InputOutput | Le paramètre peut être à la fois un paramètre d'entrée et de sortie. |
Output | Le paramètre est un paramètre de sortie. |
ReturnValue | Le paramètre représente une valeur de retour d'une opération telle qu'une procédure stockée, une fonction intégrée ou une fonction définie par l'utilisateur. |
Utilisation des espaces réservés de paramètres
La syntaxe des espaces réservés des paramètres dépend de la source de données. Les fournisseurs de données .NET Framework gèrent différemment la dénomination et la spécification des paramètres et des espaces réservés de paramètres. Cette syntaxe est personnalisée en fonction d'une source de données spécifique, comme le décrit le tableau ci-dessous.
Fournisseur de données | Syntaxe d'attribution de noms aux paramètres |
---|---|
System.Data.SqlClient | Utilise des paramètres nommés au format @ nom_paramètre. |
System.Data.OleDb | Utilise des marqueurs de paramètres positionnels indiqués par un point d'interrogation (? ). |
System.Data.Odbc | Utilise des marqueurs de paramètres positionnels indiqués par un point d'interrogation (? ). |
System.Data.OracleClient | Utilise des paramètres nommés au format : nom_paramètre (ou nom_paramètre). |
Spécification des types de données de paramètre
Le type de données d’un paramètre est spécifique au fournisseur de données .NET Framework. Si vous spécifiez le type, la valeur du Parameter
est convertie vers le type de fournisseur de données .NET Framework avant d’être passée à la source de données. Vous pouvez également spécifier le type d'un Parameter
de façon générique en affectant à la propriété DbType
de l'objet Parameter
un DbTypeparticulier.
Le type de fournisseur de données .NET Framework d’un objet Parameter
est inféré à partir du type .NET Framework de la Value
de l’objet Parameter
ou à partir du DbType
de l’objet Parameter
. Le tableau suivant indique le type Parameter
déduit en fonction de l'objet passé comme valeur Parameter
ou du DbType
spécifié.
Type .NET Framework | DbType | SqlDbType | OleDbType | OdbcType | OracleType |
---|---|---|---|---|---|
Boolean | Booléen | bit | Booléen | bit | Byte |
Byte | Byte | TinyInt | UnsignedTinyInt | TinyInt | Byte |
byte[] | Binary | VarBinary. Cette conversion implicite échouera si le tableau d’octets est plus grand que la taille maximale d’un VarBinary, soit 8 000 octets.Pour des tableaux d’octets d’une taille supérieure à 8 000 octets, définissez explicitement le SqlDbType. | VarBinary | Binary | Brut |
Char | La déduction de SqlDbType à partir de char n'est pas prise en charge. | Char | Char | Byte | |
DateTime | DateTime | DateTime | DBTimeStamp | DateTime | DateTime |
DateTimeOffset | DateTimeOffset | DateTimeOffset dans SQL Server 2008. La déduction de SqlDbType à partir de DateTimeOffset n'est pas prise en charge dans les versions de SQL Server antérieures à SQL Server 2008. | DateTime | ||
Decimal | Decimal | Decimal | Decimal | Numérique | Number |
Double | Double | Float | Double | Double | Double |
Single | Unique | Real | Unique | Real | Float |
Guid | Guid | UniqueIdentifier | Guid | UniqueIdentifier | Brut |
Int16 | Int16 | SmallInt | SmallInt | SmallInt | Int16 |
Int32 | Int32 | Int | Int | Int | Int32 |
Int64 | Int64 | BigInt | BigInt | BigInt | Nombre |
Object | Objet | Variante | Variant | La déduction d'OdbcType à partir d'Object n'est pas prise en charge. | Objet blob |
String | String | NVarChar. Cette conversion implicite échouera si la chaîne est supérieure à la taille maximale de NVarChar, soit 4 000 caractères. Pour les chaînes supérieures à 4 000 caractères, définissez explicitement SqlDbType. | VarWChar | NVarChar | NVarChar |
TimeSpan | Temps | Time dans SQL Server 2008. La déduction de SqlDbType à partir de TimeSpan n'est pas prise en charge dans les versions de SQL Server antérieures à SQL Server 2008. | DBTime | Temps | DateTime |
UInt16 | UInt16 | La déduction de SqlDbType à partir de UInt16 n'est pas prise en charge. | UnsignedSmallInt | Int | UInt16 |
UInt32 | UInt32 | La déduction de SqlDbType à partir de UInt32 n'est pas prise en charge. | UnsignedInt | BigInt | UInt32 |
UInt64 | UInt64 | La déduction de SqlDbType à partir de UInt64 n'est pas prise en charge. | UnsignedBigInt | Numérique | Nombre |
AnsiString | VarChar | VarChar | VarChar | VarChar | |
AnsiStringFixedLength | Char | Char | Char | Char | |
Devise | Money | Devise | La déduction d' OdbcType à partir de Currency n'est pas prise en charge. |
Number | |
Date | Date dans SQL Server 2008. La déduction de SqlDbType à partir de Date n'est pas prise en charge dans les versions de SQL Server antérieures à SQL Server 2008. | DBDate | Date | DateTime | |
SByte | La déduction de SqlDbType à partir de SByte n'est pas prise en charge. | TinyInt | La déduction de OdbcType à partir de SByte n'est pas prise en charge. |
SByte | |
StringFixedLength | NChar | WChar | NChar | NChar | |
Temps | Time dans SQL Server 2008. La déduction de SqlDbType à partir de Time n'est pas prise en charge dans les versions de SQL Server antérieures à SQL Server 2008. | DBTime | Temps | DateTime | |
VarNumeric | La déduction de SqlDbType à partir de VarNumeric n'est pas prise en charge. | VarNumeric | La déduction de OdbcType à partir de VarNumeric n'est pas prise en charge. |
Nombre | |
type défini par l'utilisateur (objet avec SqlUserDefinedAggregateAttribute) | Objet ou chaîne, selon le fournisseur (SqlClient retourne toujours un objet, ODBC retourne toujours une chaîne et le fournisseur de données managées OleDb l'un ou l'autre) | SqlDbType.Udt si SqlUserDefinedTypeAttribute est présent, sinon Variant | OleDbType.VarWChar (si la valeur est Null), sinon OleDbType.Variant. | OdbcType.NVarChar | non pris en charge |
Notes
Les conversions du type decimal vers d'autres types sont des conversions restrictives qui arrondissent la valeur décimale à la valeur entière la plus proche de zéro. Si le résultat de la conversion ne peut pas être représenté dans le type de destination, un OverflowException est levé.
Notes
Lorsque vous envoyez une valeur de paramètre Null au serveur, vous devez spécifier DBNull plutôt que null
(Nothing
en Visual Basic). Dans le système, la valeur null désigne un objet vide qui ne possède pas de valeur. DBNull est utilisé pour représenter des valeurs null. Pour plus d’informations sur les valeurs Null de base de données, consultez Handling Null Values.
Dérivation des informations sur les paramètres
Les paramètres peuvent aussi être dérivés d'une procédure stockée à l'aide de la classe DbCommandBuilder
. Les classes SqlCommandBuilder
et OleDbCommandBuilder
fournissent une méthode statique, DeriveParameters
, qui remplit automatiquement la collection de paramètres d'un objet Command qui utilise les informations sur les paramètres provenant d'une procédure stockée. Notez que DeriveParameters
remplace toutes les informations existantes sur les paramètres pour la commande.
Notes
La dérivation des informations de paramètre entraîne une baisse des performances car elle requiert un aller-retour supplémentaire vers la source de données pour extraire les informations. Si les informations sur les paramètres sont connues au moment du design, vous pouvez améliorer la performance de votre application en définissant les paramètres de manière explicite.
Pour plus d’informations, consultez Génération de commandes avec CommandBuilders.
Utilisation de paramètres avec SqlCommand et une procédure stockée
Les procédures stockées offrent de nombreux avantages dans les applications pilotées par des données. En utilisant les procédures stockées, les opérations de base de données peuvent être encapsulées dans une commande unique, optimisées pour de meilleures performances et améliorées grâce à une sécurité supplémentaire. Bien qu’une procédure stockée puisse être appelée en passant son nom suivi des arguments de paramètre comme instruction SQL, l’utilisation de la collection Parameters de l’objet ADO.NET DbCommand vous permet de définir plus explicitement les paramètres de procédure stockée et d’accéder aux paramètres de sortie et aux valeurs de retour.
Remarque
Les instructions paramétrables sont exécutées sur le serveur à l’aide sp_executesql
de , ce qui permet la réutilisation du plan de requête. Les curseurs ou variables locaux dans le lot sp_executesql
ne sont pas visibles pour le lot qui appelle sp_executesql
. Les modifications dans le contexte de la base de données durent uniquement jusqu'à la fin de l'instruction sp_executesql
. Pour plus d’informations, consultez sp_executesql (Transact-SQL).
Lorsque vous utilisez des paramètres avec un objet SqlCommand pour exécuter une procédure stockée SQL Server, les noms des paramètres ajoutés à la collection Parameters doivent correspondre à ceux des marqueurs de paramètres dans la procédure stockée. Le fournisseur de données .NET Framework pour SQL Server ne prend pas en charge l’espace réservé sous forme de point d’interrogation (?) pour le passage des paramètres à une instruction SQL ou une procédure stockée. Il traite les paramètres de la procédure stockée comme des paramètres nommés et recherche les marqueurs de paramètres correspondants. Par exemple, la procédure stockée CustOrderHist
est définie à l'aide d'un paramètre nommé @CustomerID
. Lorsque votre code exécute la procédure stockée, il doit également utiliser un paramètre nommé @CustomerID
.
CREATE PROCEDURE dbo.CustOrderHist @CustomerID varchar(5)
Exemple
Cet exemple montre comment appeler une procédure stockée SQL Server dans l'exemple de base de données Northwind
. Le nom de la procédure stockée est dbo.SalesByCategory
et il possède un paramètre d'entrée nommé @CategoryName
avec un type de données nvarchar(15)
. Le code crée un nouveau SqlConnection à l'intérieur d'un bloc using pour que la connexion soit libérée une fois la procédure terminée. Les objets SqlCommand et SqlParameter sont créés et leurs propriétés sont définies. Un SqlDataReader exécute SqlCommand
et retourne le jeu de résultats provenant de la procédure stockée, en affichant la sortie dans la fenêtre de console.
Notes
Au lieu de créer les objets SqlCommand
et SqlParameter
puis de définir les propriétés dans des instructions distinctes, vous pouvez choisir d'utiliser l'un des constructeurs surchargés pour définir plusieurs propriétés dans une instruction unique.
static void GetSalesByCategory(string connectionString,
string categoryName)
{
using (SqlConnection connection = new(connectionString))
{
// Create the command and set its properties.
SqlCommand command = new()
{
Connection = connection,
CommandText = "SalesByCategory",
CommandType = CommandType.StoredProcedure
};
// Add the input parameter and set its properties.
SqlParameter parameter = new()
{
ParameterName = "@CategoryName",
SqlDbType = SqlDbType.NVarChar,
Direction = ParameterDirection.Input,
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();
}
}
}
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()
Using 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 Using
End Sub
Utilisation de paramètres avec OleDbCommand ou OdbcCommand
Lorsque vous utilisez des paramètres avec un objet OleDbCommand ou OdbcCommand, l'ordre des paramètres ajoutés à la collection Parameters
doit correspondre à celui des paramètres définis dans votre procédure stockée. Les fournisseurs de données .NET Framework pour OLE DB et .NET Framework pour ODBC traitent les paramètres d’une procédure stockée comme des espaces réservés et appliquent des valeurs de paramètre dans l’ordre. En outre, les paramètres des valeurs de retour doivent être les premiers paramètres ajoutés à la collection Parameters
.
Les fournisseurs de données .NET Framework pour OLE DB et .NET Framework pour ODBC ne prennent pas en charge les paramètres nommés pour passer des paramètres à une instruction SQL ou à une procédure stockée. Dans ce cas, vous devez utiliser l'espace réservé de point d'interrogation (?), comme dans l'exemple suivant.
SELECT * FROM Customers WHERE CustomerID = ?
En conséquence, l'ordre dans lequel les objets Parameter
sont ajoutés à la collection Parameters
doit directement correspondre à la position de l'espace réservé ? pour le paramètre.
Exemple 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;
Exemple 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;