【问题标题】:Procedure or function 'xyz' has too many arguments specified过程或函数“xyz”指定的参数过多
【发布时间】:2013-02-05 16:40:46
【问题描述】:

我知道这种类型的问题在 SO 上至少被问了十几次,但我已经浏览了我可以在这里找到的所有以前的问题和答案,但我发现没有一个适用。我在我的页面上使用了几个 FormView 对象,现在想要添加编辑其中一个的选项。 FormView 由链接到存储过程的 SqlDataSource 填充,因此我创建了一个存储过程来更新记录并将其添加到 SqlDataSource,现在看起来像这样:

<asp:SqlDataSource ID="TestSqlDataSource" runat="server" 
                   SelectCommandType="StoredProcedure" 
                   ConnectionString="<%$ ConnectionStrings:development %>" 
                   SelectCommand="usp_GetNewTestDetails" 
                   UpdateCommand="usp_UpdateTest" 
                   UpdateCommandType="StoredProcedure" 
                   onupdating="TestSqlDataSource_Updating">
    <SelectParameters>
        <asp:SessionParameter SessionField="TestID" Name="TestID"/>
    </SelectParameters>
    <UpdateParameters>
        <asp:Parameter Name="testId" Type="Int32"/>
        <asp:Parameter Name="testerLicense" Type="Int32" />
        <asp:Parameter Name="premiseOwner" Type="String" />
        <asp:Parameter Name="premiseAddress" Type="String" />
        <asp:Parameter Name="premiseCity" Type="String" />
        <asp:Parameter Name="premiseState" Type="String" />
        <asp:Parameter Name="premiseZip" Type="String" />
        <asp:Parameter Name="protectionType" Type="String" />
        <asp:Parameter Name="testType" Type="String" />
        <asp:Parameter Name="repairs" Type="String" />
        <asp:Parameter Name="notes" Type="String" />
        <asp:Parameter Name="testDate" Type="DateTime" />
        <asp:Parameter Name="employerName" Type="String" />
        <asp:Parameter Name="employerAddress" Type="String" />
        <asp:Parameter Name="phoneNumber" Type="String" />
        <asp:Parameter Name="emailAddress" Type="String" />
        <asp:Parameter Name="dataEntryName" Type="String" />
        <asp:Parameter Name="dataEntryPhone" Type="String" />
        <asp:Parameter Name="signature" Type="String" />
        <asp:Parameter Name="entryDate" Type="DateTime" />
    </UpdateParameters>
</asp:SqlDataSource>

当我尝试更新记录时,我收到一条错误消息,提示我的查询中有太多参数。我已经三重检查了我的代码中的参数是否与我的存储过程中的参数完全匹配(名称、编号甚至顺序)。

在尝试寻找答案时,我遇到了this post,它引用了this site(不得不访问archive.org,因为原件似乎已失效)。我应用了他们建议的将参数添加到trace 函数的方法。我发现在我的存储过程中,选择过程中有一些“查找”值不在更新过程中。我要更新的表只有测试人员的 ID,但用户也想看到他们的名字,所以它引用了那个表,但是在 FormView 中,这些字段在编辑模式下是只读的,所以他们可以不要试图改变它。所有其他参数都排成一行……只有那些查找值是关闭的。

我认为通过包含要传递的特定参数列表,它只会使用这些参数,但这似乎是不正确的。现在我很困惑,因为我已经指定了参数,而且我看不到它们被选择存储过程中的参数覆盖的任何地方。我在哪里告诉它不要使用那些只读值?

我不想将它们从原始存储过程中删除,因为用户将需要它们。到目前为止,我想出的一种解决方法是将它们添加到存储过程中,然后永远不要使用它们。尽管我相当肯定这会起作用,但它只是掩盖问题而不是解决问题。


编辑:附加代码,每个请求

这是将参数输出到trace函数的方法:

protected void TestSqlDataSource_Updating(object sender, SqlDataSourceCommandEventArgs e)
{
    for (int i = 0; i < e.Command.Parameters.Count; i++)
    {
        Trace.Write(e.Command.Parameters[i].ParameterName);
        if (e.Command.Parameters[i].Value != null)
        {
            Trace.Write(e.Command.Parameters[i].Value.ToString());
        }
    }
}

这是用于更新的存储过程:

