You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET GridView RowUpdating空引用异常及动态UPDATE语句优化问询

关于ASP.NET GridView编辑更新功能的两个问题

问题描述

  1. 在ItemView_OnRowUpdating事件中获取GridView编辑行控件值时,持续抛出NullReferenceException空引用异常,无法正常获取控件值。
  2. 用户编辑行时无需修改所有字段,当前通过逐个判断字段是否为空来构建UPDATE语句,希望找到更优雅的循环实现方式。

原代码

ASPX GridView标记

<asp:GridView ID="ItemView" runat="server" 
     AutoGenerateColumns="false" AllowPaging="true" 
     HorizontalAlign="Center"
     PageSize="10" HeaderStyle-BackColor="#6f263d" 
     HeaderStyle-ForeColor="White" CellPadding="7" CellSpacing="0" 
     DataKeyNames="orderItemId" AllowSorting="True" 
     AlternatingRowStyle-BorderStyle="Solid" AlternatingRowStyle-BackColor="White" 
     AlternatingRowStyle-ForeColor="#6f263d"  AlternatingRowStyle-CssClass="fancylink" 
     Font-Size="Small" RowStyle-BackColor="#63666A" 
     RowStyle-BorderStyle="None" RowStyle-ForeColor="White" 
     SelectedRowStyle-BackColor="#D3D0C8" SelectedRowStyle-ForeColor="Black" 
     Width="100%" 
     OnSelectedIndexChanged="ItemView_SelectedIndexChanged" 
     ShowHeaderWhenEmpty="false" PagerStyle-CssClass="fancylink" 
     PagerStyle-BackColor="#6f263d" PagerStyle-ForeColor="White" 
     PagerSettings-FirstPageText="First Page&nbsp;&nbsp;&nbsp;"  
     PagerSettings-Mode="NextPrevious" PagerSettings-NextPageText="Next Page" 
     PagerSettings-LastPageText="End" PagerSettings-PreviousPageText="Previous Page" 
     PagerStyle-HorizontalAlign="Center" PagerStyle-Width="20%" 
     OnPageIndexChanging="OnPageIndexChanging" 
     OnRowDataBound="ItemView_RowDataBound" 
     OnRowEditing="ItemView_EditRow" 
     OnRowUpdating ="ItemView_OnRowUpdating" 
     BorderStyle="None" 
     OnRowCancelingEdit ="ItemView_RowCancelingEdit" 
     OnRowDeleting="ItemView_DeleteRow" 
     OnSelectedIndexChanging="ItemView_OnSelectedIndexChanging" 
     AutoGenerateSelectButton="False">
    <Columns>
        <asp:TemplateField HeaderText="ID">
            <ItemTemplate>
                <asp:Label ID="lbl_itemId" runat="server" Text='<%#Eval("orderItemId") %>' ReadOnly="True"></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Item Description">
            <ItemTemplate>
                <div style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 400px;">
                    <asp:LinkButton ID="btn_Select" runat="server" Text='<%#Eval("item") %>' ToolTip='<%# Eval("item") %>' CommandName="Select" ItemStyle-HorizontalAlign="Center" />
                </div>
            </ItemTemplate>
        </asp:TemplateField>                        
        <asp:TemplateField HeaderText="PO Num">
            <ItemTemplate>
                <asp:Label ID="lbl_poNum" runat="server" Text='<%#Eval("poNum") %>' NullDisplayText="--"></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txt_poNum" runat="server" Text='<%#Eval("poNum") %>' Width="75px"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Item Amount">
            <ItemTemplate>
                <asp:Label ID="lbl_amount" runat="server" Text='<%#Eval("amount") %>' NullDisplayText="--"></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txt_amount" runat="server" Text='<%#Eval("amount") %>' Width="60px"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Quantity">
            <ItemTemplate>
                <asp:Label ID="lbl_quantity" runat="server" Text='<%#Eval("quantity") %>' NullDisplayText="--" ReadOnly="True"></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Date Ordered">
            <ItemTemplate>
                <asp:Label ID="lbl_ordered" runat="server" Text='<%#Eval("ordered") %>' NullDisplayText="--"></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txt_ordered" runat="server" Text='<%#Eval("ordered") %>' Width="75px"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Date Received">
            <ItemTemplate>
                <asp:Label ID="lbl_received" runat="server" Text='<%#Eval("received") %>' NullDisplayText="--"></asp:Label>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txt_received" runat="server" Text='<%#Eval("received") %>' Width="75px"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Tech Notes">
            <ItemTemplate>
                <div style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 500px;">
                    <asp:Label ID="lbl_techNotes" runat="server" Text='<%#Eval("techNotes") %>' ToolTip='<%# Eval("techNotes") %>' NullDisplayText="--"></asp:Label>
                </div>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txt_techNotes" runat="server" Text='<%#Eval("techNotes") %>' Width="380px"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:LinkButton ID="btn_Edit" runat="server" Text="Edit" CommandName="Edit" ItemStyle-HorizontalAlign="Center"/>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:LinkButton ID="btn_Update" runat="server" Text="Update" CommandName="Update" ItemStyle-HorizontalAlign="Center" />
                <asp:LinkButton ID="btn_Cancel" runat="server" Text="Cancel" CommandName="Cancel" ItemStyle-HorizontalAlign="Center" />
            </EditItemTemplate>
        </asp:TemplateField>
   </Columns>
