JScript 内存泄露、获取 XmlDataDocument 以及 ASPX 包含页面
WEB Q&A...
JScript 内存泄露、获取 XmlDataDocument 以及 ASPX 包含页面
原著:Nancy Michell
翻译:宋文锋
原文出处:MSDN Magazine Apr. 2004(Web Q&A)

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

然而,作为一个折中的办法,你可以选择以下两条之一来解决:
总是在一个Try-Catch块中实例化 XmlDataDocument,并且捕获异常变量,如果DataSet已经与一个 XmlDataDocument 相关联,那么就会抛出异常。
利用程序跟踪判断 DataSet 实例是否已经与一个 XmlDataDocument 相关联。
之后你可以使用 DataSet.ExtendedProperty 创建一个用户自定义属性来保持对一个不知道是否被关联的 XmlDataDocument 的跟踪。
例如,使用如下代码来注册一个关联操作:
DataSet.ExtendedProperty.Add("XmlDataDocumentAttached", "1")
这个扩展属性将会在实例化XmlDataDocument之前被检查。
如果你可以确定不会通过Web服务或远程调用来序列华化 DataSet, 那么你就可以注册这个与之关联的 XmlDataDocument 实例作为 DataSet 的属性值(如果一个对象作为 DataSet 的扩展属性,那么它的序列化会被中断)。

#include file="../Include/UDBMenuAccess.asp"
我现在为这个站点添加了两个新的.aspx页面,并且我想要包含这个菜单。可是,我的新页面不是认不出包含的这个菜单就是产生很多错误。难道无法将一个asp页面包含在一个 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却不行,是这样么?

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.

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

