【问题标题】:Error: Procedure or function expects parameter which was not supplied错误:过程或函数需要未提供的参数
【发布时间】:2016-04-01 05:32:24
【问题描述】:

目前,我在 Visual Studio 中的程序将我的数据从我的转发器动态添加到我的数据库中。

现在我需要添加我在中继器之外手动收集的 ID、EventId 和 FormId。

我需要添加这个:

 sqlCmd.Parameters.Add("@EventId", SqlDbType.Int).Value = eventId;
 sqlCmd.Parameters.Add("@FormId", SqlDbType.Int).Value = formId;

但是,我的代码是如何设置的,当我添加以下代码时会出错:

附加信息:过程或函数“spInsFormRegistrant” 需要未提供的参数“@EventId”。

工作代码(已注释掉错误代码):

 protected void BtnSubmit_Click(object sender, EventArgs e)
 {
            using (SqlConnection sqlConn = new SqlConnection(ConfigurationManager.ConnectionStrings["Events2"].ConnectionString))
            {
                sqlConn.Open();

                using (SqlCommand sqlCmd = new SqlCommand())
                {

                   //sqlCmd.Parameters.Add("@EventId", SqlDbType.Int).Value = eventId;
                   //sqlCmd.Parameters.Add("@FormId", SqlDbType.Int).Value = formId;
                    foreach (RepeaterItem rpItem in RepeaterForm.Items)
                    {
                        Label lblDisplayName = rpItem.FindControl("lblDisplayName") as Label;
                        Label lblColumnName = rpItem.FindControl("lblColumnName") as Label;
                        TextBox txtColumnValue = rpItem.FindControl("txtColumnValue") as TextBox;

                        if (txtColumnValue != null)
                        {
                            sqlCmd.Connection = sqlConn;
                            sqlCmd.CommandType = CommandType.StoredProcedure;
                            sqlCmd.CommandText = "spInsFormRegistrant";
                            sqlCmd.Parameters.Clear();

                            sqlCmd.Parameters.Add("@ColumnName", SqlDbType.NVarChar).Value = lblColumnName.Text;
                            sqlCmd.Parameters.Add("@ColumnValue", SqlDbType.NVarChar).Value = txtColumnValue.Text;

                        sqlCmd.ExecuteNonQuery();
                        }
                    }
                }
            }
            PnlNone.Visible = false;
            PnlExist.Visible = false;
            PnlSuccess.Visible = true;
            PnlFail.Visible = false;
        }

所以我只需要知道在哪里添加@EventId@FormId 以使其正常运行。每次我尝试它,它都不起作用。为了不产生错误,我必须遗漏一些小东西。或者可能是我的存储过程有问题...?

存储过程

ALTER PROCEDURE [dbo].[spInsFormRegistrant]
    -- Add the parameters for the stored procedure here
     @EventId int,
     @FormId int,
     @ColumnName varchar(100),
    @ColumnValue varchar(100)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
     declare @Query nvarchar(4000)
    declare @ParmDefinition nvarchar(500);

    set @Query = 'INSERT into Registrant(DateCreated,EventId,FormId,'+ (@ColumnName) +') values (CURRENT_TIMESTAMP, @EventId, @FormId, @ColumnValue)'
    set @ParmDefinition = N'@ColumnValue varchar(100)'
    exec sp_executesql @Query, @ParmDefinition, @ColumnValue = @ColumnValue

END