</asp:GridView>

后台C#代码

protected void ItemView_OnRowUpdating(object sender, GridViewUpdateEventArgs e)
{
    GridViewRow row = ItemView.SelectedRow;
    int itemNum = Convert.ToInt16(ItemView.DataKeys[e.RowIndex].Values[0]);

    string poNum = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_poNum")).Text;
    string amount = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_amount")).Text;
    string quantity = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_quantity")).Text;
    string ordered = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_ordered")).Text;
    string received = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_received")).Text;
    string techNotes = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_techNotes")).Text;


    string updateQuery = "UPDATE OrderItems SET ";
    bool firstField = true;

    if (!string.IsNullOrEmpty(poNum))
    {
        updateQuery += "purchaseOrderNum = @OrderNum";
        firstField = false;
    }

    if (!string.IsNullOrEmpty(amount))
    {
        if (!firstField) updateQuery += ", ";
        updateQuery += "itemAmt = @Amount";
        firstField = false;
    }

    if (!string.IsNullOrEmpty(quantity))
    {
        if (!firstField) updateQuery += ", ";
        updateQuery += "quantity = @Quantity";
        firstField = false;
    }

    if (!string.IsNullOrEmpty(ordered))
    {
        if (!firstField) updateQuery += ", ";
        updateQuery += "dateOrdered = @Ordered";
        firstField = false;
    }

    if (!string.IsNullOrEmpty(received))
    {
        if (!firstField) updateQuery += ", ";
        updateQuery += "dateReceived = @Received";
        firstField = false;
    }

    if (!string.IsNullOrEmpty(techNotes))
    {
        if (!firstField) updateQuery += ", ";
        updateQuery += "techNotes = @TechNotes";
    }

    updateQuery += "WHERE orderItemId = @ID";

    using (SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["ForCustomWebApps"]))
    {
        using (SqlCommand cmd = new SqlCommand(updateQuery, conn))
        {
            cmd.Parameters.AddWithValue("@ID", id);

            if (!string.IsNullOrEmpty(poNum)) 
                 cmd.Parameters.AddWithValue("@OrderNum", poNum);

            if (!string.IsNullOrEmpty(amount)) 
                 cmd.Parameters.AddWithValue("@Amount", amount);

            if (!string.IsNullOrEmpty(quantity)) 
                 cmd.Parameters.AddWithValue("@Quantity", quantity);

            if (!string.IsNullOrEmpty(ordered)) 
                 cmd.Parameters.AddWithValue("@Ordered", ordered);

            if (!string.IsNullOrEmpty(received)) 
                 cmd.Parameters.AddWithValue("@Received", received);

            if (!string.IsNullOrEmpty(techNotes)) 
                 cmd.Parameters.AddWithValue("@TechNotes", techNotes);

            conn.Open();
            cmd.ExecuteNonQuery();
            conn.Close();
        }
    }

    ItemView.EditIndex = -1;
    BindGrid();
}

异常信息

Object reference not set to an instance of an object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:

Line 116: int itemNum = Convert.ToInt16(ItemView.DataKeys[e.RowIndex].Values[0]);
Line 117:
Line 118: string poNum = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_poNum")).Text;


