在 C# 中对大型网格视图进行排序内存不足问题

本文关键字:排序 内存不足 问题 视图 网格 大型 | 更新日期: 2023-09-27 18:34:54

我的'高级'程序员将网格数据存储在会话变量中,以便对其进行排序。

每隔一天,我们不得不重新启动服务器,因为它开始挂断。我觉得这是因为所有这些会话变量都在内存中浮动。

这是对数据进行排序的最佳方式吗?是否有最佳实践?我们必须使用存储过程,因为这是他的规则。Web应用程序真的很慢,我对SQL的了解不足以帮助加快速度。

关于会话变量是否是要走的路的任何想法?有没有更好的方法?

加载数据方法

SqlConnection conn = new SqlConnection (ConfigurationManager.AppSettings ["ConnectionString"].ToString ());
SqlCommand cmd = conn.CreateCommand ();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "RandomStoredProdcedureName";
try 
{
    DataTable GridData = new DataTable ();
    conn.Open ();
    using (SqlDataAdapter Sqlda = new SqlDataAdapter (cmd)) 
    {
       Sqlda.Fill (GridData);
    }
    //Persist the table in the Session object. (for sorting)
    Session ["GridData"] = GridData;
    gvDetails.DataSource = GridData;
    gvDetails.DataBind ();
}
catch (Exception ex) 
{
    Removed for brevity 
} 
finally 
{
    if (conn != null) {
    conn.Close ();
}
}

排序方法

protected void gvDetails_Sorting (object sender, GridViewSortEventArgs e) {
            //Retrieve the table from the session object.
            DataTable GridData = Session ["GridData"] as DataTable;
            if (GridData != null) {
                //Sort the data.
                GridData.DefaultView.Sort = e.SortExpression + " " + GetSortDirection (e.SortExpression);
                gvDetails.DataSource = GridData;
                gvDetails.DataBind ();
            }
        }

在 C# 中对大型网格视图进行排序内存不足问题

用户查看的记录数不可能超过网格显示的行数 - 如果您的网格有 25 行,则任何超过 25 行的内容都是浪费内存/CPU 时间来处理。(请记住,这些数字不是"绝对的" - 某些应用程序可能需要更多行,有些可能需要更少。它还取决于用户查看数据并理解数据的程度。有些用户一次处理几行效果更好,有些用户需要多行 - 这甚至可能是用户偏好,但底线是拉取一个巨大的结果集几乎总是浪费。

在给定时间从数据库中提取的数据不应超过网格中可以显示的行数。排序应在数据库中完成,以便您只能返回实际需要的行子集。这最大限度地减少了 Web 服务器和数据库服务器之间的网络流量,并最大限度地减少了 Web 服务器上的内存使用,因为您只将数据存储在实际需要的视图/会话状态中。

如果使用视图状态来存储数据(这比使用Session更好,因为只要用户使用网格查看特定页面,您就会存储数据(,则该数据将发送到浏览器 - 您还将以这种方式最小化 Web 服务器和浏览器之间的网络流量。

如果用户尝试以不同的方式对数据进行排序或转到另一个页面,只需重复上述过程并根据新的页面索引和/或新的排序字段抓取新行。

编辑

我刚刚注意到您在问题下添加了一条评论,即您通常有 15 个用户并返回 50-1000 行。除非您的 Web 服务器内存非常少(或者除非数据库中的行很大(,否则不太可能导致内存不足错误。是否在会话变量中存储其他大型结果集?

我认为排序可以在SQL中完成。但我们也必须看到 SP。我从不将数据表保留在会话中,我认为这不是一个好方法。

如果数据太大,无法在开发人员每次需要时从数据库中获取数据,他/她可以创建一个视图并从该视图中获取数据。它会快得多

只需改用视图状态即可。

ViewState["GridData"] = GridData;

如果您能告诉我们网格的大小,也会有所帮助?

我看不到数据表的处置位置,您有问题。我的建议是做这样的事情

public void GetData()
{
    using(var conn = new SqlConnection (ConfigurationManager.AppSettings ["ConnectionString"].ToString ()))
    {
        SqlCommand cmd = conn.CreateCommand ();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = "RandomStoredProdcedureName";
        conn.Open ();
        try {
        using(var GridData = new DataTable ())
        {
            using (SqlDataAdapter Sqlda = new SqlDataAdapter (cmd))
            {
                Sqlda.Fill (GridData);
            }
            //Persist the table in the Session object. (for sorting)
            Session ["GridData"] = CREATE_YOUR_OWN_OBJECTS_FROM_THE_DT(GridData);
        }

        } catch (Exception ex) {
        Removed for brevity 
        } finally {
        if (conn != null) {
        conn.Close ();
        }
        }
    }
}

当然有更好的方法来做到这一点,然后你应该实现排序,但我敢打赌问题出在 IDisposable 对象那里根本没有处理过