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