【问题标题】:SqlDataSource Procedure or function expects parameter which was not specifiedSqlDataSource 过程或函数需要未指定的参数
【发布时间】:2013-07-03 19:23:25
【问题描述】:

我有一个 SqlDataSource,我正在尝试向其中添加一个 UpdateCommand,以便在选择 GridView 的更新按钮时调用存储过程。我在后面的代码中执行此操作,因为我需要调用两个过程之一,具体取决于数据库表中是否已经存在记录(插入新的,更新现有的记录)。当我在 RowUpdating 事件中设置 Updateparameters 时,出现以下异常:

过程或函数“usp_TestLogInsert”需要参数“@Status”,但未提供。

这是 ASP 代码和背后的代码。我在后面的代码中明确地创建了参数,所以我不明白为什么会出现这个异常。我已经验证了这些是存储过程所需的相同参数。

C#

protected void gvChecklist_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    SQLConnections sql = new SQLConnections();
    SqlDataSource dsChecklist = (SqlDataSource)LoginView1.FindControl("dsChecklist");
    var dd = (DropDownList)gvChecklist.Rows[e.RowIndex].FindControl("ddStatus");
    var status = dd.SelectedValue;
    var testID = sql.SQLSelectSingle(String.Format("SELECT ID FROM Automation.manual.Tests WHERE Task = '{0}'", (String)e.OldValues["Task"]), "pwautosql01");
    string user = Page.User.Identity.Name;
    string notes = (String)e.NewValues["Notes"];
    string jira = (String)e.NewValues["JiraTicket"];
    var dbID = e.NewValues["ID"];
    string build = "TODO";

    if (dbID == null) //Record does not exist in TestLog, INSERT a new one
    {
        dsChecklist.UpdateCommand = "[Automation].[manual].[usp_TestLogInsert]";
        dsChecklist.UpdateCommandType = SqlDataSourceCommandType.StoredProcedure;
        dsChecklist.UpdateParameters.Add("@Status", TypeCode.Int32, status);
        dsChecklist.UpdateParameters.Add("@TestID", TypeCode.Int32, testID);
        dsChecklist.UpdateParameters.Add("@TestedBy", TypeCode.String, user);
        dsChecklist.UpdateParameters.Add("@Notes", TypeCode.String, notes);
        dsChecklist.UpdateParameters.Add("@JiraTicket", TypeCode.String, jira);
        dsChecklist.UpdateParameters.Add("@Build", TypeCode.String, build);

        dsChecklist.Update();
    }
    //else //Record already exists in TestLog. UPDATE
    //{
        //TODO
    //}
}

ASP

            <asp:UpdatePanel ID="upGridView" runat="server" UpdateMode="Conditional">
            <ContentTemplate>
            <asp:GridView ID="gvChecklist" runat="server" 
                    AutoGenerateColumns="false" DataSourceID="dsChecklist"
                    AutoGenerateEditButton="true" onrowupdating="gvChecklist_RowUpdating">
                <Columns>
                    <asp:TemplateField HeaderText="Status">
                        <ItemTemplate>
                            <asp:Label ID="lblStatus" runat="server" Text='<%#Eval("Status") %>' />
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:DropDownList ID="ddStatus" runat="server" DataTextField="Status" DataValueField="ID" DataSourceID="dsStatus" />
                        </EditItemTemplate>
                    </asp:TemplateField>
                    <asp:BoundField DataField="Division" 
                            HeaderText="Division"
                            readonly="true" />
                    <asp:BoundField DataField="Application"
                            HeaderText="Application"
                            readonly="true" />
                    <asp:BoundField DataField="Task"
                            HeaderText="Task"
                            readonly="true" />
                    <asp:BoundField DataField="TestedBy" HeaderText="Tested By" readonly="true"/>
                    <asp:BoundField DataField="Notes" HeaderText="Notes" ReadOnly="false"/>
                    <asp:BoundField DataField="JiraTicket"
                            HeaderText="JIRA Ticket"
                            readonly="false" />
                    <asp:BoundField DataField="ID" />
                </Columns>
            </asp:GridView>
            </ContentTemplate>
            <Triggers>
            <asp:PostBackTrigger ControlID="gvChecklist" />
        </Triggers>
            </asp:UpdatePanel>
            </td>
        </tr>
    </table>

    <asp:SqlDataSource ID="dsChecklist" SelectCommand=" SELECT l.ID, d.division, c.Context AS Application, t.Task, l.TestedBy, l.Notes, l.JiraTicket, s.Status
                                                        FROM Automation.manual.Tests t
                                                        OUTER APPLY 
                                                            (SELECT TOP 1 *
                                                            FROM Automation.manual.TestLog l
                                                            WHERE l.TestID = t.ID 
                                                            ORDER BY l.Date DESC) l
                                                        INNER JOIN Automation.dbo.Context c ON  c.ID = t.Context
                                                        INNER JOIN Automation.dbo.Division d ON d.ID = t.Division
                                                        LEFT OUTER JOIN Automation.manual.Status s ON s.ID = l.Status"
                                                       UpdateCommand=""
                       runat="server" 
                       ConnectionString="<%$ ConnectionStrings:AutomationDBConnectionString %>"  />

   <asp:SqlDataSource ID="dsStatus" SelectCommand="SELECT ID, Status FROM Automation.manual.Status"                               
                      runat="server" 
                      ConnectionString="<%$ ConnectionStrings:AutomationDBConnectionString %>">
                      </asp:SqlDataSource>

