批量编辑使用CheckBoxes更新ASP.Net GridView中的多行

时间:2017-11-17 13:51:27

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

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

包含CheckBox的第一列,第二列分别包含文件夹的显示ID和访问路径的Label,第三列包含Label和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

2 个答案:

答案 0 :(得分:0)

使用下面给出的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

答案 1 :(得分:0)

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);
            }