【问题讨论】:

    标签: c# asp.net sql-server stored-procedures repeater


    【解决方案1】:

    您没有为 eventID 和 FormID 添加参数,但您应该尝试使用不同的方法。不要每次都创建参数。您可以在进入 foreach 循环之前只创建一次它们,然后在循环内只更改它们的值

    // This part never changes so, set it up just one time before the loop
    sqlCmd.Connection = sqlConn;
    sqlCmd.CommandType = CommandType.StoredProcedure;
    sqlCmd.CommandText = "spInsFormRegistrant";
    sqlCmd.Parameters.Add("@EventId", SqlDbType.Int).Value = eventId;
    sqlCmd.Parameters.Add("@FormId", SqlDbType.Int).Value = formId;
    
    // These twos change inside the loop, so we don't need the value here
    sqlCmd.Parameters.Add("@ColumnName", SqlDbType.NVarChar);
    sqlCmd.Parameters.Add("@ColumnValue", SqlDbType.NVarChar);
    
    
    foreach (RepeaterItem rpItem in RepeaterForm.Items)
    {
        Label lblDisplayName = rpItem.FindControl("lblDisplayName") as Label;
        Label lblColumnName = rpItem.FindControl("lblColumnName") as Label;
        TextBox txtColumnValue = rpItem.FindControl("txtColumnValue") as TextBox;
    
        if (txtColumnValue != null)
        {
            sqlCmd.Parameters["@ColumnName"].Value = lblColumnName.Text;
            sqlCmd.Parameters["@ColumnValue"].Value = txtColumnValue.Text;
            sqlCmd.ExecuteNonQuery();
        }
    }
    

    当然你不需要打电话给Parameters.Clear

    那么在将参数传递给存储过程中的 sp_executesql 调用的方式中存在问题。该系统存储过程要求您为查询中使用的每个参数设置数据类型以及这些参数的初始化列表。

    你应该写

    ...
    -- Insert statements for procedure here
    declare @Query nvarchar(4000)
    declare @ParmDefinition nvarchar(500);
    
    set @Query = 'INSERT into Registrant(DateCreated,EventId,FormId,'+ 
                 (@ColumnName) +') values (CURRENT_TIMESTAMP, @EventId, @FormId, @ColumnValue)'
    set @ParmDefinition = N'@ColumnValue varchar(100), @EventID int, @FormID int'
    exec sp_executesql @Query, @ParmDefinition, 
                       @ColumnValue = @ColumnValue,
                       @EventID = @EventID,
                       @FormID = @FormID
    

    【讨论】:

    • 谢谢史蒂夫!好的,这可行,但现在我收到错误:必须声明标量变量“@EventId”。我想也许我的存储过程可能是原因,但我不确定。
    • 是的,问题在于如何将参数传递给 sp_executesql。我会把它添加到答案中
    • 这个定义好,我拿不下来。
    • 太棒了!这解决了错误。现在的最后一个问题是将每个 @ColumnValue 提交到一个新行中。所有这些都应该在一行中。
    • 对不起,我不明白。 一行是什么意思?
    【解决方案2】:

    您正在清除参数:

    sqlCmd.Parameters.Clear();
    

    你需要一遍又一遍地添加它们:

    foreach (RepeaterItem rpItem in RepeaterForm.Items)
    {
        Label lblDisplayName = rpItem.FindControl("lblDisplayName") as Label;
        Label lblColumnName = rpItem.FindControl("lblColumnName") as Label;
        TextBox txtColumnValue = rpItem.FindControl("txtColumnValue") as TextBox;
    
        if (txtColumnValue != null)
        {
            sqlCmd.Connection = sqlConn;
            sqlCmd.CommandType = CommandType.StoredProcedure;
            sqlCmd.CommandText = "spInsFormRegistrant";
            sqlCmd.Parameters.Clear();  //that's fine, keep it
    
            //just put them in here
            sqlCmd.Parameters.Add("@EventId", SqlDbType.Int).Value = eventId;
            sqlCmd.Parameters.Add("@FormId", SqlDbType.Int).Value = formId;
    
            sqlCmd.Parameters.Add("@ColumnName", SqlDbType.NVarChar).Value = lblColumnName.Text;
            sqlCmd.Parameters.Add("@ColumnValue", SqlDbType.NVarChar).Value = txtColumnValue.Text;
    
        sqlCmd.ExecuteNonQuery();
        }
    }
    

    【讨论】:

    • 谢谢。我试过了,现在我得到了错误:必须声明标量变量“@EventId”。
    猜你喜欢
    • 2011-02-05
    • 2013-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多