【问题标题】:System.OutOfMemoryException being thrownSystem.OutOfMemoryException 被抛出
【发布时间】:2010-06-22 08:48:29
【问题描述】:

我的代码中出现 system.outofmemory 异常:

While r1.Read()
                    menu1id = r1("id")
                    db.AddInParameter(command2, "@menu1id", DbType.Int32, menu1id)
                    r2 = db.ExecuteReader(command2)
                    command2.Parameters.Clear()
                    menu1heading = r1("Heading")
                    If r1("url") IsNot Nothing And r1("moduleid") = 0 Then
                        url = r1("url").ToString

                        If InStr(url, "file:///") > 0 Then
                            Dim builder As New StringBuilder
                            builder.Append("<a href=")
                            builder.Append(r1("url"))
                            builder.Append(" target=")
                            builder.Append(r1("urltarget"))
                            builder.Append(">")
                            builder.Append(menu1heading)
                            builder.Append("</a>")
                            level1.Add(builder.ToString)
                        Else
                            Dim builder As New StringBuilder
                            builder.Append("<a href=http://")
                            builder.Append(r1("url"))
                            builder.Append(" target=")
                            builder.Append(r1("urltarget"))
                            builder.Append(">")
                            builder.Append(menu1heading)
                            builder.Append("</a>")
                            level1.Add(builder.ToString)
                        End If
                    Else
                        Dim builder As New StringBuilder
                        builder.Append("<a href=~/Default.aspx?id=")
                        builder.Append(r1("id"))
                        builder.Append(">")
                        builder.Append(menu1heading)
                        builder.Append("</a>")
                        level1.Add(builder.ToString)
                    End If


                    While r2.Read
                        menu2id = r2("id")
                        db.AddInParameter(command3, "@menu2id", DbType.Int32, menu2id)
                        r3 = db.ExecuteReader(command3)
                        command3.Parameters.Clear()
                        menu2heading = r2("Heading")

                        If r2("url") IsNot Nothing And r2("moduleid") = 0 Then
                            Dim builder As New StringBuilder
                            builder.Append("<a href=http://")
                            builder.Append(r2("url"))
                            builder.Append(" target=")
                            builder.Append(r2("urltarget"))
                            builder.Append(menu2heading)
                            builder.Append("</a>")
                            level2.Add(builder.ToString)
                        Else
                            Dim builder As New StringBuilder
                            builder.Append("<a href=~/Default.aspx?id=")
                            builder.Append(r2("id"))
                            builder.Append(">")
                            builder.Append(menu2heading)
                            builder.Append("</a>")
                            level2.Add(builder.ToString)
                        End If


                        While r3.Read
                            menu3heading = r3("Heading")
                            menu3id = r3("id")
                            If r3("url") IsNot Nothing And r3("moduleid") = 0 Then
                                Dim builder As New StringBuilder
                                builder.Append("<a href=http://")
                                builder.Append(r3("url"))
                                builder.Append(" target=")
                                builder.Append(r3("urltarget"))
                                builder.Append(">")
                                builder.Append(menu3heading)
                                builder.Append("</a>")
                                level3.Add(builder.ToString)
                            Else
                                Dim builder As New StringBuilder
                                builder.Append("<a href=~/Default.aspx?id=")
                                builder.Append(r3("id"))
                                builder.Append(">")
                                builder.Append(menu3heading)
                                builder.Append("</a>")
                                level3.Add(builder.ToString)
                            End If

                        End While

                        r3.Close()
                    End While

                    r2.Close()
                End While

                r1.Close()
            End While
            r0.Close()

请您告诉我如何诊断和修复此异常?非常感谢。

【问题讨论】:

    标签: asp.net memory-leaks loops out-of-memory nested-repeater


    【解决方案1】:

    将逻辑更改为一次性返回所有菜单项的单个 sql 查询会好得多,然后迭代此数据集以构建菜单。

    你可以试试

    SELECT id, DepartmentID, GroupingID, Heading, OrderID, 
    Publish, moduleid, url, urltarget
    FROM Grouping 
    WHERE (DepartmentID = 0 AND Publish <> 0)
    ORDER BY OrderID
    

    这将返回上述查询返回的所有数据,包括确定树结构的 GroupingID。您应该能够将结果加载到对象集合中,然后使用 LINQ 查询它们以构建您的菜单。

    将您的数据复制到以下类中,然后在它们的列表中使用 LINQ:

    public class DataClass
    {
    public string Id { get; set; }
    public string DepartmentID { get; set; }
    public string GroupingID { get; set; }
    public string Heading { get; set; }
    public string OrderID { get; set; }
    public string Publish { get; set; }
    public string Moduleid { get; set; }
    public string Url { get; set; }
    public string Urltarget { get; set; }
    
    public List<DataClass> Children { get; set; }
    
    public DataClass(string id, string departmentID, string groupingID, string heading, string orderID, string publish, string moduleid, string url, string urltarget)
    {
        Id = id;
        DepartmentID = departmentID; 
        GroupingID = groupingID;
        Heading = heading;
        OrderID = orderID; 
        Publish = publish;
        Moduleid = moduleid;
        Url = url;
        Urltarget = urltarget;
    }
    }
    

    【讨论】:

    • 我遇到的问题是,每次循环运行时,每条记录都使用前一条记录中的 id 来确定菜单中的父级。是否可以使用数据集实现此结果? .我是使用数据集 / linq 的新手
    • 绝对。您的数据集中有 GroupingID,因此每条记录都“知道”它属于哪个父项。我刚刚向 DataClass 添加了一个 Children 属性。只是一个想法,但它可能会让你思考它是如何工作的。想想呈现锚标记的方法的可能性,或者可能是一个单独的转换器类,它接受你的数据类并生成菜单
    • 抱歉,我刚刚注意到您的示例是在 VB 中,而我的答案是在 C# 中。转换应该不会太难吧??
    • 您会将所有数据读入该类的实例列表中。此时,您可以迭代列表,构建同一类的新 FinalList。如果(GroupingID == 0)在哪里找到顶级项目,则将其添加到最终列表中。然后再次循环,在最终列表中查找具有 GroupingID 的对象,然后将其添加到相应对象的子对象中。然后再一次,直到你一无所有。这不会将您限制在 4 个级别,并且会更容易调试
    【解决方案2】:

    该方法使用了大量的字符串连接,每个连接都会创建大量新的临时字符串对象,这些对象会占用您的堆空间。这可以通过使用StringBuilder 创建连接字符串来避免。 StringBuilder 不仅在连接大量字符串时更节省内存,而且速度也更快:

    Dim builder As New StringBuilder()
    builder.Append("<a href=")
    builder.Append("r0("url"))
    builder.Append("target=")
    builder.Append(r0("urltarget"))
    builder.Append(menu0heading)
    builder.Append("</a>")
    
    Dim str as String
    str = builder.ToString()
    

    注意:正如 David Neale 在 cmets 中指出的那样,在这种情况下,最好使用 TagBuilder(或 XmlWriter)来创建 HTML/XML 文档树。

    【讨论】:

    • OP 没有提到使用 MVC,所以我只是发表评论。 TagBuilder 类可以进一步简化这类功能。
    猜你喜欢
    • 1970-01-01
    • 2011-02-07
    • 2013-12-28
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多