Come posso recuperare un elenco di parametri da una stored procedure in SQL Server

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

  •  09-06-2019
  •  | 
  •  

Domanda

L'utilizzo di C# e di Sistema.Dati.SqlClient, c'è un modo per recuperare un elenco di parametri che appartengono a una stored procedure su SQL Server prima di eseguire effettivamente è?

Ho un "multi-ambiente", scenario in cui ci sono più versioni dello stesso schema di database.Esempi di ambienti potrebbe essere "Sviluppo", la "messa in scena", & "Produzione"."Sviluppo" è una versione della stored procedure e di "messa in scena", è un'altra.

Tutto quello che voglio fare è la verifica che un parametro è intenzione di essere lì prima che il passaggio di un valore e di chiamare la stored procedure.Evitando che SqlException, piuttosto che dover prendere è un plus per me.

Giosuè

È stato utile?

Soluzione

È possibile utilizzare SqlCommandBuilder.DeriveParameters() (vedere SqlCommandBuilder.DeriveParameters - Ottenere Informazioni sui Parametri per una Stored Procedure - ADO.NET Tutorial) o non c'è in questo modo che non è così elegante.

Altri suggerimenti

Si desidera che il SqlCommandBuilder.DeriveParameters(SqlCommand) metodo.Si noti che è necessario un ulteriore giro per il database, quindi è un po ' significativo calo di prestazioni.Si dovrebbe considerare la memorizzazione nella cache i risultati.

Un esempio di chiamata:

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";

   // ....
}

Anche se non è esattamente quello che vuoi, ecco un esempio di codice che utilizza il SqlConnection.GetSchema() metodo per restituire tutte le stored procedure associate con un database, e poi in seguito tutti i nomi dei parametri e tipi per ogni stored procedure.L'esempio seguente carica solo questo in variabili.Nota che questo è anche restituisce tutto il "sistema" stored procedure, che potrebbe non essere desiderabile.

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();
                }
            }
        }
    }

È possibile utilizzare l'oggetto SqlCommandBuilder, e chiamare il metodo DeriveParameters.

Fondamentalmente, è necessario passare un comando, che è il programma di installazione per chiamare la stored proc, e sarà colpito il DB per scoprire i parametri, e creare opportuni parametri i Parametri di proprietà di SqlCommand

EDIT: Siete tutti troppo veloce!!!!

SqlCommandBuilder.DeriveParameters(command)

Questa dichiarazione fa quello che ho bisogno di.

Ecco un esempio di codice per il modo in cui ho risolto questo problema.

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

Mark è la migliore attuazione del DeriveParameters.Come ha detto, assicurarsi di memorizzare nella cache come in questo tutorial.

Tuttavia, credo che questo è un pericoloso modo di risolvere il tuo problema originale di database stored procedure di controllo delle versioni.Se avete intenzione di cambiare la firma di una procedura per l'aggiunta o la rimozione di parametri, è necessario effettuare una delle seguenti operazioni:

  • Il codice in modo compatibile utilizzando valori predefiniti per i nuovi parametri) o semplicemente ignorando param (per eliminato params).Questo assicura che il tuo codice cliente può sempre chiamare in qualsiasi versione di stored procedure.
  • Esplicitamente versione la procedura per nome (così si avrà my_proc e my_proc_v2).Questo assicura che il tuo codice cliente e sprocs rimanere in sincronia.

Basandosi su DeriveParameters per convalidare la versione stored procedure che stai usando mi sembra lo strumento sbagliato per il lavoro, IMHO.

Tutti questi ADO.NET le soluzioni sono a chiedere la libreria di codice per interrogare il database dei metadati sul tuo conto.Se avete intenzione di richiedere che le prestazioni in ogni caso, forse si dovrebbe solo scrivere alcune funzioni di supporto che chiamare

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

O forse anche generare i parametri in base all'param elenco che si ottengono.Questa tecnica permette di utilizzare più versioni di MS SQL e, talvolta, altri ANSI SQL database.

Sono stato con DeriveParameters con .NET 1.1 e 2.0 da un paio di anni, e ha lavorato come un fascino ogni volta.

Ora sto lavorando sul mio primo lavoro con .NET 3.5, e appena trovato e brutta sorpresa:DeriveParameters è la creazione di tutti i parametri con SqlDbType "Variante", invece corretto SqlDbTypes.Questa è la creazione di una SqlException quando si tenta di eseguire SPs con parametri numerici, perché SQL Server 2005 dice che sql-tipi di variante non può essere implictily convertito in int (o smallint, o numerico) valori.

Ho appena provato lo stesso codice con .NET CF 2.0 e SQL Server 2000, e ha funzionato come previsto, assegnando il corretto SqlDbType per ogni i parametri.

Avevo testato .NET 2.0 applicazioni su SQL Server 2005 Database, quindi non è un Server SQL problema, quindi deve essere qualcosa legato con .NET 3.5

Tutte le idee?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top