C# 使用复选框批量编辑更新ASP.Net GridView中的多行

C# 使用复选框批量编辑更新ASP.Net GridView中的多行,c#,asp.net,sql-server,gridview,C#,Asp.net,Sql Server,Gridview,在下面的HTML标记中,我有一个简单的ASP.NETGridView,有3列 第一列包含复选框,第二列包含分别用于显示文件夹ID和访问路径的标签,第三列包含分别用于显示和编辑文件夹状态的标签和下拉列表 这里我使用带分页的GridView来显示数据,数据大约有数百万行当我单击“提交”按钮更新选中的复选框行时,更新表中的行所需的执行时间太长。 例如:对于5000行=26分钟。 谁能帮我解决这个问题,并缩短执行时间,在几秒钟内更新所有记录 请参阅代码: <asp:GridView

在下面的HTML标记中,我有一个简单的ASP.NETGridView,有3列

第一列包含复选框,第二列包含分别用于显示文件夹ID和访问路径的标签,第三列包含分别用于显示和编辑文件夹状态的标签和下拉列表

这里我使用带分页的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>

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

我假设ACLId是具有聚集索引的主键,并且您在Status列上有一个索引。如果您在ACLId上创建另一个索引并在其中包含列状态,您会感觉更好,因为这将真正加快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
声明@numberOfRowsUpdated INT=1000,@maxRowsToUpdate INT=1000;
开始尝试
开始训练
而(@numberOfRowsUpdated>0)
开始
UPDATE TOP(@maxRowsToUpdate)VT_ACL报告集状态=@ChangeStatus
其中ACLId=@ACLId,Status@ChangeStatus;
SET@numberOfRowsUpdated=@@ROWCOUNT;
结束
如果@trancount>0
提交传输
结束尝试
开始捕捉
如果@trancount>0
回滚传输
--记录并引发错误
端接
我通过维护视图状态、保留所有复选框状态和存储在视图状态解决了这个问题。
然后将所有id连接到一个变量中。
受保护的void gvACLReport\u PageIndexChanging(对象发送方,GridViewPageEventArgs e)
{
GridView gv=(GridView)发送方;
分页数据(gv);
gvACLReport.PageIndex=e.NewPageIndex;
updatealreport();
}
受保护的无效分页数据(GridView gvAll)
{
列表=新列表();
如果(ViewState[“SelectedRecords”]!=null)
{
列表=(列表)视图状态[“SelectedRecords”];
}
foreach(gvAll.Rows中的GridViewRow行)
{
复选框chk=(复选框)row.FindControl(“chkReport”);
var selectedKey=int.Parse(gvAll.DataKeys[row.RowIndex].Value.ToString());
如果(已检查)
{
如果(!list.Contains(selectedKey))
{
list.Add(selectedKey);
}
}
其他的
{
if(list.Contains(selectedKey))
{
列表。删除(selectedKey);
}
}
}
ViewState[“SelectedRecords”]=列表;
}
}
受保护的无效ChangeStatusACLReport()
{
int rowsAffected=0;
List List=ViewState[“SelectedRecords”]作为列表;
字符串ACLId=“”;
如果(列表!=null)
{
foreach(列表中的int-id)
{
ACLId=ACLId+id.ToString()+“,”;
rowsAffected++;
}
}
其他的
{
foreach(gvACLReport.Rows中的GridViewRow行)
{
if(row.RowType==DataControlRowType.DataRow)
{
bool isChecked=row.Cells[0]。Controls.OfType().FirstOrDefault().Checked;
如果(已检查)
{
ACLId=ACLId+row.Cells[1].Controls.OfType().FirstOrDefault().Text+;
rowsAffected++;
}
}
}
}
if(rowsAffected==0)
{
lblUpdateMsg.Text=“请选中复选框以更新状态!!”;
lblupdatedrowsmg.Text=rowsAffected+“行已更新!!”;
}
其他的
{
ACLId=ACLId.ToString().Trim(',');
使用(SqlConnection con=newsqlconnection(cs))
{
cmd=新的SqlCommand(“VT_ACLReportChangeStatus”,con);
cmd.CommandType=System.Data.CommandType.StoredProcess;
cmd.CommandTimeout=3600;
//cmd.Parameters.AddWithValue(“@ChangeStatus”,ddlChangeStatus.SelectedItem.Text.ToString());
//cmd.Parameters.AddWithValue(“@ACLId”,ACLId);
Add(新的SqlParameter(“@ACLId”,SqlDbType.NVarChar,-1));
cmd.Parameters.Add(新的SqlParameter(“@ChangeStatus”,SqlDbType.NVarChar,50));
cmd.Parameters[“@ACLId”].Value=ACLId;
cmd.Parameters[“@ChangeStatus”].Value=ddlChangeStatus.SelectedItem.Text.ToString();
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
lblupdatedrowsmg.Text=rowsAffected+“行已更新!!”;
lblUpdateMsg.Text=“详细信息保存成功!!”;
gvACLReport.Visible=false;
tableChangeStatus.Visible=false;
divReport.Visible=false;
//DeleteCompleteClReport(ACLId);
}

您能发布存储过程吗?您能尝试只使用一个连接吗?如果不需要(row.RowType==DataControlRowType.DataRow)。是的,我上载了存储过程,您可以检查@EmanuelYou提到的一些
 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
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
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);
            }