12
votes

Comment récupérer le type de paramètre de PROPROCHEDURE STOREDPRODURE DONNÉE EN SQL?

Je crée "générique" wrapper au-dessus des procédures SQL et je peux résoudre tous les noms des paramètres requis et les sqltypes, mais y a-t-il quelque chose comment obtenir le type "sous-jacent"?

Mon objectif est de faire quelque chose comme: xxx

où getnetype est la chose dont j'ai besoin. Je sais que cela peut être écrit en tant que commutateur à l'intérieur de param.sqldbtype, mais cela est plus court, et un code commenté plus court signifie une maintenance plus faible :)


1 commentaires

Qu'est-ce que tu essaies exactement de faire? Suis-je correct quand je lis que vous avez une collection de sqlparameters et que vous avez une collection de valeurs .NET? Et vous voulez "convertir" votre collection de valeurs aux propriétés SQLParameter.Value? Exemple: sqlparamaters [0] .Value = MagicConvert (valeurs [0]);


6 Réponses :


3
votes

Je pense que vous manquez une étape ici. La première chose à faire est de faire appel à la base de données de la définition de la procédure stockée via un appel Sélectionner et une jointure intérieure à la table Objets SYS ou à l'aide d'une enveloppe de gestion. Ensuite, vous pouvez "déduire" les types de paramètres basés sur les informations retournées.

Voici un MSO LIN k pour vous aider à démarrer p>

et un exemple de Comment interroger la structure de la base de données directement p>

Si vous exécutez le SQL du deuxième exemple de votre base de données, vous verrez exactement ce qui se passe: p>

USE AdventureWorks;
GO
SELECT SCHEMA_NAME(SCHEMA_ID) AS [Schema], 
SO.name AS [ObjectName],
SO.Type_Desc AS [ObjectType (UDF/SP)],
P.parameter_id AS [ParameterID],
P.name AS [ParameterName],
TYPE_NAME(P.user_type_id) AS [ParameterDataType],
P.max_length AS [ParameterMaxBytes],
P.is_output AS [IsOutPutParameter]
FROM sys.objects AS SO
INNER JOIN sys.parameters AS P 
ON SO.OBJECT_ID = P.OBJECT_ID
WHERE SO.OBJECT_ID IN ( SELECT OBJECT_ID 
FROM sys.objects
WHERE TYPE IN ('P','FN'))
ORDER BY [Schema], SO.name, P.parameter_id
GO


4 commentaires

Je ne suis pas sûr de savoir comment cela se fait (im extension du code de quelqu'un d'autre), mais interatialier à travers SQLCOMMAND.paramètres me montre tous les paramètres requis. Comment puis-je déduire les types?


Vous ne pouvez pas vraiment déduire le type. Vous devez connaître le type en quelque sorte. Habituellement, le type est codé en papier mais vous recherchez une manière automatisée et le seul moyen de le faire, de «savoir» le type, consiste à interroger la base de données.


Je pense qu'il pourrait simplement avoir besoin d'un moyen de cartographier du type SQL au type .NET correspondant. par exemple. Varchar => chaîne, etc.


Knobloch a raison .. Je veux savoir s'il est possible de la cartographie autre que le commutateur (param.sqldbtype)



13
votes

Malheureusement, autant que je sache que ce mappage n'est pas exposé au code de la technologie .NET. J'ai parcouru à travers la source de référence .NET Framework avant de cela, et j'ai constaté que dans le code .NET, il y a beaucoup de nouvelles relevés de commutateurs par type, comme ceux que vous essayez d'éviter, mais aucun d'entre eux ne semble être exposé à l'extérieur.

Si vous voulez vraiment mapper de SQLTYPES sur le type de SQLYPES sur le plus chime .NET, je pense que votre meilleur pari est de tourner la table de mappage dans les documents MSDN dans le code. Notez que le tableau sur MSDN a (au moins) deux erreurs: # 1: il n'y a pas de type .NET appelé "DateTime2" (j'ai utilisé DateTime) et il n'y a pas non plus de type "XML" (j'ai utilisé SQLXML). P>

Quoi qu'il en soit, voici la mappage que j'utilise - à l'aide d'un dictionnaire au lieu d'un commutateur pour faciliter l'accès sans une méthode distincte. p> xxx pré>