【问题讨论】:

  • 当您单步执行您的代码时,var status 会返回一个实际值吗?
  • 是的。它被分配了一个字符串值。
  • 在黑暗中拍摄,但是当你从 'dd' 中拉出它时尝试将其转换为 Int32,假设状态是你表中的 'int'。我假设它应该是“状态”上的“UpdateParameters.Add”方法中的“int”。我认为这不会是问题,因为您将它作为 var 使用,但确定并没有什么坏处。
  • UpdateParameters 的 value 属性必须是字符串。
  • 你有它作为 TypeCode.Int32。

标签: c# asp.net sqldatasource


【解决方案1】:

您需要在参数名称之前省略@,SqlDataSource会为您添加它。见here

还可以尝试在实例化数据源时添加参数,然后在后面的代码中设置它们的值:

<UpdateParameters>
    <asp:Parameter Name="Status"   Type="Int32" />
    <asp:Parameter Name="TestID"  Type="Int32" />
    <asp:Parameter Name="TestedBy"    Type="String" />
    <asp:Parameter Name="Notes"       Type="String" />
    <asp:Parameter Name="JiraTicket"     Type="String" />
    <asp:Parameter Name="Build" Type="String" />
</UpdateParameters>

然后:

if (dbID == null) //Record does not exist in TestLog, INSERT a new one
{
    dsChecklist.UpdateCommand = "[Automation].[manual].[usp_TestLogInsert]";
    dsChecklist.UpdateCommandType = SqlDataSourceCommandType.StoredProcedure;
    dsChecklist.UpdateParameters["@Status"].Value = status;
    dsChecklist.UpdateParameters["@TestID"].Value = testID;
    dsChecklist.UpdateParameters["@TestedBy"].Value = user;
    dsChecklist.UpdateParameters["@Notes"].Value = notes;
    dsChecklist.UpdateParameters["@JiraTicket"].Value = jira;
    dsChecklist.UpdateParameters["@Build"].Value = build;

    dsChecklist.Update();
}

【讨论】:

  • 这工作并且存储过程执行,我可以看到数据库表中的值。但是当事件退出时,Procedure or function usp_TestLogInsert has too many arguments specified. 被抛出。
  • 您需要清除后续调用的参数或仅更新它们的值。您可能会多次添加它们。
  • 当我打电话给dsChecklist.UpdateParameters.Clear(); 时,原来的问题又出现了。我应该在哪里清除参数以防止它们被再次添加?
  • 抱歉误会了。您可以在通话后清除列表,然后再次添加它们,或者留下它们并更新它们的值。关键是要确保在您即将进行调用时,您拥有正确数量的参数。
  • 你能偶然添加一些示例代码吗?我想我仍然缺少一些东西。我正在事件结束前清除列表,这会引发异常。
猜你喜欢
  • 1970-01-01
  • 2011-02-05
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多