JScript 内存泄露、获取 XmlDataDocument 以及 ASPX 包含页面

来源: 作者: 2007-11-22 出处:pcdog.com

.net  access  xml  

  原文出处:MSDN Magazine Apr. 2004(Web Q&A)
 

我创建了一个 Web 应用程序,它的界面功能十分丰富。这个程序主要是由 XML、XSLT 和 JScript 构建的。我遇到了一个大问题就是它消耗了大量的内存,但我不知道为何会出现这种情况。我使用 闭合函数(closures:一种在函数中定义函数的方法)来实现事件处理,我怀疑就是使用它才导致的内存泄露。

答案: 用闭合函数作为事件处理的实现,是导致内存泄露的普遍原因。闭合函数总是允许内部函数访问外部函数的参数和变量。
  Eric Lippert 的 Blog (译者:Web Log 的简称)上有一篇关于闭合函数和内存泄露的文章:What are closures?。然而请注意,在这篇文章截稿前仍旧有一个错误没有改正。当微软IE浏览器导航到某一页时 ,循环引用会使效率下降的说法并不正确。几年前当这个问题第一次出现时,并没有造成很大影响,但是IE团队发现它影响很多现存的页面,所以还是关闭了此项功能 。
  创建一个界面功能丰富的 Web 应用程序,就像你前面所叙述的。首先这不是一个好想法,它会导致软件过于臃肿以至于泄漏内存。这方面内容请参见:Thin To My Chagrin
  根据函数是否被动态地创建来谨慎地使用闭合函数语义。如果函数是被动态地创建,例如通过 new 操作符来声明,那么你应该寻找一种方法来避免这么做。使用New表达式生成的函数相当于使用Eval表达式,而Eval表达式会影响性能。它会执行编译过程。如果这个函数需要被动态地创建,并且可以不需要使用闭合函数语 义,那么将发生器放到一个辅助函数中,该辅助函数没有那些会形成循环引用的参数。这样,所产生的函数将会在一些不需要回指向IE对象模型的事件前结束。如果这个函数是静态创建的,不需要使用闭合函数语 义,就不要将它嵌入到其它函数中。并且重构你的应用程序直到你脱离这种困境。

我怎样才能确定 XmlDataDocument与 DataSet 是关联的?如果我采用下面的代码来从 DataSet 中创建一个XmlDataDocument: 便很容易获得与这个 XmlDataDocument 相一致的 DataSet,如下所示:

DataSet dataset = xmlData.DataSet;

  然而,一旦XmlDataDocument与DataSet的关联关系建立起来,我怎样才能确定这个XmlDataDocument确实来自于DataSet呢?这很重要,因为如果我试图为DataSet创建第二个XmlDataDocument时,会抛出一个异常。 我依赖于DataSet。在许多方法中, 我以XML的格式来操作数据. 当DataSet在方法间被传递时,XmlDataDocumnet是否被创建了,它的引用是什么,我需要知道调用这些方法时其内部操作的相关知识。

答案: 没有简单的方法。很不幸,DataSet不提供任何公有的API来检查一个 XmlDataDocument 是否与之相关或者提供它的一个引用。 然而,作为一个折中的办法,你可以选择以下两条之一来解决:
  1. 总是在一个Try-Catch块中实例化 XmlDataDocument,并且捕获异常变量,如果DataSet已经与一个 XmlDataDocument 相关联,那么就会抛出异常。
  2. 利用程序跟踪判断 DataSet 实例是否已经与一个 XmlDataDocument 相关联。

  之后你可以使用 DataSet.ExtendedProperty 创建一个用户自定义属性来保持对一个不知道是否被关联的 XmlDataDocument 的跟踪。
  例如,使用如下代码来注册一个关联操作:

DataSet.ExtendedProperty.Add("XmlDataDocumentAttached", "1")

  这个扩展属性将会在实例化XmlDataDocument之前被检查。

  如果你可以确定不会通过Web服务或远程调用来序列华化 DataSet, 那么你就可以注册这个与之关联的 XmlDataDocument 实例作为 DataSet 的属性值(如果一个对象作为 DataSet 的扩展属性,那么它的序列化会被中断)。

