Aujourd'hui, une requête doit renvoyer un ensemble de résultats via ExcuteReader, et en même temps elle souhaite afficher des paramètres. Au début, je n'ai pas pu obtenir la valeur des paramètres de sortie, pensant que la procédure stockée contenait une erreur. le test dans l'analyseur de requêtes était correct et les paramètres de sortie ont effectivement été modifiés.
Ce qui est encore plus déroutant, c'est qu'après avoir lancé une exception lors de la conversion forcée du type de la sortie, elle peut effectivement être obtenue à nouveau. Est-ce un bug d'ado.net ? C'est impossible d'imaginer une telle page. L'API couramment utilisée apparaît. Est-ce faux ? Mon code est similaire au scénario suivant :
essayez {
using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) {
int val = (int)cmd.Parameters[1].Value; // Toujours vide maintenant
// plus
}
}
capture (Exp d'exception) {
throw new ApplicationException("Valeur du paramètre de sortie : " + cmd.Parameters[1].Value, exp); // La valeur de sortie peut maintenant être obtenue.
}
C'est vraiment frustrant après une heure de débogage et de suivi,
j'ai finalement trouvé la réponse dans MSDN :
Lorsque vous utilisez un objet Command avec une procédure stockée, vous pouvez définir la propriété CommandType de l'objet Command sur StoredProcedure. Lorsque CommandType est StoredProcedure, vous pouvez utiliser la propriété Parameters de Command pour accéder aux paramètres d’entrée et de sortie et aux valeurs de retour. Quelle que soit la méthode Execute appelée, la propriété Parameters est accessible. Cependant, lorsque ExecuteReader est appelé, la valeur de retour et les paramètres de sortie ne seront pas accessibles tant que DataReader n'est pas fermé.
réf : http://msdn2.microsoft.com/zh-CN/library/tyy0sz6b.aspx
C'est tout. J'ai l'impression d'avoir encore été dupé par MS. À bien y penser, pourquoi suis-je inexpérimenté en apprentissage ? J'ai déjà modifié le document et
y suis revenu. Votre propre environnement de code peut toujours être expliqué.
Parce que lorsque l'exception est interceptée, la portée d'utilisation a été sautée, le DataReader a été automatiquement fermé et la valeur du paramètre de sortie peut naturellement être obtenue.
Bien sûr, si vous mettez le try catch dans using, vous ne pouvez toujours pas l'obtenir, car il est toujours dans la portée using et le DataReader n'a pas été fermé.
De plus, MSDN indique qu'il n'est accessible que si le DataReader est fermé, mais ce n'est pas le cas.
Après tests, il peut être résumé ainsi :
1. Pour ExecuteReader, le paramètre de sortie et la valeur de retour sont renvoyés à DataReader en tant que jeu de résultats, et le jeu de résultats est toujours le dernier.
2. Selon 1, lorsqu'il existe un ensemble de résultats, pour accéder aux paramètres de sortie et aux valeurs de retour, vous devez appeler NextResult à l'emplacement de l'ensemble de résultats correspondant aux paramètres de sortie et aux valeurs de retour.
3. Selon 1, lorsque Execute ne renvoie pas de jeu de résultats, il est accessible directement (notez qu'il n'est pas nécessaire d'appeler Read())
4. Portez une attention particulière à la nécessité d'appeler NextResult plusieurs fois si plusieurs jeux de résultats sont renvoyés ; si le nombre de jeux de résultats est dynamique, alors la valeur de retour de nextResult() est fausse.
5. Même si l'option CommandBehavior.SingleResult est spécifiée pour ExecuteReader (renvoyant un seul jeu de résultats, en fait renvoyant le premier jeu de résultats du lot), les paramètres de sortie sont renvoyés sous forme de jeu de résultats.
6. A la fermeture du DataReader (Close()), les paramètres de sortie sont renseignés et donc accessibles.
7. Étant donné que le DataReader est en lecture directe uniquement, même si les paramètres de sortie sont obtenus via la méthode NextResult avant de fermer le DataReader, le jeu de résultats précédent n'est plus accessible (dans certains cas, vous souhaiterez peut-être contrôler dynamiquement le jeu de résultats via le jeu de résultats). paramètres.visite).
8. Afin de résoudre le problème en 6, vous ne pouvez pas utiliser le paramètre de sortie et renvoyer directement le paramètre de sortie comme premier résultat (SELECT @parmname).
Ce qui précède n'est que mon propre résumé, j'espère qu'il n'y a pas de divergence et cela peut être le cas. utile aux débutants.
réf :
http://www.bigcircleboy.net/583a194f-2c2c-4662-9036-4e2f0eb262396084313157728108.html