Quelle est la meilleure méthode pour passer des paramètres à SQLCommand?
-
08-07-2019 - |
Question
Quelle est la meilleure méthode pour transmettre des paramètres à SQLCommand? Vous pouvez faire:
cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";
ou
cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";
ou
cmd.Parameters.Add("@Name").Value = "Bob";
Il semble que le premier puisse être en quelque sorte "meilleur" soit en termes de performance ou de vérification d'erreur. Mais je voudrais savoir plus définitivement.
La solution
Vous pouvez également utiliser AddWithValue ()
, mais soyez conscient de la possibilité d'une conversion de type implicite erronée.
cmd.Parameters.AddWithValue("@Name", "Bob");
Autres conseils
Que se passe-t-il là-bas?
Vous citez les listes de paramètres pour plusieurs surcharges de Add
. Ce sont des méthodes pratiques qui correspondent directement aux surcharges de constructeur de la classe SqlParameter
. Ils construisent essentiellement l'objet paramètre en utilisant n'importe quel constructeur ayant la même signature que la méthode de confort que vous avez appelée, puis appellent SqlParameterCollection.Add (SqlParameter)
comme suit:
SqlParameter foo = new SqlParameter(parameterName, dbType, size);
this.Add(foo);
AddWithValue
est similaire mais prend encore plus de commodité, en définissant également la valeur. Cependant, il a en fait été introduit pour résoudre un problème de cadre. Pour citer MSDN,
La surcharge de
Add
qui prend une chaîne et un objet a été déconseillé en raison d'une ambiguïté possible avec le surchargeSqlParameterCollection.Add
qui prend unechaîne
et unSqlDbType
valeur d'énumération où passer un entier avec la chaîne pourrait être interprété comme étant le valeur du paramètre ou le correspondant ValeurSqlDbType
. UtilisezAddWithValue
chaque fois que vous voulez ajouter un paramètre en spécifiant son nom et sa valeur.
Les surcharges de constructeur pour la classe SqlParameter
ne sont que commodités pour la définition des propriétés d'instance. Ils raccourcissent le code, avec un impact marginal sur les performances: le constructeur peut contourner les méthodes de définition et opérer directement sur des membres privés. S'il y a une différence, ce ne sera pas beaucoup.
Que dois-je faire?
Notez les éléments suivants (à partir de MSDN)
Pour bidirectionnel et sortie les paramètres et les valeurs de retour, vous doit définir la valeur de
Taille
. C'est non requis pour les paramètres d'entrée, et si elle n'est pas explicitement définie, la valeur est déduit de la taille réelle de la paramètre spécifié lorsqu'un l'instruction paramétrée est exécutée.
Le type par défaut est input. Cependant, si vous autorisez la déduction de la taille de cette manière et recyclez l'objet paramètre dans une boucle (vous avez dit que vous vous intéressiez aux performances), la taille sera définie par la première valeur et les valeurs suivantes, plus longues, coupé. Évidemment, cela n’est significatif que pour les valeurs de longueur variable telles que les chaînes.
Si vous passez le même paramètre logique à plusieurs reprises dans une boucle, je vous recommande de créer un objet SqlParameter en dehors de la boucle et de le dimensionner correctement. Le surdimensionnement d'un varchar est inoffensif. Par conséquent, si vous souhaitez obtenir le maximum exact dans un PITA, définissez-le simplement plus grand que ce que vous attendez de la colonne. Étant donné que vous recyclez l'objet au lieu d'en créer un nouveau à chaque itération, la consommation de mémoire pendant la durée de la boucle risque de tomber , même si vous êtes un peu excité par le surdimensionnement.
À vrai dire, à moins que vous ne traitiez des milliers d'appels, rien de tout cela ne fera une grande différence. AddWithValue
crée un nouvel objet, contournant le problème de dimensionnement. C'est court et doux et facile à comprendre. Si vous parcourez des milliers, utilisez mon approche. Sinon, utilisez AddWithValue
pour que votre code reste simple et facile à gérer.
2008 était il y a longtemps
Depuis que j'ai écrit ceci, le monde a changé. Il y a de nouveaux types de dates, et il y a aussi un problème qui ne m’a pas traversé l’esprit jusqu’à ce qu’un problème récent lié aux dates me fasse penser aux conséquences de l’élargissement.
L'élargissement et le rétrécissement, pour ceux qui ne connaissent pas les termes, sont des qualités des conversions de types de données. Si vous affectez un int à un double, il n'y a pas de perte de précision car le double est "plus large". Il est toujours prudent de le faire, la conversion est donc automatique. C'est pourquoi vous pouvez affecter un int à un double, mais dans le sens contraire, vous devez effectuer une conversion explicite. Doubler en int est une conversion restrictive avec une perte de précision potentielle.
T
Je dirais n ° 1 à coup sûr. Toutefois, Microsoft le fait dans le bloc d’application d’accès aux données de la bibliothèque d’entreprise, ce qui est préférable, en particulier pour le serveur SQL:
J'avais l'habitude d'utiliser votre option 1:
cmd.Parameters.Add ("@ Name", SqlDbType.VarChar, 20) .Value = "Bob";
qui a bien fonctionné, mais j’ai commencé à utiliser .AddWithValue et c’est aussi simple que cela. Cela ne m'a pas posé de problème après plusieurs milliers d'utilisations. Remarquez, je passe presque toujours les variables privées de mes classes, je n'ai donc pas à m'inquiéter autant de la conversion de type implicite.
Cela dépend de votre application. En fait, j'aime bien 2, car je n'ai pas à changer mon DAO si je change la longueur d'un paramètre proc stocké. C'est juste moi si. Je ne sais pas s'il y a des pénalités de performance ou quoi que ce soit.