解决方案

问题1:修复空引用异常

空引用的原因有两个:

  1. 使用ItemView.SelectedRow获取编辑行错误,编辑行应该通过ItemView.Rows[e.RowIndex]获取,SelectedRow是用户点击选择按钮后的行,和编辑行不是同一个。
  2. Quantity字段没有定义EditItemTemplate,代码中尝试查找txt_quantity会返回null,导致调用.Text时抛出异常。

修正后的事件代码片段:

protected void ItemView_OnRowUpdating(object sender, GridViewUpdateEventArgs e)
{
    // 获取当前编辑的行
    GridViewRow row = ItemView.Rows[e.RowIndex];
    int itemNum = Convert.ToInt16(ItemView.DataKeys[e.RowIndex].Values[0]);

    // 注意:Quantity字段没有EditItemTemplate,直接从ItemTemplate的Label获取(只读字段)
    string poNum = ((TextBox)row.FindControl("txt_poNum")).Text;
    string amount = ((TextBox)row.FindControl("txt_amount")).Text;
    string quantity = ((Label)row.FindControl("lbl_quantity")).Text;
    string ordered = ((TextBox)row.FindControl("txt_ordered")).Text;
    string received = ((TextBox)row.FindControl("txt_received")).Text;
    string techNotes = ((TextBox)row.FindControl("txt_techNotes")).Text;

    // 后续代码...
}

问题2:优雅构建动态UPDATE语句

通过定义字段映射集合,将控件ID、数据库字段名、参数名关联,循环处理避免重复判断:

protected void ItemView_OnRowUpdating(object sender, GridViewUpdateEventArgs e)
{
    GridViewRow row = ItemView.Rows[e.RowIndex];
    int itemNum = Convert.ToInt16(ItemView.DataKeys[e.RowIndex].Values[0]);

    // 定义字段映射:控件ID -> (数据库字段名, 参数名)
    var fieldMappings = new Dictionary<string, (string DbField, string ParamName)>
    {
        {"txt_poNum", ("purchaseOrderNum", "@OrderNum")},
        {"txt_amount", ("itemAmt", "@Amount")},
        {"txt_ordered", ("dateOrdered", "@Ordered")},
        {"txt_received", ("dateReceived", "@Received")},
        {"txt_techNotes", ("techNotes", "@TechNotes")}
    };

    List<string> setClauses = new List<string>();
    SqlCommand cmd = new SqlCommand();

    // 循环处理每个可编辑字段
    foreach (var mapping in fieldMappings)
    {
        TextBox txt = (TextBox)row.FindControl(mapping.Key);
        if (txt != null && !string.IsNullOrEmpty(txt.Text.Trim()))
        {
            setClauses.Add($"{mapping.Value.DbField} = {mapping.Value.ParamName}");
            cmd.Parameters.AddWithValue(mapping.Value.ParamName, txt.Text.Trim());
        }
    }

    // 处理只读的quantity字段(无需更新可删除此段)
    Label lblQuantity = (Label)row.FindControl("lbl_quantity");
    if (!string.IsNullOrEmpty(lblQuantity.Text.Trim()) && lblQuantity.Text != "--")
    {
        setClauses.Add("quantity = @Quantity");
        cmd.Parameters.AddWithValue("@Quantity", lblQuantity.Text.Trim());
    }

    // 无字段更新直接退出
    if (setClauses.Count == 0)
    {
        ItemView.EditIndex = -1;
        BindGrid();
        return;
    }

    string updateQuery = $"UPDATE OrderItems SET {string.Join(", ", setClauses)} WHERE orderItemId = @ID";
    cmd.CommandText = updateQuery;
    cmd.Parameters.AddWithValue("@ID", itemNum);

    using (SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["ForCustomWebApps"]))
    {
        cmd.Connection = conn;
        conn.Open();
        cmd.ExecuteNonQuery();
        conn.Close();
    }

    ItemView.EditIndex = -1;
    BindGrid();
}

该方案优势:

  • 新增/修改字段仅需更新映射集合,无需重复编写判断逻辑
  • 自动处理字段分隔符,避免手动拼接错误
  • 代码简洁,可维护性更强

内容的提问来源于stack exchange,提问作者Amy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:07:03