我有一个运行了两年的Web应用程序,他有一个所有页面都要使用的标题菜单。它是按照下面的方式被ASP页面调用的:

#include file="../Include/UDBMenuAccess.asp"

  我现在为这个站点添加了两个新的.aspx页面,并且我想要包含这个菜单。可是,我的新页面不是认不出包含的这个菜单就是产生很多错误。难道无法将一个asp页面包含在一个 aspx 页面中么?有解决办法么? 

答案: 将这个旧的包含文件转换为一个 .ascx 文件,之后将其放入你的 aspx 页面。包含页并没有失效,他们现在被更简单地称作自定义控件并且更加强大。记住,编写这些控件与编写工程所使用的语言必须相同。 如果你决定采用C#,并且你有一些采用VisualBasic 编写的包含页面,那么你需要将他们转换为C#。请看下面这个例子,如 Figure 1。 现在,你可以使用如下方法将它包含在aspx页面中了。在aspx页面的顶部声明它。 

<%@ Register TagPrefix="thisSite" TagName="copyright"

 src="includes/cr.ascx" %>

之后,当你想在页面中放置它时,使用如下元素来调用它:

<thisSite:copyright id="copyright1" runat="server">

</thisSite:copyright>

我有一段代码,如下:

SqlConnection sqlConnection;

CloseConnection()

{

    sqlConnection.Close();

    sqlConnection.Dispose();

    sqlConnection = null; 

}

  调用SqlConnection的Dispose方法是否可以将其从连接池中移除呢?还是要同时调用Dispose和Close方法呢? 我正在使用.NET Framework 1.1。我读了一片文章,上面说在.NET Framework 1.0中调用Dispose方法可以从连接池中移除连接,然而在.NET Framework 1.1却不行,是这样么?

答案: Dispose方法不会从连接池中移除连接,它会将连接放回池中,如果以前没有这么做的话。对于.NET Framework  1.0 和 1.1, 你可以基本认为Close 与 Dispose是同等的。作为你的问题的回答, Dispose 在.NET Framework  1.0 和 1.1中是相同的。总是调用Close或Dispose方法来释放一个SqlConnection 可以使你避免许多基于垃圾回收和清除方面的问题。如果你想处理的更好,你可以像下面所展示的代码那样使用Using关键字:

using ( SqlConnection conn = new SqlConnection(CONNECT_STRING) )

{

    try

    {

        conn.Open();

        // Use conn in here...

    }

    catch ( SqlException sqlEX )

    {

        // Log errors here...

    }

} //一旦超出这个括号的范围SqlConnection对象的Dispose方法会被调用


  更多关于SqlConnection的编程实例,请参见 Data Access Application Block for .NET.

是否有从XSD文件中获取XML schema 命名空间URI信息的内置方法呢?还是需要我手动的去分析这个schema文件呢?我想让用户选择一批XSD文件,并自动载入它们的schema命名空间URI。而不用要求他们输入过多的信息。

答案: 你有至少三种选择来解决你的问题。第一,你可以将schema装载入一个DOM,并使用XPath来选择/xs:schema/@targetNamespace结点(xs对应于http://www.w3.org/2001/XMLSchema)。 第二,你可以将schema装载入一个schema对象模型(SOM),通过调用System.Xml.Schema.XmlSchema.Read方法并读取 argetNamespace属性来实现。最后一个选择是使用 XmlTextReader来分析schema中的第一个元素,检查{http://www.w3.org/2001/XMLSchema},并读取 targetNamespace属性。
  这些方法实现起来都十分简单。然而,最后一个是到目前为止最高效的,无论从空间利用率还是从时间利用率来说,因为前两个方法都需要运行第三个方法,增加了额外的负担。

System.Data.SqlClient是怎么在批量的SQL语句中处理分号分隔符的?批处理看起来工作的很好,可是,在.N

上一篇:JScript 方法 - fromCharCode 方法
下一篇:JScript中正则表达函数的说明与应用