2013-07-05 31 views
3

我有一個綁定到SqlDataSource的GridView。我遇到UpdateCommand正在執行的問題,它似乎正在執行兩次。當我遍歷gvChecklist_RowUpdating事件中的代碼時,我看到一切正常運行並且存儲過程被執行。我已經驗證存儲過程正常工作,因爲db表中有新的記錄。當這個事件雖然退出,我得到以下錯誤:被稱爲兩次的SqlDataSource UpdateCommand

Procedure or function usp_TestLogInsert has too many arguments specified.

我看到的數據源更新事件被RowUpdating事件後調用。我試圖取消這個事件以防止多次更新嘗試,但是沒有任何反應,並且GridView保持編輯模式。

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" 
        runat="server"         
        ConnectionString="<%$ ConnectionStrings:AutomationDBConnectionString %>" 
        onupdating="dsChecklist_Updating" > 
    <UpdateParameters> 
    <asp:Parameter Name="Status" DbType="Int32" /> 
    <asp:Parameter Name="TestID" DbType="Int32" /> 
    <asp:Parameter Name="TestedBy" DbType="String" /> 
    <asp:Parameter Name="Notes" DbType="String" /> 
    <asp:Parameter Name="JiraTicket" DbType="String" /> 
    <asp:Parameter Name="Build" DbType="String" /> 
    </UpdateParameters> 
</asp:SqlDataSource> 

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["Status"].DefaultValue = status; 
     dsChecklist.UpdateParameters["TestID"].DefaultValue = testID; 
     dsChecklist.UpdateParameters["TestedBy"].DefaultValue = user; 
     dsChecklist.UpdateParameters["Notes"].DefaultValue = notes; 
     dsChecklist.UpdateParameters["JiraTicket"].DefaultValue = jira; 
     dsChecklist.UpdateParameters["Build"].DefaultValue = build; 

     gvChecklist.DataBind(); 
    } 
    //else //Record already exists in TestLog. UPDATE 
    //{ 
    //TODO 
    //} 
} 

編輯:我使用的SQL Profiler來看看參數在存儲過程中發送的是什麼。即使發生INSERT並創建了新記錄,也會發送一個稱爲ID的額外參數。我從來沒有明確地發送這個參數,但它似乎是因爲我在GridView中有一個名爲ID的BoundField而創建的。 要建立在原始問題上,有沒有辦法讓UpdateCommand忽略這個BoundField,所以它不會自動使用它作爲參數?

+0

你可以發佈'dsChecklist_Updating'的代碼嗎? – Tim

+0

該事件爲空。我在代碼中創建了它,看它是否被擊中。看起來UpdateCommand在我的RowUpdating事件中執行,但是在調用dsChecklist_Updating事件之後。 – Andrew

+0

請將'[Automation]。[manual]。[usp_TestLogInsert]'的TSQL發佈。 – Hogan

回答

1

使用SQL事件探查器後,我看到BoundField ID被隱式添加爲UpdateCommand參數。將此字段更改爲TemplateItem可修復此問題。

     <asp:TemplateField> 
         <ItemTemplate> 
          <asp:TextBox ID="tbId" Text='<%#Eval("ID") %>' ReadOnly="true" runat="server"></asp:TextBox> 
         </ItemTemplate> 
         </asp:TemplateField>