Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1568849
  • 博文数量: 884
  • 博客积分: 52280
  • 博客等级: 大将
  • 技术积分: 13060
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-06 09:46
文章分类

全部博文(884)

文章存档

2008年(884)

我的朋友

分类: C/C++

2008-08-06 09:57:01

下载本文示例代码
原文出处: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" %>

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





我有一段代码,如下:

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对应于)。 第二,你可以将schema装载入一个schema对象模型(SOM),通过调用System.Xml.Schema.XmlSchema.Read方法并读取 argetNamespace属性来实现。最后一个选择是使用 XmlTextReader来分析schema中的第一个元素,检查{},并读取 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:;

在这种批处理中(例如事务处理,存储过程)调用的语句会产生什么不同的结果么?

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

我有一个关于ADO.NET中表间关系和已删除记录的问题。当我这么做时:

parentRow.GetChildRows( "relationship name" ) ;

我无法获得被标记为Deleted的返回记录。
  可是,我确实需要这些信息。我需要获取那些新增,修改或删除的相关记录。GetChildRows仅仅返回新增和修改的记录,但是不返回被删除的记录。
  我试图通过传递可选参数DataRowVersion

parentRow.GetChildRows("relationship name", DataRowVersion.Original);

使其返回那些删除的记录,但是并没有成功。我该怎么做呢?

GetChildRows的第二个参数控制你获取的数据的版本,你可以获取(current, 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。

下载本文示例代码
阅读(187) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~