【问题标题】:Bulk Edit Update Multiple Rows in ASP.Net GridView using CheckBoxes使用复选框批量编辑更新 ASP.Net GridView 中的多行
【发布时间】:2018-05-01 07:40:54
【问题描述】:

you can see VT_AClReport Table design 在下面的 HTML 标记中,我有一个包含 3 列的简单 ASP.Net GridView。

第一列包含 CheckBox,第二列分别包含文件夹的显示 ID 和访问路径的标签,第三列分别包含文件夹的显示和编辑状态的标签和 DropDownList。

这里我用GridView配合分页来显示数据,数据大概有几百万行。 当我点击提交按钮更新复选框选中的行时,执行时间太长,无法更新表中的行。

例如:5000 行 = 26 分钟。 谁能帮我解决这个问题并减少执行时间以在几秒钟内更新所有记录。

请看代码:

        <asp:GridView ID="gvACLReport" runat="server" AutoGenerateColumns="False"CssClass="mgrid" EmptyDataText="No Records Exists..." DataKeyNames="ACLId" ShowFooter="True" HorizontalAlign="Center" Width="100%" AllowPaging="True" EnableSortingAndPagingCallback="True" PageSize="500" AllowSorting="True" Visible="False" onpageindexchanging="gvACLReport_PageIndexChanging"                                        EnableSortingAndPagingCallbacks="True">
            <AlternatingRowStyle CssClass="mgridalt" />
            <PagerSettings PageButtonCount="10000" />
            <PagerStyle CssClass="gridview" HorizontalAlign="Center"></PagerStyle>
            <Columns>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <asp:CheckBox ID="chkAllACLReport" runat="server" AutoPostBack="true" OnCheckedChanged="OnCheckedChanged" />
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:CheckBox ID="chkACLReport" runat="server" AutoPostBack="true" OnCheckedChanged="OnCheckedChanged"/>
                    </ItemTemplate>
                    <ItemStyle Width="20px" />
                </asp:TemplateField>

                <asp:TemplateField HeaderText="ACL Id">
                    <ItemTemplate>
                        <asp:Label ID="lblACLId" runat="server" Text='<%# Eval("ACLId") %>'></asp:Label>
                    </ItemTemplate>
                    <ItemStyle Width="20px" />
                </asp:TemplateField>

                <asp:TemplateField HeaderText="Access Path">
                    <ItemTemplate>
                        <asp:TextBox ID="lblAccessPathACL" runat="server" Rows="3" Width="400px" Text='<%# Eval("AccessPath") %>'ReadOnly="True" TextMode="MultiLine" BorderStyle="None" BorderWidth="0px" BackColor="Transparent"></asp:TextBox>
                    </ItemTemplate>
                    <ItemStyle Width="150px" />
                </asp:TemplateField>

                <asp:TemplateField HeaderText="Directory Name">
                    <ItemTemplate>
                        <asp:TextBox ID="lblDirectoryName" runat="server" Rows="3" Width="400px" Text='<%# Eval("DirectoryName") %>'ReadOnly="True" TextMode="MultiLine" BorderStyle="None" BorderWidth="0px" BackColor="Transparent"></asp:TextBox>                              
                    </ItemTemplate>
                    <ItemStyle Width="150px" />
                </asp:TemplateField>


                        <asp:TemplateField HeaderText="User Group">
                                                            <ItemTemplate>
                                                                <asp:Label ID="lblUserGroup" runat="server" Text='<%# Eval("UserGroup") %>'></asp:Label>                              
                                                            </ItemTemplate>
                                                            <ItemStyle Width="150px" />
                                                        </asp:TemplateField>  
            </Columns>
            <HeaderStyle CssClass="mgridheader" />
            <RowStyle CssClass="mgriditem" />
        </asp:GridView>

