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