Comment puis-je récupérer une liste de paramètres d'une procédure stockée dans SQL Server

StackOverflow https://stackoverflow.com/questions/33761

  •  09-06-2019
  •  | 
  •  

Question

À l'aide de C# et du Système.Les données.SqlClient, est-il un moyen de récupérer une liste de paramètres qui appartiennent à une procédure stockée sur un Serveur SQL server avant que je l'exécuter?

J'ai un "multi-environnement" scénario où il y a de multiples versions d'un même schéma de base de données.Exemples d'environnements peut-être "Développement", la "mise en scène", & "Production".Le "développement" va avoir une version de la procédure stockée et "mise en scène" va avoir un autre.

Tout ce que je veux faire est de valider que c'est un paramètre va être là avant de passer une valeur et l'appel de la procédure stockée.En évitant que SqlException plutôt que d'avoir à les attraper c'est un plus pour moi.

Joshua

Était-ce utile?

La solution

Vous pouvez utiliser SqlCommandBuilder.DeriveParameters() (voir SqlCommandBuilder.DeriveParameters - Obtenir des Informations de paramètres d'une Procédure Stockée - ADO.NET Tutoriels) ou il y a de cette façon ce qui n'est pas aussi élégant.

Autres conseils

Vous voulez que le SqlCommandBuilder.DeriveParameters(SqlCommand) la méthode.Noter qu'il nécessite un supplément aller-retour à la base, donc c'est quelque significative des performances.Vous devriez envisager la mise en cache des résultats.

Un exemple d'appel:

using (SqlConnection conn = new SqlConnection(CONNSTRING))
using (SqlCommand cmd = new SqlCommand("StoredProc", conn)) {
   cmd.CommandType = CommandType.StoredProcedure;
   SqlCommandBuilder.DeriveParameters(cmd);

   cmd.Parameters["param1"].Value = "12345";

   // ....
}

Bien que ses pas exactement ce que vous voulez, voici un exemple de code qui utilise l'occurrence de SqlConnection.GetSchema() méthode pour retourner toutes les procédures stockées associé à une base de données, et par la suite tous les noms de paramètres et types pour chaque procédure stockée.L'exemple ci-dessous charge ce dans des variables.Remarque que cela revient aussi tout le "système" des procédures stockées, ce qui pourrait ne pas être souhaitable.

Steve

    public void LoadProcedureInfo()
    {
        SqlConnection connection = new SqlConnection();

        ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["ConnectionString"];

        connection.ConnectionString = settings.ConnectionString;
        connection.Open();

        DataTable procedureDataTable = connection.GetSchema("Procedures");
        DataColumn procedureDataColumn = procedureDataTable.Columns["ROUTINE_NAME"];

        if (procedureDataColumn != null)
        {
            foreach (DataRow row in procedureDataTable.Rows)
            {
                String procedureName = row[procedureDataColumn].ToString();

                DataTable parmsDataTable = connection.GetSchema("ProcedureParameters", new string[] { null, null, procedureName });

                DataColumn parmNameDataColumn = parmsDataTable.Columns["PARAMETER_NAME"];
                DataColumn parmTypeDataColumn = parmsDataTable.Columns["DATA_TYPE"];

                foreach (DataRow parmRow in parmsDataTable.Rows)
                {
                    string parmName = parmRow[parmNameDataColumn].ToString();
                    string parmType = parmRow[parmTypeDataColumn].ToString();
                }
            }
        }
    }

Vous pouvez utiliser l'objet SqlCommandBuilder, et d'appeler la DeriveParameters méthode.

Fondamentalement, vous avez besoin pour passer une commande, c'est-setup pour appeler votre procédure stockée, et il frappera la bd à découvrir les paramètres, et de créer les paramètres appropriés dans les Paramètres de propriété de la SqlCommand

EDIT: Vous êtes tous trop vite!!

SqlCommandBuilder.DeriveParameters(command)

Cette déclaration fait ce que j'en ai besoin.

Voici un exemple de code complet pour la façon dont j'ai résolu ce problème.

Public Sub GetLogEntriesForApplication(ByVal settings As FilterSettings,
                              Optional ByVal RowGovernor As Integer = -1)

    Dim command As New SqlCommand("GetApplicationActions", 
        New SqlConnection(m_environment.LoggingDatabaseConnectionString))
    Dim adapter As New SqlDataAdapter(command)

    Using command.Connection

        With command

            .Connection.Open()
            .CommandType = CommandType.StoredProcedure

            SqlCommandBuilder.DeriveParameters(command)

            With .Parameters

                If settings.FilterOnLoggingLevel Then
                    If .Contains("@loggingLevel") Then
                        .Item("@loggingLevel").Value = settings.LoggingLevel
                    End If
                End If

                If settings.FilterOnApplicationID Then
                    If .Contains("@applicationID") Then
                        .Item("@applicationID").Value = settings.ApplicationID
                    End If
                End If

                If settings.FilterOnCreatedDate Then
                    If .Contains("@startDate") Then
                        .Item("@startDate").Value = settings.CreatedDate.Ticks
                    End If
                End If

                If settings.FilterOnEndDate Then
                    If .Contains("@endDate") Then
                        .Item("@endDate").Value = settings.EndDate.Ticks
                    End If
                End If

                If settings.FilterOnSuccess Then
                    If .Contains("@success") Then
                        .Item("@success").Value = settings.Success
                    End If
                End If

                If settings.FilterOnProcess Then
                    If settings.Process > -1 Then
                        If .Contains("@process") Then
                            .Item("@process").Value = settings.Process
                        End If
                    End If
                End If

                If RowGovernor > -1 Then
                    If .Contains("@topRows") Then
                        .Item("@topRows").Value = RowGovernor
                    End If
                End If

            End With

        End With

        adapter.TableMappings.Clear()
        adapter.TableMappings.Add("Table", "ApplicationActions")
        adapter.TableMappings.Add("Table1", "Milestones")

        LogEntries.Clear()
        Milestones.Clear()
        adapter.Fill(m_logEntryData)

    End Using

End Sub

Marque a la meilleure mise en œuvre de DeriveParameters.Comme il le dit, assurez-vous de cache comme dans ce tutoriel.

Cependant, je pense que c'est une manière dangereuse de la résolution de votre problème d'origine de la base de données de la procédure stockée de contrôle de version.Si vous allez modifier la signature d'une procédure en ajoutant ou en supprimant des paramètres, vous devez effectuer l'une des opérations suivantes:

  • Code dans un rétro-compatible manière en utilisant les valeurs par défaut (pour les nouveaux params) ou en ignorant tout simplement un param (supprimé params).Cela garantit que votre code client peut toujours faire appel à n'importe quelle version de votre procédure stockée.
  • Explicitement version de la procédure par nom (vous aurez my_proc et my_proc_v2).Cela garantit que votre code client et sprocs séjour dans la synchronisation.

En s'appuyant sur DeriveParameters pour valider la version de la procédure stockée que vous utilisez semble que le mauvais outil pour le travail, à mon humble avis.

L'ensemble de ces ADO.NET des solutions sont à sont à demander à la bibliothèque de code pour interroger la base de données de métadonnées de l'en votre nom.Si vous allez prendre que les performances de toute façon, vous devriez peut-être juste écrire de certaines fonctions d'assistance qui appeler

Select count(*) from information_schema.parameters 
where ...(proc name =.. param name=...) (pseudo-code)

Ou peut-être même générer vos paramètres en fonction du param liste, vous obtenez de retour.Cette technique permet de travailler avec plusieurs versions de MS SQL et parfois d'autres ANSI SQL bases de données.

J'ai été en utilisant DeriveParameters avec .NET 1.1 et 2.0 depuis quelques années maintenant, et a travaillé comme un charme à chaque fois.

Maintenant, je travaille sur mon premier travail avec .NET 3.5, et viens de trouver et vilaine surprise:DeriveParameters est la création de tous les paramètres avec SqlDbType "Variante", plutôt bon SqlDbTypes.C'est la création d'une SqlException lorsque vous tentez d'exécuter SPs avec des paramètres numériques, car SQL Server 2005 indique que sql-variante types de ne peut pas être implictily converti en int (ou smallint ou numérique) des valeurs.

Je viens de tester le même code .NET CF 2.0 et SQL Server 2000, et a fonctionné comme prévu, l'attribution de la SqlDbType appropriée à chacun des paramètres.

J'avais testé .NET 2.0 apps par rapport à SQL Server 2005 Bases de données, n'est donc pas un Serveur SQL server question connexe, alors il doit être quelque chose en rapport avec .NET 3.5

Des idées?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top