ALTER PROCEDURE [dbo].[usp_UpdateTest]
    @testId INT ,
    @testerLicense INT ,
    @premiseOwner VARCHAR(50) ,
    @premiseAddress VARCHAR(150) ,
    @premiseCity VARCHAR(50) ,
    @premiseState VARCHAR(2) ,
    @premiseZip VARCHAR(10) ,
    @protectionType VARCHAR(11) ,
    @testType VARCHAR(2) ,
    @repairs VARCHAR(200) ,
    @notes VARCHAR(300) ,
    @testDate DATETIME ,
    @employerName VARCHAR(50) ,
    @employerAddress VARCHAR(150) ,
    @phoneNumber VARCHAR(25) ,
    @emailAddress VARCHAR(60) ,
    @dataEntryName VARCHAR(50) ,
    @dataEntryPhone VARCHAR(25) ,
    @signature VARCHAR(50) ,
    @entryDate DATETIME
AS 
    BEGIN
        SET NOCOUNT ON;

        UPDATE  dbo.Tests
        SET     TesterLicense = @testerLicense ,
                PremiseOwner = @premiseOwner ,
                PremiseAddress = @premiseAddress ,
                PremiseCity = @premiseCity ,
                PremiseState = @premiseState ,
                PremiseZip = @premiseZip ,
                ProtectionType = @protectionType ,
                TestType = @testType ,
                Repairs = @repairs ,
                Notes = @notes ,
                TestDate = @testDate ,
                EmployerName = @employerName ,
                EmployerAddress = @employerAddress ,
                PhoneNumber = @phoneNumber ,
                EmailAddress = @emailAddress ,
                DataEntryName = @dataEntryName ,
                DataEntryPhone = @dataEntryPhone ,
                Signature = @signature ,
                EntryDate = @entryDate 
        WHERE TestID = @testId
    END

【问题讨论】:

  • 检查是否有拼写错误或数据类型转换错误?
  • @RuchiRahulDoshi 是的。我将两组参数复制到 Excel 中并逐行比较。这是这里这个非常常见的问题中最常见的问题,所以我非常小心地确保它们是准确的。使用trace 显示它传递的所有参数后,我可以确定它实际上传递了太多参数,但我不知道如何关闭它。
  • 如果您不介意,请在此处粘贴您的“usp_UpdateTest”和“TestSqlDataSource_Updating”。
  • @RuchiRahulDoshi 添加了请求的代码。
  • 我可以建议你一件事,即为 _updating 事件上的每个更新参数一一指定它,例如 e.Command.Parameters["@testerLicense"].Value = value - 所以如果有是一个问题,它需要更多的参数,它会受到 no 的限制。此处指定的参数。

标签: asp.net stored-procedures formview


【解决方案1】:

最终我自己解决了这个问题。这与 Visual Studio 根据存储过程的架构为我创建模板这一事实有关。当模板自动生成时,&lt;EditItemTemplate&gt; 部分中的每个文本框都会像这样生成:

<asp:TextBox ID="TestIDTextBox" runat="server" Text='<%# Bind("TestID") %>'/>

原来是Bind 语句导致了这种情况。 VS 自动为使用Bind 填充的任何字段创建一个参数。尽管我被引导相信&lt;UpdateParameters&gt; 部分应该覆盖它,但实际上恰恰相反。通过将这些字段上的代码从 Bind 更改为 Eval,我能够阻止这几个只读字段传回其参数:

<asp:TextBox ID="TestIDTextBox" runat="server" Text='<%# Eval("TestID") %>'/>

现在完美运行。


附录:

发现这也会在另一个方向上导致同样的问题。如果您将不想编辑的字段标记为 Eval 但它需要包含在更新中(例如行 ID),它将不起作用,这一次是因为参数太少。我现在想知道&lt;UpdateParameters&gt; 部分的目的是什么,因为它似乎没有遵循任何内容......

【讨论】:

  • 我尝试了您的解决方案,将 Bind 替换为 Eval。它不再给我错误“过程或函数 'xyz' 指定了太多参数”,但数据没有更新
  • @ThandoTee 您不想用Eval 替换所有 Bind 语句,只有少数不应该更新数据的语句。 Eval 是只读命令,因此不会更新这些字段。
  • 感谢您发布您提出的解决方案。我不是 ASP 程序员,但它可以让我在 SQL Server 出现错误时帮助其他人。
【解决方案2】:

您可以在 OnDeleting 事件 (e.Command.Parameters.RemoveAt(i)) 等期间删除不需要的参数。

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 2014-02-08
    • 2015-12-10
    • 2016-02-22
    相关资源
    最近更新 更多