Notez qu'une chose que vous aurez besoin de surveiller est la taille / la précision - certains types SQL (par exemple, varchar code>) ont des limites de taille , tandis que les types .NET (par exemple, chaîne code>) ne le font pas. Donc, être capable de connaître le type de .NET le plus probable ne suffit pas vraiment ... Si vous utilisez ceci, par exemple, des règles de validation de lecteurs, vous devez également pouvoir empêcher les utilisateurs d'entrer invalides (par exemple trop grand ) Valeurs en connaissant plus sur le paramètre, comme la précision. Notez que, si vous regardez à l'intérieur de la source SQLCLIENT, ils utilisent un code spécial pour gérer des cas tels que la définition de la précision d'un type décimal de la précision SQL correspondante. p>

Notez que si la seule raison pour laquelle vous avez besoin du type .NET est pour pouvoir modifier les données dans un paramètre de PROC stocké, vous pouvez essayer d'utiliser simplement l'utilisation de ToString () sur toutes vos valeurs .net. Une chaîne dans la propriété de valeur du SQLParameter et voir si le cadre fera la conversion / l'analyse de votre part. Par exemple, pour un paramètre XML ou DATE, vous pourrez peut-être vous en envoyer avec une chaîne. p>

aussi, au lieu d'utiliser la réflexion pour trouver une méthode d'analyse () sur chaque type, car il existe une liste connue (et sa petite) de types, vous pouvez obtenir de meilleures performances en utilisant un code d'analyse fortement tapé pour chaque , comme le code ci-dessous. (Notez que plusieurs types (par exemple, sqldbtype.udt) n'ont pas nécessairement une méthode d'analyse d'analyse évidente ... vous devez déterminer comment vous voulez gérer ceux-ci.) P>

        string valueToSet = "1234";
        SqlParameter p = new SqlParameter();
        p.SqlDbType = System.Data.SqlDbType.Int;
        p.Value = TypeMapper[p.SqlDbType](valueToSet);


0 commentaires

3
votes

Vous ne pouvez pas nécessairement implicitement et avec précision extraire le type correct .NET CTS ("sous-jacent"), car cela pourrait changer en fonction de la valeur dans le paramètre - Le fichier .dbtype de SQLParameter et .sqldbtype est mutable et explicitement réglable par le programmeur (ou le moteur de génération de code) dans le cas d'un paramètre de sortie, le .dbtype / .sqldbtype peut être faux même après avoir été juste pendant un temps, par exemple si la valeur en dessous qui revient soudainement est différent que prévu en termes .NET. Les valeurs sont entraînées par le magasin de données et .NET SQLPARAMÈTRÈME COPES AU MEILLEUR SUR LE SON DES TYPES EXPLICITÉS. La valeur de données du SQLParameter doit être considérée comme faiblement saisie de termes .NET (en évidence par la valeur de retour de la propriété Param.Value).

Votre meilleur pari est

  1. Utilisez l'une des méthodes de mappage décrites par d'autres affiches - bien sûr, qui a sa propre hypothèse implicite selon laquelle le type de paramètre SQL sera toujours correct pour les données dedans.
  2. Test éventuellement la valeur revenant du paramètre de sortie et assumer des valeurs successives sont du même type. Bien sûr, c'est vraiment jusqu'à la base de données.
  3. Trouvez une autre stratégie au lieu de s'appuyer sur l'espace de noms Microsoft SQL - vous pourriez être beaucoup plus heureux à l'avenir.

    Test de la valeur d'un type .NET CTS ressemblerait à quelque chose comme system.type t = paraminStance.value.gettype (); null provoquera une exception. Vous auriez toujours besoin de le jeter de manière appropriée en utilisant un commutateur ou si / sinon, sauf si vous retirez certaines techniques de réflexion fantaisie.


0 commentaires

1
votes

Si vous pouvez résoudre le bon SQLType, la réflexion vous obtiendra la distribution explicite à un type .NET. La valeur de retour serait le système sous-jacent.Type. La mise en cache du résultat devrait compenser la perfection sur la 1ère recherche.


0 commentaires

1
votes

Jetez un coup d'œil à ce qu'ils font dans LINQ à SQL T4 , il semble fonctionner bien. < / p>

Vous pourriez être capable de savoir ce dont vous avez besoin en regardant le code.


0 commentaires

4
votes

Personne d'autre semble vouloir vous dire, mais ce que vous faites n'est probablement pas la meilleure façon de le faire. XXX PRE>

Vous dites que vous avez donné un Valeur de chaîne, que vous savez doit être affectée à un paramètre et vous souhaitez faire cesser cette valeur par une manière qu'il peut s'adapter? P>

Veuillez considérer pourquoi vous faites cela. Vous faites de l'hypothèse que le code suivant est correct: p> xxx pré>

Il n'y a pas de raison claire pourquoi c'est mieux que: p>

param.Value = value;


0 commentaires