//Please check this the table contain the drop down list to update the status and submit and clear button 
      <table id ="tableChangeStatus" align="center" width="100%" 
         class="body style1" cellspacing="4" style="border-color: #808080;
         border-style: solid; border-width: 1px; table-layout: auto;" 
         runat="server" visible="False">

               <tr runat="server">
                       <td align="left" runat="server">
                               Status:
                       </td>
                       <td runat="server">
                                                    <asp:DropDownList ID="ddlChangeStatus" AutoPostBack="True" AppendDataBoundItems="True"
                                                        runat="server" Width="200px" DataSourceID="SDSChangeStatus" DataTextField="Status"
                                                        DataValueField="StatusId">
                                                        <asp:ListItem Text="--Select--" Value="0"></asp:ListItem>
                                                    </asp:DropDownList>
                                                    <asp:SqlDataSource ID="SDSChangeStatus" runat="server" ConnectionString="<%$ ConnectionStrings:gtsgeneralconn %>"
                                                        SelectCommand="VT_getStatusList" SelectCommandType="StoredProcedure"></asp:SqlDataSource>
                                                    <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server" ControlToValidate="ddlChangeStatus"
                                                        Display="Dynamic" ErrorMessage="Select Status" InitialValue="0" SetFocusOnError="True">*</asp:RequiredFieldValidator>
                                                </td>
                                            </tr>
                                            <tr runat="server">
                                                <td align="center" colspan="2" runat="server">
                                                    <asp:Button ID="btnChangeStatus" runat="server" Text="Submit" CausesValidation="False" 
                                                       onclick="btnChangeStatus_Click"
                                                     />
                                                    <asp:Button ID="btnChangeClear" runat="server" Text="Clear" 
                                                        CausesValidation="False" onclick="btnChangeClear_Click"
                                                     />
                                                </td>
                                            </tr>
                                            </table>

代码背后:

         protected void ChangeStatusGlobalSensitiveNonSensitiveReport() 
         {
             int rowsAffected = 0;
             foreach (GridViewRow row in gvGlobalSensitive.Rows)
             {
                if (row.RowType == DataControlRowType.DataRow)
                {
                    bool isChecked = row.Cells[0].Controls.OfType<CheckBox().FirstOrDefault().Checked;
                    if (isChecked)
                    {
                           using (SqlConnection con = new SqlConnection(cs))
                           {
                                    cmd = new SqlCommand("VT_ACLReportChangeStatus", con);
                                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                                    cmd.CommandTimeout = 3600;
                                    cmd.Parameters.AddWithValue("@ChangeStatus", ddlChangeStatus.SelectedItem.Text.ToString());
                                    cmd.Parameters.AddWithValue("@ACLId", row.Cells[1].Controls.OfType<Label>().FirstOrDefault().Text);
                                    con.Open();
                                    cmd.ExecuteNonQuery();
                                    con.Close();
                                    rowsAffected++;
                             }
                        }
                    }
                    lblUpdatedRowsMsg.Text = rowsAffected + " Rows updated!!";
                    lblUpdateMsg.Text = "Detail Saved Successfully!!";            
                    gvGlobalSensitive.Visible = false;
                    tableChangeStatus.Visible = false;
                    divReport.Visible = false;
                }
                if (rowsAffected == 0) 
                {
                    lblUpdateMsg.Text = "Please select the check box to update the status!!";
                    lblUpdatedRowsMsg.Text = rowsAffected + " Rows updated!!";
                }
            }

存储过程

 ALTER PROCEDURE [dbo].[VT_ACLReportChangeStatus]
    (
        @ChangeStatus nvarchar(50)=null,
        @ACLId int
        )
    AS
    // Exec VT_ACLReportChangeStatus 'Complete',34 
    BEGIN   
    UPDATE VT_ACLReport SET Status = @ChangeStatus WHERE ACLId = @ACLId     
    End

【问题讨论】:

  • 你能发布存储过程吗?你能尝试只使用一个连接吗? if (row.RowType == DataControlRowType.DataRow) 不需要。
  • 是的,我上传了存储过程,你可以查看@Emanuele
  • 您在某处提到过提交页面,那么提交按钮在哪里?
  • 您要更新的表VT_ACLReport 上的主键是什么?
  • 我在表中创建了 ACLID 作为可索引键,并且所有更新操作都仅参考 ACLId 键执行。

标签: c# asp.net sql-server gridview


【解决方案1】:

用下面给出的 T-SQL 替换存储过程中的 UPDATE 语句。

我假设 ACLId 是具有聚集索引的主键,并且您在 Status 列上有一个索引。如果您在 ACLId 上创建另一个索引并在其中包含列 Status 会更好,因为这将真正加快 UPDATE 语句中的查找速度。

在此 T-SQL 中,更新以 1000 条记录为单位进行,而不是更新整个数据集。您可以尝试将 100 的值更改为 500 甚至更小,以得出最佳更新批次。

DECLARE @numberOfRowsUpdated INT = 1000, @maxRowsToUpdate INT = 1000;  

BEGIN TRY    
  BEGIN TRAN

  WHILE (@numberOfRowsUpdated > 0)
  BEGIN

     UPDATE TOP (@maxRowsToUpdate) VT_ACLReport SET Status = @ChangeStatus 
          WHERE ACLId = @ACLId and Status <> @ChangeStatus;

      SET @numberOfRowsUpdated  = @@ROWCOUNT;
  END

  if @@trancount > 0
      COMMIT TRAN