argetNamespace属性来实现。最后一个选择是使用
XmlTextReader来分析schema中的第一个元素,检查{http://www.w3.org/2001/XMLSchema},并读取
targetNamespace属性。
这些方法实现起来都十分简单。然而,最后一个是到目前为止最高效的,无论从空间利用率还是从时间利用率来说,因为前两个方法都需要运行第三个方法,增加了额外的负担。

System.Data.SqlClient是怎么在批量的SQL语句中处理分号分隔符的?批处理看起来工作的很好,可是,在.NET
Framework文档中我没有看到任何一篇关于分号的文档。
下面的代码段
DECLARE @val int
SET @val=10
UPDATE dbo.Foo
SET val=@val
IF (@@ERROR <> 0) GOTO EXIT_SCRIPT
SET @val=20
UPDATE b
SET b.val=@val
FROM dbo.Foo AS f INNER JOIN dbo.Bar AS b ON f.id = b.id
IF (@@ERROR <> 0) GOTO EXIT_SCRIPT
EXIT_SCRIPT:
会与这段代码处理的不同么?
DECLARE @val int;SET @val=10;UPDATE dbo.Foo SET val=@val;IF (@@ERROR <> 0)
GOTO EXIT_SCRIPT;SET @val=20;UPDATE b SET b.val=@val FROM dbo.Foo AS f
INNER JOIN dbo.Bar AS b ON f.id = b.id;IF (@@ERROR <> 0)
GOTO EXIT_SCRIPT;EXIT_SCRIPT:;
在这种批处理中(例如事务处理,存储过程)调用的语句会产生什么不同的结果么?

Server,在客户端不加任何修改。SQL Server 将分号作为合法的分隔符,所以可以正常工作。就SQL Server而言,这两种批处理没有什么不同的。

parentRow.GetChildRows( "relationship name" ) ;
我无法获得被标记为Deleted的返回记录。
可是,我确实需要这些信息。我需要获取那些新增,修改或删除的相关记录。GetChildRows仅仅返回新增和修改的记录,但是不返回被删除的记录。
我试图通过传递可选参数DataRowVersion
parentRow.GetChildRows("relationship name", DataRowVersion.Original);
使其返回那些删除的记录,但是并没有成功。我该怎么做呢?

original, or proposed)中的一种。 他不是记录属性(added, modified, deleted, unchanged)的过滤器
。
要访问那些存在不确定改变属性的记录,你可以使用DataTable。在Select语句中创建一个寻找确定记录的过滤器(例如,FKColumn
= Value),并提供记录属性(例如 Added,ModifiedCurrent, Deleted)。在 Figure 2 种有一些样例代码。
如果你不介意使用数据视图,你也可以使用它。创建子视图并设置相应的记录属性过滤器,代码如下:
DataView vueCustomers = ds.Tables["Customers"].DefaultView;
vueCustomers.Sort = "CustomerID";
DataView vuePendingOrders =
vueCustomers[vueCustomers.Find("ALFKI")].CreateChildView
("Customers_Orders");
vuePendingOrders.RowStateFilter = DesiredRowStates;
Console.WriteLine("ALFKI has {0} pending modified orders",
vuePendingOrders.Count);
如果你有问题或解答,请将其发送到: webqa@microsoft.com。
致谢以下微软开发者提供的专家解答:Jeff Abrams, Kawarjit Bedi, Jeffrey
Brendecke, Lale Divringi, Blaine Dockter, Yves Dolce, Tim Ewald, Michael
Hestness, Eric Lippert, Matt Neerincx, Carl Nolan, Thomas Rahm, David Sceppa,
Larry Sun,Vinayak Tadas。
Figure 1 一个自定义控件
<%@ Control Language="c#" AutoEventWireup="false" Codebehind="cr.ascx.cs"
Inherits="thisSite.includes.cr_B"
TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
<img height="16" src="http://thisSite/images/bar2003.gif" width="748"
border="0"><br>
<table class="betaBorder" width="748" bgColor="#eef1f4">
<tr>
<td class="CenterSmall">?thisSite 2003 -
<a tabIndex="40" target="_blank" href="http:// thisSite /default.aspx"> Home</a> -
<a tabIndex="41" target="_blank" href="http://thisSite/info/contacts.aspx"
target="_parent"> Contacts</a> -
<a tabIndex="42"
target="_blank" href="http://thisSite/info/disclaimer.aspx" target="_blank">
Disclaimer</a>
</td>
</tr>
</table>
Figure 2 获取改变的记录string strConn = "Data Source=(local);Initial
Catalog=Northwind;Trusted_Connection=Yes;";
string strSQL = "SELECT CustomerID, CompanyName, ContactName FROM
Customers WHERE CustomerID LIKE ''A%'';" +
"SELECT OrderID, CustomerID, OrderDate FROM Orders WHERE CustomerID LIKE ''A%''";
SqlDataAdapter da = new SqlDataAdapter(strSQL, strConn);
da.TableMappings.Add("Table", "Customers");
da.TableMappings.Add("Table1", "Orders");
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
DataSet ds = new DataSet();
da.Fill(ds);
ds.Relations.Add("Customers_Orders",
ds.Tables["Customers"].Columns["CustomerID"],
ds.Tables["Orders"].Columns["CustomerID"]);
DataRow row = ds.Tables["Customers"].Rows.Find("ALFKI");
DataRow[] ChildRows = row.GetChildRows("Customers_Orders");
Console.WriteLine("ALFKI has {0} orders", ChildRows.Length);
ChildRows[2].Delete();
ChildRows[4].Delete();
ChildRows[3]["OrderDate"] = DateTime.Today;
ds.Tables["Orders"].LoadDataRow(new Object[]{-1, "ALFKI", DateTime.Today},
false);
DataViewRowState DesiredRowStates = DataViewRowState.Added |
DataViewRowState.ModifiedCurrent | DataViewRowState.Deleted;
DataRow[] ChildPendingChanges = ds.Tables["Orders"].Select("CustomerID =
''ALFKI''", "", DesiredRowStates);
Console.WriteLine("ALFKI has {0} pending modified orders",
ChildPendingChanges.Length);
