Programmatically Retrieving a Stored Procedure's Parameters 获取Sql Server 存储过程参数
Introduction
Stored procedures in SQL Server are similar to methods in C# and Visual Basic code. They encapsulate one or more statements into a single, parameterized construct. Both stored procedures and methods are a form of code reuse and their use help developers adhere to the DRY principle (Don't Repeat Yourself). But the similarities don't end there. The .NET Framework has a feature called Reflection that enables developers to programmatically retrieve a list of methods for a given class, along with their input parameters and return types. It's also possible to programmatically determine what stored procedures exist in a database, along with each stored procedure's input and output parameters.
Being able to programmatically retrieve a database's stored procedures and determine their parameters are useful in a handful of scenarios. For example, code generators like CodeSmith and the Typed DataSet feature in Visual Studio use these techniques to determine the code to construct to call each stored procedure. These techniques are also useful for allowing ad-hoc stored procedure execution from a page on your website, which can be a useful tool for administrators.
This article shows how to retrieve a list of stored procedures in a database and how to enumerate a selected stored procedure's input and output parameters. We'll also look at how to let the user visiting the page pick a stored procedure, enter values for its parameters, and execute and view the resulting output. Read on to learn more!
An Overview of the Demo Application
The download available at the end of this article includes a web page with a DropDownList Web control enumerating the stored procedures in the website's database. Selecting a stored procedure form the DropDownList causes a postback. On postback the stored procedure's input and output parameters are each displayed in a BulletedList control. In addition, the input parameters are listed in a two-column GridView: the first column lists each parameter's name, while the second has a TextBox control. The user visiting the page can enter values for the input parameters into these TextBoxes and then click the "Execute Stored Procedure" Button. Doing so displays the results in another GridView further down on the page.
The following screen shot shows this demo page in action.
The DropDownList at the top of the page lists the stored procedures in the database. In the screen shot below I have selected the aspnet_Membership_GetAllUsers
stored procedure, which is one of the stored procedures used by the SqlMembershipProvider
. (For more information on ASP.NET's Membership feature, read Examining ASP.NET's Membership, Roles, and Profile.)
The selected stored procedure's input and output parameters are enumerated in bulleted lists. Note that there are three input parameters for this stored procedure: @ApplicationName
, @PageIndex
, and @PageSize
. These input parameters are listed alongside TextBoxes in a GridView further down in the page. A user can enter values for these parameters, click the "Execute Stored Procedure" button, and see the results in a GridView at the bottom of the page. Granted, the GridView contains rather raw-looking, unformatted data, but the data is there nevertheless.
The remainder of this article looks at how various portions of this demo were implemented.
Retrieving a List of Stored Procedures
Every Microsoft SQL Server database includes a number of system tables that catalog the various objects that comprise the database, including the database's tables (and their columns), its triggers, its stored procedures, its UDFs, and so on. The "core" system table, and the one that contains a list of the database's stored procedures, is named
sysobjects
. Each stored procedure is represented as a row in sysobjects
. Likewise, each table and constraint and view and so on are represented by rows in this table. The different database objects can be differentiated by the value in the sysobjects.type
column - stored procedures have a type
value of P
. The following SQL query returns the name of every stored procedure in the database:
SELECT name
FROM sysobjects
WHERE type = 'P'
The DropDownList in the demo is populated by a SqlDataSource control that runs the above query. It's that simple.
(For more information on using the sysobjects
table see Using the sysobjects
Table; for more on working with data in an ASP.NET page be sure to read Accessing and Updating Data in ASP.NET.)
Retrieving a Stored Procedure's Parameters
Once a stored procedure has been selected, how do we retrieve its parameters? While this information can be retrieved from SQL Server's system tables, there's an easier way: by calling the
SqlCommandBuilder
class's DeriveParameters
method. This method accepts a SqlCommand
object as its input and populates the SqlCommand
object's Parameters
collection with the specified stored procedure's parameters. The following code illustrates the SqlCommandBuilder.DeriveParameters
method in action. (Note: While this article shows Visual Basic code, the demo available for download at the end of this article includes both a VB and C# version.)
' ... Create SqlConnection object
Dim myCommand As New SqlCommand
myCommand.Connection = myConnection
myCommand.CommandText = stored procedure name
myCommand.CommandType = Data.CommandType.StoredProcedure
myConnection.Open()
SqlCommandBuilder.DeriveParameters(myCommand)
myConnection.Close()
' ...
While I don't show the code in the above snippet, the first step is to create a valid SqlConnection
object to the database (which I named myConnection
in the code above). Next create a SqlCommand
object, and associate it with the SqlConnection
object. Set the CommandText
property to the name of the stored procedure whose parameters you want and set the CommandType
property to StoredProcedure
. All that remains is to open a connection to the database and call the SqlCommandBuilder.DeriveParameters
method, passing in the SqlCommand
object. This populates the passed-in SqlCommand
object's Parameters
collection with the specified stores procedure's parameter information.
The Parameters
property is a collection of SqlParameter
objects. Each SqlParameter
object represents a parameter in a parameterized query or stored procedure. The most germane properties of the SqlParameter
class are:
ParameterName
- the name of the parameter.SqlDbType
- the parameter's data type.Direction
- indicates whether the parameter is an input parameter, is an output parameter, or can serve as both an input and output parameter. As discussed in Retrieving Scalar Data from a Stored Procedure, output parameters are useful for returning scalar values from a stored procedure.Value
- the parameter's value.
Once you have the parameters you can close the connection to the database and work with the parameters. The following code snippet continued the code from above by enumerating the returned parameters, displaying each parameter (along with its data type) in the appropriate BulletedList control depending on whether the parameter serves as an input or output parameter.
' ...
blInputParameters.Items.Clear()
blOutputParameters.Items.Clear()
For Each param As SqlParameter In myCommand.Parameters
If param.Direction = Data.ParameterDirection.Input OrElse param.Direction = Data.ParameterDirection.InputOutput Then
blInputParameters.Items.Add(param.ParameterName & " - " & param.SqlDbType.ToString())
Else
blOutputParameters.Items.Add(param.ParameterName & " - " & param.SqlDbType.ToString())
End If
Next
Prompting the User for Input Parameter Values and Executing the Stored Procedure With Those Values
In addition to the two BulletedList controls the demo page also includes a GridView named
gvParameters
that lists the selected stored procedure's input parameters along with a TextBox for each parameter. In particular, this GridView is programmatically bound to a list of SqlParameter
objects (namely, the set of input parameters returned by SqlCommandBuilder.DeriveParameters
) and is composed of two fields: - A BoundField that displays each
SqlParameter
object'sParameterName
property, and - A TemplateField that contains a TextBox control named
ParameterValue
.
gvParameters
GridView's DataKeyFields
property is set to ParameterName
. The page also includes an "Execute Stored Procedure" Button control and another GridView for the stored procedure results. This results GridView is named gvResults
. When the "Execute Stored Procedure" Button is clicked the following code runs:
' ... Create SqlConnection object
Dim myCommand As New SqlCommand
myCommand.Connection = myConnection
myCommand.CommandText = stored procedure name
myCommand.CommandType = Data.CommandType.StoredProcedure
'Get the parameter values from the grid
For Each gvRow As GridViewRow In gvParameters.Rows
'Determine the parameter name
Dim paramName As String = gvParameters.DataKeys(gvRow.RowIndex).Value.ToString()
Dim paramValue As Object = DBNull.Value
'Get the TextBox in the row
Dim paramValueTextBox As TextBox = CType(gvRow.FindControl("ParameterValue"), TextBox)
If Not String.IsNullOrEmpty(paramValueTextBox.Text) Then
paramValue = paramValueTextBox.Text
End If
'Add the parameter name/value pair to the SqlCommand
myCommand.Parameters.AddWithValue(paramName, paramvalue)
Next
myConnection.Open()
gvResults.DataSource = myCommand.ExecuteReader()
gvResults.DataBind()
myConnection.Close()
End Using
The code starts by configuring a SqlCommand
object that will execute the specified stored procedure. In this case we don't need to go off and programmatically determine the stored procedure's parameters because they are already encompassed by the gvParameters
GridView. Each row in the gvParameters
GridView is enumerated and the parameter's name and user-entered value are grabbed and added to the SqlCommand
object's Parameters
property via the AddWithValue(name, value)
method.
After the parameters have been added to the SqlCommand
object the results are bound to the gvResults
GridView. That's all there is to it!
Conclusion
Programmatically retrieving the list of stored procedures in a database and those stored procedures' parameters are quite easy tasks. The database provides both the stored procedures and their parameters through system tables. Additionally, the parameters for a stored procedure can also be retrieved via the .NET Framework's
SqlCommandBuilder.DeriveParameters
method. The demo available at the end of this article implements a quick and dirty dynamic reporting system. In short, it allows the visitor to execute any stored procedure on the database through a single page. Granted, the results are ugly and there's nothing stopping the visitor from executing any stored procedure she chooses, but such a page, when limited to a section accessible only to administrators, might be useful. In fact, with a little more effort it is possible to enhance this functionality to create a more user-friendly and secure general purpose reporting page. A future article will explore such functionality in greater detail.
Happy Programming!
Attachments
Further Reading
sysobjects
Table