Quelle est la meilleure méthode pour passer des paramètres à SQLCommand?

Quelle est la meilleure méthode pour passer 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 pourrait être quelque peu "mieux" que ce soit au niveau des performances ou la vérification d'erreur. Mais je voudrais en savoir plus définitivement.

49
demandé sur TAG 2008-11-16 03:56:13

5 réponses

vous pouvez également utiliser AddWithValue() , mais soyez conscient de la possibilité de la conversion de type implicite incorrecte.

cmd.Parameters.AddWithValue("@Name", "Bob");
49
répondu Mitch Wheat 2015-02-23 05:35:04

que se passe-t-il là-dedans?

vous citez les listes de paramètres pour plusieurs surcharges de Add . Ce sont des méthodes pratiques qui correspondent directement aux surcharges du constructeur pour la classe SqlParameter . Ils construisent essentiellement l'objet paramètre en utilisant quel que soit le constructeur a la même signature que la méthode de commodité que vous avez appelé, et ensuite appeler SqlParameterCollection.Add(SqlParameter) comme ceci:

SqlParameter foo = new SqlParameter(parameterName, dbType, size);
this.Add(foo);

AddWithValue est similaire, mais prend la convenance encore plus loin, en fixant également la valeur. Toutefois, elle a été introduite pour résoudre un problème de cadre. Pour citer MSDN,

La surcharge de Add qui prend un chaîne et un objet a été désapprouvée en raison d'une ambiguïté possible avec le SqlParameterCollection.Add surcharge cela prend un String et un SqlDbType valeur d'énumération où passer un entier avec la chaîne pourrait être interprété comme étant le paramètre la valeur ou le correspondant SqlDbType de la valeur. Use AddWithValue chaque fois que vous voulez ajouter un paramètre en spécifiant son nom et la valeur.

les surcharges de constructeur pour la classe SqlParameter sont de simples commodités pour définir des propriétés d'exemple. Ils raccourcissent le code, avec un impact marginal sur la performance: le constructeur peut contourner les méthodes setter et opérer directement sur les membres privés. S'il y a une différence, ce ne sera pas beaucoup.

Que dois-je faire?

Notez les points suivants (à partir de MSDN)

pour bidirectionnel et de sortie paramètres et valeurs de retour, vous devez définir la valeur de Size . C'est pas requis pour les paramètres d'entrée, et si pas explicitement défini, la valeur est inférée à partir de la taille réelle de l' paramètre spécifié lorsqu'un paramétrable instruction est exécutée.

le type par défaut est entrée. Cependant, si vous permettez à la taille d'être déduite comme ceci et que vous recyclez l'objet paramètre dans une boucle (vous avez dit que vous étiez concerné par la performance) alors la taille sera définie par la première valeur et toutes les valeurs suivantes qui sont plus longues seront coupées. De toute évidence, ceci n'est significatif que pour les valeurs de longueur variables 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 du boucle et de taille appropriée. Surdimensionner une varchar est inoffensif, donc si c'est une PITA pour obtenir le maximum exact, mettez juste plus grand que vous jamais vous attendez à la colonne pour être. Parce que vous recyclez l'objet plutôt que d'en créer un nouveau pour chaque itération, la consommation de mémoire sur la durée de la boucle sera probablement drop même si vous obtenez un peu excité avec le surdimensionnement.

en vérité, à moins que vous ne traitiez des milliers d'appels, rien de tout cela vont faire beaucoup de différence. AddWithValue crée un nouvel objet, en évitant le problème de dimensionnement. C'est court et doux et facile à comprendre. Si vous passez par milliers, utilisez mon approche. Si vous ne le faites pas, utilisez AddWithValue pour garder votre code simple et facile à entretenir.


2008 était il y a longtemps

depuis que j'ai écrit ceci, le monde a changé. Il y a de nouveaux types de date, et il y a aussi un problème qui Je n'ai pas pensé à ça jusqu'à ce qu'un problème récent avec les dates me fasse penser aux implications de l'élargissement.

élargissement et rétrécissement, pour ceux qui ne connaissent pas les termes, sont des qualités de conversions de type de données. Si vous assignez un int à un double, il n'y a pas de perte de précision car le double est "plus large". Il est toujours sûr de le faire, donc la conversion est automatique. C'est pourquoi vous pouvez affecter un entier à un double, mais dans l'autre sens que vous avez à faire un cast explicite - double int est une conversion de rétrécissement avec perte potentielle de précision.

cela peut s'appliquer aux cordes: NVARCHAR est plus large que VARCHAR, donc vous pouvez assigner un VARCHAR à un NVARCHAR mais aller dans l'autre sens nécessite un plâtre. La comparaison fonctionne parce que le VARCHAR s'élargit implicitement à NVARCHAR, mais cela interférera avec l'utilisation des index!

C# chaînes Unicode, donc AddWithValue va produire un paramètre NVARCHAR. À l' à l'autre extrémité, les valeurs de la colonne VARCHAR élargissent à NVARCHAR pour la comparaison. Cela n'arrête pas l'exécution de la requête, mais il empêche l'index de. Ce qui est mauvais.

Que pouvez-vous y faire? Vous avez deux solutions possibles.

  • tapez explicitement le paramètre. Cela signifie qu'il n'y a plus de valeur ajoutée
  • changer tous les types de colonnes de chaîne en nvarchar.

amerrissage VARCHAR est probablement le la meilleure idée. C'est un changement simple avec des conséquences prévisibles et il améliore votre histoire de localisation. Toutefois, il se peut que vous n'ayez pas cette option.

ces jours-ci je ne fais pas beaucoup de direct ADO.NET. Linq2Sql est maintenant mon arme de choix, et le fait d'écrire cette mise à jour m'a fait me demander comment il gère ce problème. J'ai soudain un désir ardent de purger mes bases de données de VARCHAR.

56
répondu Peter Wone 2015-02-24 00:10:15

je dirais #1 pour sûr. Mais, cependant Microsoft le fait dans le bloc d'application d'accès aux données dans la bibliothèque d'entreprise est le meilleur, esp pour SQL server:

http://msdn.microsoft.com/en-us/library/dd203144.aspx

4
répondu Booji Boy 2008-11-16 01:17:57

j'utilisais votre option 1:

cmd.Paramètre.Ajouter ("@Name", SqlDbType.VarChar, 20).Valeur = "Bob";

qui fonctionnait bien, mais j'ai commencé à l'utiliser .AddWithValue et c'est aussi simple que cela. Ça ne m'a pas posé de problème après des milliers d'utilisations. Remarquez, je passe presque toujours les variables privées de mes classes, donc je n'ai pas à m'inquiéter autant de la conversion de type implicite.

2
répondu aSkywalker 2008-11-16 03:30:00

cela dépend de votre application. J'aime en fait 2, parce que je n'aime pas avoir à changer mon DAO si je change la longueur d'un paramètre proc stocké. C'est juste moi. Je ne sais pas s'il y a des pénalités de performance ou autre.

2
répondu Charles Graham 2008-11-17 04:41:28