0

我正在尝试使用几个必需参数和几个可选参数调用存储过程。在我出现之前,程序的开头是这样编写的:

USE [MYDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SP_GetStudents]
(
    @SortOrder          varchar(50),
    @SortColumn         varchar(150),
    @SortLetter         varchar(10),
    @Status             varchar(250),
    @PageIndex              int,
    @PageSize           int,
    @User_ID            int,
    @Reference_No           varchar(50) = NULL,
    @First_Name         varchar(50) = NULL,
    @Middle_Name            varchar(50) = NULL,
    @Last_Name          varchar(50) = NULL
)
As
BEGIN
-- other stuff here

一切似乎都很好。然后我在末尾添加了另一个参数:

USE [MYDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SP_GetStudents]
(
    @SortOrder          varchar(50),
    @SortColumn         varchar(150),
    @SortLetter         varchar(10),
    @Status             varchar(250),
    @PageIndex              int,
    @PageSize           int,
    @User_ID            int,
    @Reference_No           varchar(50) = NULL,
    @First_Name         varchar(50) = NULL,
    @Middle_Name            varchar(50) = NULL,
    @Last_Name          varchar(50) = NULL,
    @ContextID          int = NULL
)
As
BEGIN
-- other stuff here

现在它坏了。当我使用 ADO.NET 通过设置带有参数的命令对象来调用存储过程时,它会引发异常,因为我没有设置@ContextID参数。

知道为什么吗?我想如果我将它设置为默认值NULL,那么它实际上是完全可选的。

更新:这是 SqlCommand 的设置方式,我可以在这里表示它:

SqlCommand cmd = new SqlCommand("SP_GetStudents");
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter();
param.ParameterName = "@SortOrder";
param.Value = sortOrder;
param.Direction = ParameterDirection.Input;

SqlParameter param2 = new SqlParameter();
param2.ParameterName = "@SortColumn";
param2.Value = sortColumn;
param2.Direction = ParameterDirection.Input;
cmd.Parameters.Add(param);
cmd.Parameters.Add(param2);
cmd.Parameters.Add(new SqlParameter("@SortLetter", sortLetter));
cmd.Parameters.Add(new SqlParameter("@Status", status));
cmd.Parameters.Add(new SqlParameter("@PageIndex", pageIndex));
cmd.Parameters.Add(new SqlParameter("@PageSize", pageSize));

// here, the code splits a search expression into multiple parameters, looping over a switch statement like this:

foreach (string token in tokens)
{
    switch(token)
    {
        case "Reference_No":
            cmd.Parameters.Add(new SqlParameter("@Reference_No", (object)value ?? DBNull.Value));
            break;
        case "First_Name":
            cmd.Parameters.Add(new SqlParameter("@First_Name", (object)value ?? DBNull.Value));
            break;
        case "Last_Name":
            cmd.Parameters.Add(new SqlParameter("@Last_Name", (object)value ?? DBNull.Value));
            break;
        case "Middle_Name":
            cmd.Parameters.Add(new SqlParameter("@Middle_Name", (object)value ?? DBNull.Value));
            break;
        case "Generation":
            cmd.Parameters.Add(new SqlParameter("@Generation", (object)value ?? DBNull.Value));
            break;
        case "ContextID":
            cmd.Parameters.Add(new SqlParameter("@ContextID", (object)value ?? DBNull.Value));
            break;
    }
}

cmd.Parameters.AddWithValue("@User_ID", userID);
// fires off cmd through a DAL

这是例外(类型System.Data.SqlClient.SqlException):

参数化查询 '(@Reference_No varchar(50), @First_Name varchar(5' 需要参数 '@ContextID',但未提供该参数。

我觉得这条消息有点奇怪,因为格式似乎被劫持了。无论如何,在引擎盖下,该命令SqlDataAdapter是通过用于填充 a 的 a执行的DataSetFill在方法执行期间抛出异常。

4

1 回答 1

0

在此http://msdn.microsoft.com/en-us/library/ms187926.aspx链接上,提到了以下行。

每个声明参数的值必须由用户在调用过程时提供,除非定义了参数的默认值或将该值设置为等于另一个参数。如果过程包含表值参数,并且调用中缺少该参数,则传入一个空表。

因此,基于此,我可以说,如果您使用“默认”密钥工作,您的问题将得到解决。

同样在同一页面上,还提到了有关默认值的信息,其中包含以下详细信息。

default 参数的默认值。如果为参数定义了默认值,则可以在不为该参数指定值的情况下执行过程。默认值必须是常量,也可以为 NULL。常量值可以是通配符的形式,使得在将参数传递到过程中时可以使用 LIKE 关键字。请参见下面的示例 C。

默认值仅记录在 sys.parameters.default 列中,用于 CLR 过程。对于 Transact-SQL 过程参数,该列将为 NULL。

谢谢, 吉格

于 2012-07-07T04:47:32.583 回答