END TRY
BEGIN CATCH
    if @@trancount > 0
      ROLLBACK TRAN

    -- log and raise error
END CATCH

【讨论】:

  • 感谢@sunil,我尝试使用上述 T-SQL 查询,但执行时间相同。没有区别..实际上我正在处理复选框是否选中,如果选中,唯一的查询将执行..因此对于每一行查询都在运行,这会增加执行时间。
  • 好的。那么可以从不同的网格视图行更新相同的行吗?
  • 那么对于每一行,大概需要26分钟?
  • 不是每一行,要更新完整的 5000 行,需要 26 分钟。
  • 不一样,不会更新,我在数据进入网格视图之前应用了过滤器。更新将仅适用于特定行。但由于逐一执行行会增加整体执行时间。
【解决方案2】:
I solved this problem by maintaining View State, Preserving all checked checkbox state and storing in view state.

then concatenating all the id's in one variable.

    protected void gvACLReport_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        GridView gv = (GridView)sender;
        PaginateTheData(gv);
        gvACLReport.PageIndex = e.NewPageIndex;
        UpdateACLReport();
    }
 protected void PaginateTheData(GridView gvAll) 
    {
        List<int> list = new List<int>();
        if (ViewState["SelectedRecords"] != null)
        {
            list = (List<int>)ViewState["SelectedRecords"];
        }
        foreach (GridViewRow row in gvAll.Rows)
        {
            CheckBox chk = (CheckBox)row.FindControl("chkReport");

            var selectedKey = int.Parse(gvAll.DataKeys[row.RowIndex].Value.ToString());

            if (chk.Checked)
            {

                if (!list.Contains(selectedKey))
                {

                    list.Add(selectedKey);
                }
            }

            else
            {
                if (list.Contains(selectedKey))
                {

                    list.Remove(selectedKey);
                }
            }
        }

        ViewState["SelectedRecords"] = list;

    }

}

    protected void ChangeStatusACLReport()
        {
           int rowsAffected = 0;
            List<int> list = ViewState["SelectedRecords"] as List<int>;
            string ACLId = "";
            if (list != null)
            {
                foreach (int id in list)
                {
                    ACLId = ACLId + id.ToString() + ",";
                    rowsAffected++;
                }
            }
            else
            {
                foreach (GridViewRow row in gvACLReport.Rows)
                {
                    if (row.RowType == DataControlRowType.DataRow)
                    {
                        bool isChecked = row.Cells[0].Controls.OfType<CheckBox>().FirstOrDefault().Checked;
                        if (isChecked)
                        {
                            ACLId = ACLId + row.Cells[1].Controls.OfType<Label>().FirstOrDefault().Text + ",";
                            rowsAffected++;
                        }
                    }
                }
            }
            if (rowsAffected == 0)
            {
                lblUpdateMsg.Text = "Please select the check box to update the status!!";
                lblUpdatedRowsMsg.Text = rowsAffected + " Rows updated!!";
            }
            else
            {
                ACLId = ACLId.ToString().Trim(',');
                using (SqlConnection con = new SqlConnection(cs))
                {
                    cmd = new SqlCommand("VT_ACLReportChangeStatus", con);
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    cmd.CommandTimeout = 3600;
                    //cmd.Parameters.AddWithValue("@ChangeStatus", ddlChangeStatus.SelectedItem.Text.ToString());
                    //cmd.Parameters.AddWithValue("@ACLId", ACLId);
                    cmd.Parameters.Add(new SqlParameter("@ACLId", SqlDbType.NVarChar,-1));
                    cmd.Parameters.Add(new SqlParameter("@ChangeStatus", SqlDbType.NVarChar, 50));
                    cmd.Parameters["@ACLId"].Value = ACLId;
                    cmd.Parameters["@ChangeStatus"].Value = ddlChangeStatus.SelectedItem.Text.ToString();
                    con.Open();
                    cmd.ExecuteNonQuery();
                    con.Close();
                }
                lblUpdatedRowsMsg.Text = rowsAffected + " Rows updated!!";
                lblUpdateMsg.Text = "Detail Saved Successfully!!";
                gvACLReport.Visible = false;
                tableChangeStatus.Visible = false;
                divReport.Visible = false;
              //  DeleteCompleteACLReport(ACLId);
            }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    • 2020-01-13
    • 2014-10-18
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 2015-10-09
    相关资源
    最近更新 更多