[Oracle]Oracle Access SQL Server类型对照表

mikel阅读(515)

   Access, SQL Server, and oracle数据类型的对应关系

The table below shows the ADO Data Type mapping between Access, SQL Server, and oracle:

DataType Enum Value Access SQLServer Oracle
adBigInt 20   BigInt (SQL Server 2000 +)  
adBinary 128   Binary
TimeStamp
Raw *
adBoolean 11 YesNo Bit  
adChar 129   Char Char
adCurrency 6 Currency Money
SmallMoney
 
adDate 7 Date DateTime  
adDBTimeStamp 135 DateTime (Access 97 (ODBC)) DateTime
SmallDateTime
Date
adDecimal 14     Decimal *
adDouble 5 Double Float Float
adGUID 72 ReplicationID (Access 97 (OLEDB)), (Access 2000 (OLEDB)) UniqueIdentifier (SQL Server 7.0 +)  
adIDispatch 9      
adInteger 3 AutoNumber
Integer
Long
Identity (SQL Server 6.5)
Int
 
Int *
adLongVarBinary 205 OLEObject Image Long Raw *
Blob (Oracle 8.1.x)
adLongVarChar 201 Memo (Access 97)
Hyperlink (Access 97)
Text Long *
Clob (Oracle 8.1.x)
adLongVarWChar 203 Memo (Access 2000 (OLEDB))
Hyperlink (Access 2000 (OLEDB))
NText (SQL Server 7.0 +) NClob (Oracle 8.1.x)
adNumeric 131 Decimal (Access 2000 (OLEDB)) Decimal
Numeric
Decimal
Integer
Number
SmallInt
adSingle 4 Single Real  
adSmallInt 2 Integer SmallInt  
adUnsignedTinyInt 17 Byte TinyInt  
adVarBinary 204 ReplicationID (Access 97) VarBinary  
adVarChar 200 Text (Access 97) VarChar VarChar
adVariant 12   Sql_Variant (SQL Server 2000 +) VarChar2
adVarWChar 202 Text (Access 2000 (OLEDB)) NVarChar (SQL Server 7.0 +) NVarChar2
adWChar 130   NChar (SQL Server 7.0 +)  

* In oracle 8.0.x – decimal and int are equal to number and number(10).

[IIS]IIS ASP.NET的进程模式浅析

mikel阅读(485)

转载:http://developer.51cto.com/art/200907/139085.htm

IIS ASP.NET的进程模式有哪些呢?他们各自有什么特点呢?来开始我们的讲解。

IIS ASP.NET的进程模式之ASP.NET处理模型

到目前为止,我们已经明白当请求一个ASP.NET文件的请求传到IIS后,他被转递到aspnet_isapi.dll,他是ASP.NET相关 处理的主要入口点。实际上,这个扩展明显依赖于系统上IIS的版本,因此处理模型是通过asp.net运行时通过有序的操作执行来处理请求并生成回送,也 许有那么一点改变。

在IIS5.X,所有asp.net相关请求通过ISAPI扩展被分配到外部工作进程叫做aspnet_wp.exe.ISAPI扩展,在IIS进 程(inetinfo.exe)中运行,再传递控制权连同所有关于当前传入请求的信息到aspnet_wp.exe。2个进程间的通信通过命名管道(众所 周知IPC[内部进程通信]机制建立。ASP.NET工作进程执行ISAPI扩展的大部分任务。注意一下每个WEB应用程序的实质,以及与IIS下不同虚 拟目录的通讯,他们在asp.net工作进程同一个进程的上下文中被执行。为了实现读取各自执行中上下文ASP.net引入了应用程序域的概念,缩写 AppDomains.他们可以被认为是一个轻量级的进程。更多的将在后面介绍。

如果运行在IIS6上,aspnet_wp.exe进程没有被使用,选择一个更优的进程叫做w3wp.exe.同时,inetinfo.exe也不 再用来传递HTTP请求到ISAPI扩展,尽管这样他还是保持为其他协议的请求提供服务。虽然IIS6能够运行在兼容模式下并且模拟之前的行为,但是相对 于先前的IIS5处理模型有了很多的变化。相对早期最大改变,当处理模型运行在IIS5上,传入进来的请求以lower-kernel-level形式然 后传递到正确的ISAPI扩展,从而避免在内部信息处理方面花费过多的操作。在下面的段落中,我们将进行更深入的研究。

IIS ASP.NET的进程模式之IIS5.0 处理模型

在windows2000以及XP系统上这是默认的处理模型。如上所说他有IIS inetinfo.exe进程默认在TCP端口80监听传入的HTTP请求并且把他们推送进队列等待处理。如果请求类型是asp.net,处理将委托给 asp.net isapi扩展 aspnet_isapi.dll.这样轮流通过命名管道与ASP.NET工作进程通信,最终工作进程处理并传递请求到asp.net HTTP运行时环境。图表2将具体描叙这个过程。

图表2:IIS5.0处理模型

IIS5.0处理模型 

图表2显示一个我们尚未提到过的元素—ASP.NET HTTP运行时环境。目前他并不是我们这编文章的主题,他将在接下来的文章中被解析。HTTP运行时可以被看作一个黑色盒子,所有ASP.NET指定处理 在这里发生,所有的受管制代码运行场所,从HTTP运行时一直到httphandler最终处理请求并生成回送都在这里被处理。这里还涉及到 ASP.NET管道或HTTP运行时管道。

就这个模型有一个有趣的地方就是所有请求,一旦被ISAPI扩展处理,就被传递到asp.net工作进程。每次活动时间有且仅有一个进行实例,一个 例外,后面讨论。因此所运行在IIS上的asp.net web应用程序实际上也运行在工作进程上。尽管如此,这并不意味着所有应用运行在同一个上下文上并共享他们所有的数据。值得一提,asp.net引入 APPDomain概念,本质上是一种提供独立和安全边界的受管制轻量级进程。每个IIS虚拟目录在一个APPDomain里执行,他将自动加载到工作进 程只要资源是属于第一次请求的应用程序。一旦appdomain被加载,换句话说,当前请求所有需要的程序集被加载到appdomain–实际上是传递到 asp.net管道处理。若干appdomains能够这样运行在同样的进程中,当多个请求对于同样的appdomain能够在多个线程出来。尽管如此, 一个线程并不属于一个appdomain,他能为多个不同的appdomians处理多个请求,但是同一个给定的时间一个线程属于一个 APPdomain.

处于性能目的,工作线程能够根据一些标准(通过MACHINCE.CONFIG文件配置)被回收。这些标准包括进程生命周期,请求以及队列数量,空 闲时间,内存分配。一旦达到这些参数中一项临界值,ISAPI扩展将生成一个新的工作进程实例用来处理请求。实际上,先前的进程实例并没有被关闭,但是他 被终止服务等待的请求。

IIS ASP.NET的进程模式之IIS6.0处理模型

IIS6是WINDOWS2003系统默认的。在IIS5处理模型的上他有几个改变和改进。其中之一最大改变就是应用程序池概念。在IIS5系列应 用程序上,即所有的appDomains—运行在asp.net工作进程上。为了在安全以及特性上完成一个出色的界定,IIS6处理模型允许应用程序运行 在同一个工作进程的不同拷贝上。每个应用程序池能够包含多个appdomains(运行在单独一个工作进程拷贝上).换而言之,这个变化是从单一进程运行 所有程序到多个进程运行每一个应用池。这个模型也叫做工作过程隔离模式。

例外一个大变化相对先前的模型在IIS监听所有传入数据方面。在IIS5里,由IIS进程,inetinfo.exe监听指定的TCP端口。在 IIS6中,传入请求被处理并队列在核心级别来替换先前通过核心驱动调用http.sys的用户模式;这种方法有几个优势相对于先前的模式被叫作 kernel-level 请求队列。

图表3 IIS6处理模型

IIS6处理模型 

图表3主要由请求处理组成。一旦一个请求到达核心级别设备驱动http.sys,然后发送到相应的应用程序池队列,每个队列属于一个指定的应用程序池。

工作进程负责加载asp.net ISAPI扩展,依次加载 CRL 委派所有工作到HTTP运行时。

W3WP.exe进程与IIS5下面的aspnet_wp.exe不同,他不是asp.net特有的,能够用来处理任何类型的请求。什么样的ISAPI模块被加载类型根据需要的服务资源类型。

IIS ASP.NET的进程模式就向你就介绍到这里,希望对你有所帮助。

[MVC]新Orcas语言特性:扩展方法

mikel阅读(498)

【原文地址】New "Orcas" Language Feature: Extension Methods
【原文发表日期】 Tuesday, March 13, 2007 2:27 AM

上个星期,我发表了我准备写的讨论一些新的VB和C#语言特性的系列博客贴子的第一篇,这些新语言特性是将于今年晚些时候发布的Visual Studio和.NET框架Orcas版的一部分。

我的上一个博客贴子讨论了自动属性,对象初始化器和集合初始化器等新特性。如果你还没有读过这个帖子的话,请在这里阅读。今天的贴子讨论一个VB和C#中都具有的,重要得多的新特性:扩展方法 (Extension Methods)

什么是扩展方法 (Extension Methods)?

扩展方法允许开发人员往一个现有的CLR类型的公开契约(contract)中添加新的方法,而不用生成子类或者重新编译原来的类型。扩展方法有助于把今天动态语言中流行的对duck typing的支持之灵活性,与强类型语言之性能和编译时验证融合起来。

扩展方法促成了好多有用的使用场景,并使在作为Orcas一部分发布的.NET版本中引进的非常强大的LINQ查询框架成为可能。

简单的扩展方法例子:

有没有想过要检查一个字符串变量是否是个合法的电子邮件地址? 在今天,你大概需要通过调用一个单独的类(或许通过一个静态方法)来实现检查该字符串变量是否合法。譬如,象这样:

string email Request.QueryString["email"];
if 
( EmailValidator.IsValid(email) ) {
   

}

而 使用C#和VB中的新“扩展方法”语言特性的话,我则可以添加一个有用的“IsValidEmailAddress()”方法到string类本身中去, 该方法返回当前字符串实例是否是个合法的字符串。然后我可以把我的代码重写一下,使之更加干净,而且更具描述性,象这样:

string email Request.QueryString["email"];
if 
( email.IsValidEmailAddress() ) {
   

}

我们是怎么把这个新的IsValidEmailAddress()方法添加到现有的string类里去的呢?我们是通过定义一个静态的类型,带有我们的“IsValidEmailAddress”这个静态的方法来实现的,象下面这样:

public static class ScottGuExtensions
{
    
public static bool IsValidEmailAddress(this string s)
    {
        Regex regex 
= new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
        return 
regex.IsMatch(s);
    
}
}

注 意,上面的静态方法在第一个类型是string的参数变量前有个“this”关键词,这告诉编译器,这个特定的扩展方法应该添加到类型为“string” 的对象中去。然后在IsValidEmailAddress()方法实现里,我可以访问调用该方法的实际string实例的所有公开属性/方法/事件,取 决于它是否是合法电子邮件地址来返回true/false。

在我的代码里把这个特定的扩展方法的实现添加到string实例,我只要使用标准的“using”语句来引入含有该扩展方法的实现的命名空间:

using ScottGuExtensions;

然后编译器就会在任何string上正确地定位IsValidEmailAddress()方法。在公开发行的Orcas三月份的CTP中的C#和VB在Visual Studio代码编辑器里对扩展方法提供了完整的intellisense支持。所以,当我在一个字符串变量上点击“.”关键词时,我的扩展方法现在就会出现在intellisense的下拉框里:

VB和C#编译器也会很自然地给与你对所有扩展方法用法的编译时的检查,这意味着你会得到一个编译时错误,假如你键错或者错用一个扩展方法的话。

[感谢David Hayden是他在去年的一个老帖子 里第一个示范了我在上面使用的这个IsValidEmailAddress使用场景。]

扩展方法使用场景续…

利 用扩展方法这个新特性来给个别类型添加方法给开发人员开辟了许多有用的扩展性使用场景。但使得扩展方法非常强有力的是,它们不仅能够应用到个别类型上,也 能应用到.NET框架中任何基类或接口上。这允许开发人员建立种种可用于整个.NET框架的丰富的可组合的框架层扩展。

譬如,考虑这样一个场景,我想要一个既容易,描述性又强的方式来检查一个对象是否已经包含在一个对象集合或数组里。我可以定义一个简单的.In(集合)扩展方法,我想把它添加到.NET框架中的所有对象上,我可以在C#里这么来实现这个“In()”扩展方法:

注意上面我是如何声明扩展方法的第一个参数的:“this object o”。这表明,这个扩展方法应该适用于继承于基类System.Object的所有类型,这意味著我可以在.NET中的每个对象上使用它。

上面这个“In”方法的实现允许我检查一个指定的对象是否包含在作为方法参数传入的一个IEnumerable序列中。因为所有的.NET集合和数组都实现了IEnumerable接口,现在我拥有了一个有用的,描述性强的方法来检查一个任意的对象是否属于任何.NET集合或数组。

然后我就可以使用这个“In()”方法来看一个特定的字符串是否在一个字符串数组中:

我也可以用它来检查一个特定的ASP.NET控件是否在一个容器控件集合里:

我甚至可以将其用在象整数这样的标量数据类型上:

注意上面,你甚至可以在象整数值42这样的基本数据类型值上使用扩展方法。因为CLR支持数值类型的自动boxing/unboxing,扩展方法可以直接使用在数值和其他标量数据类型上。

你大概可以开始从上面的例子中看出,扩展方法可以促成一些非常丰富和描述性强的扩展性使用场景。当使用于.NET中常见的基类和接口上时,他们可以促成一些非常好的特定于某个领域(domain specific)的框架和组合使用场景。

内置的System.Linq扩展方法

一 个在Orcas时段随.NET发布的内置的扩展方法库是一套允许开发人员对任何数据进行查询的非常强有力的查询扩展方法。这些扩展方法实现位于新的 System.Linq 命名空间之下,定义了标准的查询操作符扩展方法,可以为.NET开发人员用来轻松地查询XML,关系数据库,.NET 对象, 和任何其他数据结构类型。

下面是使用这些查询扩展方法的扩展性模型的几个好处:

1) 它允许一个可用于所有数据类型(数据库,XML文件,内存中的对象,以及web-services等)的共同的查询编程模型和语法。

2) 它是可以组合的,允许开发人员轻松地往查询语法中添加新的方法/操作符。譬如,我们可以将我们自定义的“In()”方法与为LINQ所定义的标准的 “Where()”方法作为一个单独查询的一部分一起使用。我们自定义的In()方法看上去就跟由System.Linq命名空间提供的标准方法一样。

3) 它是可扩展的,允许与任何数据提供器类型一起使用。譬如,任何一个象NHibernate或LLBLGen这样现有的ORM引擎可以实现LINQ的标准查 询操作符来允许对他们现有的ORM实现和映射引擎实现LINQ查询。这允许开发人员学会一个查询数据的共同方式,然后对种类繁多的丰富数据存储实现使用同 样的技能。

我将在下几个星期里对LINQ作更多的示范,但想留给你几个例子,这些例子展示了如何对不同类型的数据使用几个内置的LINQ查询扩展方法:

使用场景一:对内存中的.NET对象使用LINQ扩展方法

假定我们象这样定义了代表“Person”的类:

然后我可以使用新的对象初始化器和集合初始化器特性创建和填充一个“people”集合,象这样:

然后我可以使用由System.Linq提供的标准的“Where()”扩展方法来获取这个集合中FirstName的首字符是"S"的那些“Person”对象,象这样:

上 面这个新的 p => 语法是“Lambda表达式”的一个例子,是对C# 2.0匿名方法支持的更简明的发展,允许我们通过一个实参来轻松地表达查询过滤(在这个情形下,我们表示我们只想要返回一串firstname属性的首字 符是“S”字母的Person对象) 。上面这个查询然后就会返回包含2个对象的序列,Scott 和 Susanne。

我也可以利用由System.Linq提供的新的“Average” 和“Max”扩展方法编写代码来决定我的集合里的人的平均年龄,以及年龄最大的人,象这样:

使用场景二:对XML文件使用LINQ扩展方法

你手工在内存里创建一个硬写(hard-coded)的数据集合大概是很少见的。更有可能的是,你会从一个XM文件,数据库,或web服务里获取数据。

假定我们在硬盘上有一个XML文件,包含下面这样的数据:

很 明显地,我可以使用现有的 System.Xml APIs 来装载这个XML文件进一个DOM,然后访问它,或者使用一个层次较低的XmlReader API ,自己对之手工分析。或者,在 orcas中,我现在也可以使用支持标准的LINQ扩展方法的System.Xml.Linq 实现(即 XLINQ),更优雅地分析和处理XML。

下面的代码例子展示了如何使用LINQ来获取所有包含一个子节点的值的首字母为“S”的<person> XML元素:

注 意,它使用了跟内存中对象例子中一模一样的 Where() 扩展方法。现在它返回一个“XElement”元素序列,XElemen是没有类型的XML节点元素。或者我也可以重写查询表达式,通过LINQ的 Select() 扩展方法来构造数据形状,提供一个使用了新的对象初始化器句法的Lambda 表达式来填充同样的“Person”类,跟我们第一个内存中的集合的例子一样:

上面的代码会做需要打开,分析,和过滤XML,然后返回一个强类型的Person对象序列所有的工作,不需要什么映射或持久的文件来映射数值,我只是在上面的LINQ查询式里直接指明了从XML到对象的构形而已。

我也可以和前面一样使用同样的Average() 和 Max() LINQ扩展方法来计算XML文件中<person>元素的平均年龄,以及最大年龄,象这样:

我不用手工分析XML文件,XLINQ 不仅可以为我处理分析,它在估算LINQ表达式时,也可以使用低层的XMLReader,而不是使用DOM来分析文件。这意味着它是迅速之极,而且不分配很多内存。

使用场景三:对数据库使用LINQ扩展方法

假定我们拥有一个SQL数据库,内含一个叫“People”的表,具有下列数据定义:

我可以使用Visual Studio中新的LINQ到SQL的所见即所得(WYSIWYG) orM设计器,快速地创建一个映射到数据库的“Person”类:

然后我可以使用我先前用于对象和XML文件同样的LINQ Where() 扩展方法,从数据库中获取firstname的首字符为“S”的强类型“Person”对象序列:

注意,查询句法与对象和XML场景中的一模一样。

然后我也可以使用与前面一样的 LINQ Average() 和Max() 扩展方法来从数据库里获取平均和最大值,象这样:

要 使上面代码例子工作,你自己不需编写任何SQL代码。Orcas中提供的LINQ到SQL对象关系映射器会处理获取,跟踪,和更新映射到你的数据库数据定 义和存储过程的对象。你只要使用任何LINQ扩展方法对结果进行过滤和构形即可,LINQ到SQL会执行获取数据所需的SQL代码(注意,上面的 Average和Max 扩展方法很明显地不会从数据表中返回所有的数据行,它们会使用TSQL的聚合函数来计算数据库中的值,然后只返回一个标量值)。

请观看我一月份制作的一个录像,演示了LINQ到SQL如何显著地改进了Orcas中的数据生产力。录像中,你也可以看到新的LINQ到SQL的所见即所得ORM设计器的实战示范,以及对数据模型编写LINQ代码时代码编辑器提供的完整的 intellisense。

结语

希望上面的帖子给了你一个对扩展方法工作原理的基本理解,以及你能够利用它们来实现的一些酷扩展性方式。跟任何扩展性机制一样,我要告诫你别一开始就滥建新的扩展方法。不能因为你有一个闪亮的新榔头,就意味着世界上所有的东西突然都变成钉子了!

想 着手开始尝试扩展方法的话,我建议你先探究一下Orcas中System.Linq命名空间中提供的标准查询操作符。这些操作符提供了对任何数组,集 合,XML流,或关系数据库做丰富的查询的支持,可以极大地改进你操作数据时的生产力。我认为你会发现它们极大地减小了你要在你应用中编写的代码量,允许 你编写非常干净和描述性强的语句。它们也允许你在你编码中得到查询逻辑自动的intellisense 和编译时检查。

在下几个星期里,我将继续这个关于Orcas中新语言特性的系列,探讨匿名类和类的推断(Type Inference),还会讨论Lambda的细节和其他酷特性。很明显地,我还会地更多地讨论LINQ。

希望本文对你有所帮助,

Scott

[MVC]mvc1.0开发 小结2:iis7和iis6我遇到的几个奇怪的异常

mikel阅读(510)

转载:http://www.cnblogs.com/subway-2008/archive/2009/07/26/1531610.html

   我写的这些不是什么新鲜事儿,在google上都能找得到,不过都是自己在部署mvc应用程序时遇到的奇怪问题,可以说可大可小,毕竟第一次管理并配置服务器,对于基本的部署步骤在网上都可以找到的,在那之外的这些问题。对我而言,显得弥足珍贵。

先看Iis7:  

1.Could not load file or assembly 'Name' or one of its dependencies. An attempt was made to load a program with an incorrect format.

我 在google上找关于这个错误,似乎说说原因的很多,一个个尝试都没什么效果,折腾了几个小时,在ms 论坛看到一些说法是将重新设置编译选项,打开项 目属性->编译选项-》改变目标cpu从x86到任何cpu,重编译,不过没什么用,、总算找到一篇文章和我的情况完全相似的情况,Could not load file or assembly 'name' or one of its dependencies ,这个家伙遇到的问题和我几乎一样,在他的介绍下,我解决了问题。对于这个问题

I. iis运行64位版本操作系统

II. 问题在于dll程序集是为32位操作系统编译的,

 因此你需要打开项目属性,在bulid选项,platform target 是x86,意味着应用程序是为32位系统编译的,为什么你有一个32位的dll,可能是使用了一些64位不兼容组件,如mapi,odbc..



当然实际的问题是64位iis使用的应用程序池不允许32位dll被加入进程,打开iis管理器,找到网站的应用程序池,选择高级设置,看到其中有一个选项,
Enable 32-Bit Applications"默认是false,这是异常出现的原因所在。


2.
HTTP Error 403.14 – Forbidden The Web server is configured to not list the contents of this directory

我记得在ii5,ii6下这个应该算是目录访问权限的问题,可是无论如何怎么设置都没什么效果,下面是我的解决方案:

打开iis7管理器。打开目录浏览,在目录浏览页中的,行为面板,点击 Enable

1.Open IIS Manager. 

2.In the Features view, double-click Directory Browsing. 

On the Directory Browsing page, in the Actions pane, click Enable. 

 

下面是关于II6:安装好framework2.0,3.0,3.5以及sp1,在安装完mvc框架,新建网站,配置到数据库连接,打开浏览

 HTTP 错误 403.1 – 禁止访问:执行访问被拒绝

我在网上找到的方法,一个试下来

1、在IIS里配置一下!默认是不行的!打开IIS的管理,找到相应的目录,打开属性,可以找到几个选项,勾中可以执行程序就行了! 

2、用的是windows2003 IIS6.0吧,进入IIS,在网站下面找到“服务器扩展”——〉选择“允许所有未知CGI”“允许所有未知ISAPI” 

3、 cgi之类的程序必须在特定的文件夹下才能执行,如cgi在名为cgi-bin的文件夹下存储才能被有效执行

4、在IE中找到工具,然后选择Internet选项,在里面找到 高级选项卡,然后找到显示友好的URL,并将左边的选取去掉,一切ok 

5、也许是IIS没有搞好啊,用系统盘在重装一下IIS试试!

6、没有配置好服务器啊

7、把文件复制到wwwroot下面了嘛?没有的话,就做一个虚拟目录,这个不要解释了吧

8、IS→网站→属性→主目录 选中脚本和可执行文件如 NTFS 配置权限文件夹选项→查看 勾去使用简单文件共享 再配置文件权

9、你先试一下能不能访问你创建的虚拟目录。再用http://你的机器名/你的虚拟目录名/文件名.htm测试一下图片或者HTML静态网页是否可以浏览!

10、主目录->执行权限->脚本和可执行文件,再设置everyone权限

还是一样,后来在国外的社区看到

在IIS中选中网站点属性–主目录–配置

 那个可执行文件选择 D:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll   这个非常关键,果然可以被浏览了。

[MVC]ELMAH with ASP.NET MVC

mikel阅读(490)

转载:http://darrell.mozingo.net/2009/02/19/elmah-with-aspnet-mvc/

We finally got to the point of needing some error reporting in our new application. We’d read about ELMAH before and assumed we’d use that, but that was a while before we decided to go with the ASP.NET MVC framework instead of the traditional WebForms.

I was a little worried we’d hit some road block using ELMAH in conjunction with ASP.NET MVC, but it actually works out of the box without a hitch. ELMAH has a built in module for displaying any logged errors, and is accessible (by default) via http://localhost/elmah.axd. The latest releases of ASP.NET MVC automatically ignore routes with a .axd extension, though I’m not sure for how many releases they’ve been including that, so earlier releases will have a problem getting to that URL.

Simone Busoli wrote up an excellent article on the most important features of ELMAH and getting it setup. A must read if you’re going to implement this solution.

Here’s a quick run-down of the steps we went through for our application, though (using SQL logging & emailing the developers whenever an exception is logged):

  1. Reference the ELMAH.dll assembly in your project.
  2. Define the section group in your web.config:
    1
    2
    3
    4
    5
    
    <sectionGroup name="elmah">
    <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
    <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
    <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
    </sectionGroup>
  3. Define the needed ELMAH section elements, along with their related SQL connection string, in your web.config (we’re only allowing access to the error page via the local host):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    <elmah>
    <security allowRemoteAccess="0" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ErrorLogging" />
    <errorMail
            from="PPError@PatriotSoftware.com"
            to="PPDevs@SynergyDataSystems.com"
            subject="Patriot Pay Error"
            async="true"
            smtpPort="25"
            smtpServer="imail.topechelon.corp" />
    </elmah>
     
    <connectionStrings>
    <add name="ErrorLogging" connectionString="Data Source=...." />
    </connectionStrings>
  4. Add the follow handler to the section that’ll allow you to view the errors (I used the path errors.axd instead of the default elmah.axd, just because I hate using default URL like that in case we ever allow this on something other than localhost w/a restricted login):
    1
    
    <add verb="POST,GET,HEAD" path="errors.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
  5. Add the following modules to the section, which will actually catch exceptions for logging to SQL and emailing out:
    1
    2
    
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
  6. (Optional) Add the following methods to your Global.asax, which will filter all exceptions thrown on the local host and ignore them (so developing on your local machine won’t keep emailing everyone else, which, trust me, gets old pretty damn quick):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    public void errorLog_Filtering(object sender, ExceptionFilterEventArgs e)
    {
    if(ErrorFiltering.Filter(new HttpContextWrapper(e.Context)))
    {
    e.Dismiss();
    }
    }
     
    public void errorMail_Filtering(object sender, ExceptionFilterEventArgs e)
    {
    if(ErrorFiltering.Filter(new HttpContextWrapper(e.Context)))
    {
    e.Dismiss();
    }
    }

    and in another file somewhere (note the HttpContextWrapper in both of these pieces of code, for easier testing):

    1
    2
    3
    4
    5
    6
    7
    
    public class ErrorFiltering
    {
    public static bool Filter(HttpContextWrapper httpContextWrapper)
    {
    return httpContextWrapper.Request.IsLocal;
    }
    }
  7. Run the SQL script included with the ELMAH download to generate the needed table and stored procedures, then hookup SQL security and the connection string from the previous steps

You should be good to go now, ripe with error logging goodness. For added user friendliness, we use the following in our web.config to redirect users to nice pages when an error pops up:

1
2
3
4
<customErrors mode="RemoteOnly" defaultRedirect="~/Errors/Generic.html">
<error statusCode="404" redirect="~/Errors/NotFound.html" />
<error statusCode="500" redirect="~/Errors/Internal.html" />
</customErrors>

The only thing that buggs me about using ELMAH is how Resharper acts with it. The SectionHandler’s defined in the sectionGroup in the web.config (from step 2 above) are internal to the ELMAH assembly, so Resharper freaks out that saying they’re not defined. Bzzt. Sorry, Resharper, try again. So I’ve simply built a local version of the project with those attributes marked as public and it’s all good. I’m looking into filing a bug report with Resharper on this issue now, as it does it with log4net too. Quite annoying when you have the Solution-wide Analysis option turned on and the web.config consistently shows up with “errors”.

[MVC]Real world error hadnling in ASP.NET MVC RC2.

mikel阅读(536)

转载:http://blogs.microsoft.co.il/blogs/shay/archive/2009/03/06/real-world-error-hadnling-in-asp-net-mvc-rc2.aspx

I would like to share with You my ASP.NET MVC Error Handling solution after reading this question in stackoverflow.com 

Goal:

To catch every error that occures on server include HttpExeptions like 404 (Page not found).

The ability to choose a specific View (error Template) for some errors and a generic View/Behaviour if nor specific has been specified.
Scenario 1:
anonymus user typed a wrong url.
Actions:
display a user friendly message like: "OOPS, The page is missing… back to home"
Log the error to .log file on server.
Send email to admin.

Senario 2:
same as scenario 1 but one difference : user is anonymus but his IP is from our company office.
Actions:
show the detailed error.

Let's see some code:

 

Add this method to Global.asax:

protected void Application_Error(object sender, EventArgs e)
{
 
   Exception exception = Server.GetLastError();
 
 // Log the exception.
 ILogger logger = Container.Resolve<ILogger>();
 logger.Error(exception);
 
 Response.Clear();
 
 
 HttpException httpException = exception as HttpException;
 RouteData routeData = new RouteData();
 routeData.Values.Add("controller", "Error");
 
 if (httpException == null)
 {
      routeData.Values.Add("action", "Index");
 }
 else //It's an Http Exception, Let's handle it.
 {
 
  switch (httpException.GetHttpCode())
  {
    case 404:
      // Page not found.
      routeData.Values.Add("action", "HttpError404");
      break;
     case 500:
     // Server error.
       routeData.Values.Add("action", "HttpError500");
       break;
       // Here you can handle Views to other error codes.
        // I choose a General error template  
        default:
        routeData.Values.Add("action", "General");
        break;
     }
  }
 
 // Pass exception details to the target error View.
 routeData.Values.Add("error", exception);
 
 // Clear the error on server.
 Server.ClearError();
 
// Call target Controller and pass the routeData.
 IController errorController = new ErrorController();
 errorController.Execute(new RequestContext(
new HttpContextWrapper(Context), routeData));
 
}

Created a new controller called ErrorController:
You can specify some more behaviors to another eception types, I breated a view just for error: 404, 500.

 

    public ActionResult HttpError404(string error)
        {
            ViewData["Title"] = "Sorry, an error occurred while processing your request. (404)";
            ViewData["Description"] = error;
            return View("Index");
        }
 
        public ActionResult HttpError500(string error)
        {
            ViewData["Title"] = "Sorry, an error occurred while processing your request. (500)";
            ViewData["Description"] = error;
            return View("Index");
        }
 
 
        public ActionResult General(string error)
        {
            ViewData["Title"] = "Sorry, an error occurred while processing your request.";
            ViewData["Description"] = error;
            return View("Index");
        }

 

I attached an example project to this post.

 

Com

[SQL]请谨慎使用sp_executesql

mikel阅读(767)

转载:http://www.cnblogs.com/perfectdesign/archive/2009/10/15/sp_executeSQL.html
前一段时间,给一位朋友公司做咨询,看到他们的很多的存储过程都存在动态SQL语句执行,sp_executesql,即使在没有动态表名,动态字段名的情况下仍然使用sp_executesql,这个做法是不太明智的,会存在一些性能方面的问题。
先 说说什么场景使用这个系统存储过程吧,sp_executesql,是sql server动态执行一段可以带有参数(内参,外参)的语句文本的系统存储过程,传入sp_executesql 的参数会以参数的形式传递,不会是以拼凑sql的形式传递,所以能够在不得不拼接sql语句的情景下使用以防止sql注入。不得不拼接sql的情景包括 传递in内参数,动态决定表列,列名,还有就是like,为防止sql注入,也不得不拼接sql。按理来说这是一个非常好的存储过程,但是,由于他本身的 限制,会对查询性能有很大的影响,下面我举个例子。
使用northwind数据库,
执行:
select * from orders where customerid = 'SAVEA';

执行:
select * from orders where customerid = 'CENTC';

这两个语句的唯一不同就是客户号不一样,一个在订单表内有31个重复值,一个没有重复值。
然后咱们再来对比当这个语句放在了一个动态执行的sql语句内部的情况如何。
创建如下存储过程:

Code

然后执行这个存储过程:
exec testexecutesql 'SAVEA';
其执行计划如下图,是个聚集索引扫描:

(31 行受影响)
表 'Orders'。扫描计数 1,逻辑读取 22 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
使用聚集索引扫描是个很明智的选择,咱们可以来看看customerid上的非聚集索引的统计信息,orders表共830行,其中客户'SAVEA'就有31个订单,所以优化器选择使用聚集索引扫描而不是嵌套循环的book mark look up。
然后咱们再来执行一个:
exec testexecutesql 'CENTC';
区 别仅仅是传入的customerid参数不一样,再看看执行计划,仍然是一样,io也是一样,就是返回的行数只有一行,按理来说,只返回一行,优化器应该 会选择使用非聚集索引,嵌套查找数据,但是优化器却没有好好利用customerid上的统计信息,仍然使用了聚集索引扫描,为什们?难道是索引上的统计 信息不及时吗?不,在手动使用fullscan后的统计信息仍然是一样的查询计划,为什么呢?
因为sp_executesql本身就是一个存储过 程,他执行动态语句的参数是不会被利用上的,所以当第一次编译的时候产生的计划,存储过程testexecutesql 是无法嗅探到的,即无法去引用customerid上的统计信息来做查询计划参考的,所以第一次编译的查询计划是聚集索引扫描就是扫描,即使第二次执行的 时候应该是查找。
如何才能改变这一现状呢?
可以使用提示符,recompile强制让存储过程在执行的时候重新编译,来获得最好的执行计划,不过这也是有代价的,就是每次都需要编译,不过相比那些被浪费掉的IO,对一些大表的性能低下的查询计划还是很值得的。于是,我们把存储过程改写如下:

USE [Northwind]
GO
/****** 对象:  StoredProcedure [dbo].[testexecutesql]    脚本日期: 10/15/2009 20:09:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Alter proc [dbo].[testexecutesql](@customerid nchar(5))
as
begin
exec sp_executesql N'select * from orders where customerid = @cid option(recompile) ',
N
'@cid as nchar(5)',@cid = @customerid   ;
end

这样再次执行exec testexecutesql 'CENTC'; exec testexecutesql 'SAVEA';
都能获得一个最优的查询计划。
sql server能够支持语句级的重编译,自动嗅探重编译环境,阀值,使得绝大部分情况下能够很好的利用编译后的查询计划,提高数据库整体性能。我在08年初 写过的一个ppt,是关数据库于重编译的,大家可以下载看看,http://img.cyzone.cn/temp/SQL SERVER 高级技巧系列之二:重编译详解.ppt   
如果有朋友关注数据库性能方面的东西,可以加入我创建的一个小组,http://home.cnblogs.com/group/sql/  欢迎提出自己遇到的性能问题。

[ASP.NET] 24个优化ASP.NET的性能方法(转)

mikel阅读(436)

1. 数据库访问性能优化

数据库的连接和关闭

访问数据库资源需要创建连接、打开连接和关闭连接几个操作。这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源。ASP.NET中提供 了连接池(Connection Pool)改善打开和关闭数据库对性能的影响。系统将用户的数据库连接放在连接池中,需要时取出,关闭时收回连接,等待下一次的连接请求。连接池的大小是 有限的,如果在连接池达到最大限度后仍要求创建连接,必然大大影响性能。因此,在建立数据库连接后只有在真正需要操作时才打开连接,使用完毕后马上关闭, 从而尽量减少数据库连接打开的时间,避免出现超出连接限制的情况。

使用存储过程

存储过程是存储在服务器上的一组预编译的SQL语句,类似于DOS系统中的批处理文件。存储过程具有对数据库立即访问的功能,信息处理极为迅速。使用存储 过程可以避免对命令的多次编译,在执行一次后其执行规划就驻留在高速缓存中,以后需要时只需直接调用缓存中的二进制代码即可。另外,存储过程在服务器端运 行,独立于ASP.NET程序,便于修改,最重要的是它可以减少数据库操作语句在网络中的传输。

优化查询语句

ASP.NET中ADO连接消耗的资源相当大,SQL语句运行的时间越长,占用系统资源的时间也越长。因此,尽量使用优化过的SQL语句以减少执行时间。比如,不在查询语句中包含子查询语句,充分利用索引等。

2. 字符串操作性能优化

使用值类型的ToString方法

在连接字符串时,经常使用"+"号直接将数字添加到字符串中。这种方法虽然简单,也可以得到正确结果,但是由于涉及到不同的数据类型,数字需要通过装箱操 作转化为引用类型才可以添加到字符串中。但是装箱操作对性能影响较大,因为在进行这类处理时,将在托管堆中分配一个新的对象,原有的值复制到新创建的对象 中。使用值类型的ToString方法可以避免装箱操作,从而提高应用程序性能。

运用StringBuilder类

String类对象是不可改变的,对于String对象的重新赋值在本质上是重新创建了一个String对象并将新值赋予该对象,其方法ToString 对性能的提高并非很显著。在处理字符串时,最好使用StringBuilder类,其.NET 命名空间是System.Text。该类并非创建新的对象,而是通过Append,Remove,Insert等方法直接对字符串进行操作,通过 ToString方法返回操作结果。

  其定义及操作语句如下所示:

int num;

System.Text.StringBuilder str = new System.Text.StringBuilder(); //创建字符串

  str.Append(num.ToString()); //添加数值num

Response.Write(str.ToString); //显示操作结果3. 优化 Web 服务器计算机和特定应用程序的配置文件以符合您的特定需要

默认情况下,ASP.NET 配置被设置成启用最广泛的功能并尽量适应最常见的方案。因此,应用程序开发人员可以根据应用程序所使用的功能,优化和更改其中的某些配置,以提高应用程序的性能。下面的列表是您应该考虑的一些选项。

3.仅对需要的应用程序启用身份验证。

默认情况下,身份验证模式为 Windows,或集成 NTLM。大多数情况下,对于需要身份验证的应用程序,最好在 Machine.config 文件中禁用身份验证,并在 Web.config 文件中启用身份验证。根据适当的请求和响应编码设置来配置应用程序。ASP.NET 默认编码格式为 UTF-8。如果您的应用程序为严格的 ASCII,请配置应用程序使用 ASCII 以获得稍许的性能提高。

考虑对应用程序禁用 AutoEventWireup。

在 Machine.config 文件中将 AutoEventWireup 属性设置为 false,意味着页面不将方法名与事件进行匹配和将两者挂钩(例如 Page_Load)。如果页面开发人员要使用这些事件,需要在基类中重写这些方法(例如,需要为页面加载事件重写 Page.OnLoad,而不是使用 Page_Load 方法)。如果禁用 AutoEventWireup,页面将通过将事件连接留给页面作者而不是自动执行它,获得稍许的性能提升。

从请求处理管线中移除不用的模块。

默认情况下,服务器计算机的 Machine.config 文件中 节点的所有功能均保留为激活。根据应用程序所使用的功能,您可以从请求管线中移除不用的模块以获得稍许的性能提升。检查每个模块及其功能,并按您的需要自 定义它。例如,如果您在应用程序中不使用会话状态和输出缓存,则可以从 列表中移除它们,以便请求在不执行其他有意义的处理时,不必执行每个模块的进入和离开代码。

4. 一定要禁用调试模式

在部署生产应用程序或进行任何性能测量之前,始终记住禁用调试模式。如果启用了调试模式,应用程序的性能可能受到非常大的影响。

5. 对于广泛依赖外部资源的应用程序,请考虑在多处理器计算机上启用网络园艺

ASP.NET 进程模型帮助启用多处理器计算机上的可缩放性,将工作分发给多个进程(每个CPU一个),并且每个进程都将处理器关系设置为其 CPU。此技术称为网络园艺。如果应用程序使用较慢的数据库服务器或调用具有外部依赖项的 COM 对象(这里只是提及两种可能性),则为您的应用程序启用网络园艺是有益的。但是,在决定启用网络园艺之前,您应该测试应用程序在网络园中的执行情况。

6. 只要可能,就缓存数据和页输出

ASP.NET 提供了一些简单的机制,它们会在不需要为每个页请求动态计算页输出或数据时缓存这些页输出或数据。另外,通过设计要进行缓存的页和数据请求(特别是在站点 中预期将有较大通讯量的区域),可以优化这些页的性能。与 .NET Framework 的任何 Web 窗体功能相比,适当地使用缓存可以更好的提高站点的性能,有时这种提高是超数量级的。使用 ASP.NET 缓存机制有两点需要注意。首先,不要缓存太多项。缓存每个项均有开销,特别是在内存使用方面。不要缓存容易重新计算和很少使用的项。其次,给缓存的项分配 的有效期不要太短。很快到期的项会导致缓存中不必要的周转,并且经常导致更多的代码清除和垃圾回收工作。若关心此问题,请监视与 ASP.NET Applications 性能对象关联的 Cache Total Turnover Rate 性能计数器。高周转率可能说明存在问题,特别是当项在到期前被移除时。这也称作内存压力。

7. 选择适合页面或应用程序的数据查看机制

根据您选择在 Web 窗体页显示数据的方式,在便利和性能之间常常存在着重要的权衡。例如,DataGrid Web 服务器控件可能是一种显示数据的方便快捷的方法,但就性能而言它的开销常常是最大的。在某些简单的情况下,您通过生成适当的 HTML 自己呈现数据可能很有效,但是自定义和浏览器定向会很快抵销所获得的额外功效。Repeater Web 服务器控件是便利和性能的折衷。它高效、可自定义且可编程。

8. 将 SqlDataReader 类用于快速只进数据游标

SqlDataReader 类提供了一种读取从 SQL Server 数据库检索的只进数据流的方法。如果当创建 ASP.NET 应用程序时出现允许您使用它的情况,则 SqlDataReader 类提供比 DataSet 类更高的性能。情况之所以这样,是因为 SqlDataReader 使用 SQL Server 的本机网络数据传输格式从数据库连接直接读取数据。另外,SqlDataReader 类实现 IEnumerable 接口,该接口也允许您将数据绑定到服务器控件。有关更多信息,请参见 SqlDataReader 类。有关 ASP.NET 如何访问数据的信息,请参见通过 ASP.NET 访问数据。

9. 将 SQL Server 存储过程用于数据访问

在 .NET Framework 提供的所有数据访问方法中,基于 SQL Server 的数据访问是生成高性能、可缩放 Web 应用程序的推荐选择。使用托管 SQL Server 提供程序时,可通过使用编译的存储过程而不是特殊查询获得额外的性能提高。

10. 避免单线程单元 (STA) COM 组件

默认情况下,ASP.NET 不允许任何 STA COM 组件在页面内运行。若要运行它们,必须在 .aspx 文件内将 ASPCompat=true 属性包含在 @ Page 指令中。这样就将执行用的线程池切换到 STA 线程池,而且使 HttpContext 和其他内置对象可用于 COM 对象。前者也是一种性能优化,因为它避免了将多线程单元 (MTA) 封送到 STA 线程的任何调用。使用 STA COM 组件可能大大损害性能,应尽量避免。若必须使用 STA COM 组件,如在任何 interop 方案中,则应在执行期间进行大量调用并在每次调用期间发送尽可能多的信息。另外,小心不要在构造页面期间创建任何 STA COM 组件。例如下面的代码中,在页面构造时将实例化由某个线程创建的 MySTAComponent,而该线程并不是将运行页面的 STA 线程。这可能对性能有不利影响,因为要构造页面就必须完成 MTA 和 STA 线程之间的封送处理。

Dim myComp as new MySTAComponent() Public Sub Page_Load() myComp.Name = "Bob" End Sub

首选机制是推迟对象的创建,直到以后在 STA 线程下执行上述代码,如下面的例子所示。

Dim myComp Public Sub Page_Load() myComp = new MySTAComponent() myComp.Name = "Bob" End Sub

推荐的做法是在需要时或者在 Page_Load 方法中构造任何 COM 组件和外部资源。永远不要将任何 STA COM 组件存储在可以由构造它的线程以外的其他线程访问的共享资源里。这类资源包括像缓存和会话状态这样的资源。即使 STA 线程调用 STA COM 组件,也只有构造此 STA COM 组件的线程能够实际为该调用服务,而这要求封送处理对创建者线程的调用。此封送处理可能产生重大的性能损失和可伸缩性问题。在这种情况下,请研究一下使 COM 组件成为 MTA COM 组件的可能性,或者更好的办法是迁移代码以使对象成为托管对象。

 11. 将调用密集型的 COM 组件迁移到托管代码

  .NET Framework 提供了一个简单的方法与传统的 COM 组件进行交互。其优点是可以在保留现有投资的同时利用新的平台。但是在某些情况下,保留旧组件的性能开销使得将组件迁移到托管代码是值得的。每一情况都是 不一样的,决定是否需要迁移组件的最好方法是对 Web 站点运行性能测量。建议您研究一下如何将需要大量调用以进行交互的任何COM 组件迁移到托管代码。许多情况下不可能将旧式组件迁移到托管代码,特别是在最初迁移 Web 应用程序时。在这种情况下,最大的性能障碍之一是将数据从非托管环境封送到托管环境。因此,在交互操作中,请在任何一端执行尽可能多的任务,然后进行一个 大调用而不是一系列小调用。例如,公共语言运行库中的所有字符串都是 Unicode 的,所以应在调用托管代码之前将组件中的所有字符串转换成 Unicode 格式。另外,一处理完任何 COM 对象或本机资源就释放它们。这样,其他请求就能够使用它们,并且最大限度地减少了因稍后请求垃圾回收器释放它们所引起的性能问题。

  12. 在 Visual Basic .NET 或 JScript. 代码中使用早期绑定

  以往,开发人员喜欢使用 Visual Basic、VBScript. 和 JScript. 的原因之一就是它们所谓“无类型”的性质。变量不需要显式类型声明,并能够简单地通过使用来创建它们。当从一个类型到另一个类型进行分配时,转换将自动执 行。不过,这种便利会大大损害应用程序的性能。Visual Basic 现在通过使用 Option Strict 编译器指令来支持类型安全编程。为了向后兼容,默认情况下,ASP.NET 不启用该选项。但是,为了得到最佳性能,强烈建议在页中启用该选项。若要启用 Option Strict,请将 Strict 属性包括在 @ Page 指令中,或者,对于用户控件,请将该属性包括在 @ Control 指令中。下面的示例演示了如何设置该属性,并进行了四个变量调用以显示使用该属性是如何导致编译器错误的。

  JScript. .NET 也支持无类型编程,但它不提供强制早期绑定的编译器指令。若发生下面任何一种情况,则变量是晚期绑定的:被显式声明为 Object,是无类型声明的类的字段,是无显式类型声明的专用函数或方法成员,并且无法从其使用推断出类型。   最后一个差别比较复杂,因为如果 JScript. .NET 编译器可以根据变量的使用情况推断出类型,它就会进行优化。在下面的示例中,变量 A 是早期绑定的,但变量 B 是晚期绑定的。

  var A;

  var B;

  A = "Hello";

  B = "World";

  B = 0; 为了获得最佳的性能,当声明 JScript. .NET 变量时,请为其分配一个类型。例如,var A : String。

  13. 使请求管线内的所有模块尽可能高效

  请求管线内的所有模块在每次请求中都有机会被运行。因此,当请求进入和离开模块时快速地触发代码至关重要,特别是在不使用模块功能的代码路径里。分别在使用及不使用模块和配置文件时执行吞吐量测试,对确定这些方法的执行速度非常有用。
  

  14. 使用 HttpServerUtility.Transfer 方法在同一应用程序的页面间重定向

  采用 Server.Transfer 语法,在页面中使用该方法可避免不必要的客户端重定向。

  15. 必要时调整应用程序每个辅助进程的线程数

  ASP.NET 的请求结构试图在执行请求的线程数和可用资源之间达到一种平衡。已知一个使用足够 CPU 功率的应用程序,该结构将根据可用于请求的 CPU 功率,来决定允许同时执行的请求数。这项技术称作线程门控。但是在某些条件下,线程门控算法不是很有效。通过使用与 ASP.NET Applications 性能对象关联的 Pipeline Instance Count 性能计数器,可以在 PerfMon 中监视线程门控。当页面调用外部资源,如数据库访问或 XML Web services 请求时,页面请求通常停止并释放 CPU。如果某个请求正在等待被处理,并且线程池中有一个线程是自由的,那么这个正在等待的请求将开始被处理。遗憾的是,有时这可能导致 Web 服务器上存在大量同时处理的请求和许多正在等待的线程,而它们对服务器性能有不利影响。通常,如果门控因子是外部资源的响应时间,则让过多请求等待资源, 对 Web 服务器的吞吐量并无帮助。为缓和这种情况,可以通过更改 Machine.config 配置文件节点的 maxWorkerThreads 和 maxIOThreads 属性,手动设置进程中的线程数限制。

  注意:辅助线程是用来处理 ASP.NET 请求的,而 IO 线程则是用于为来自文件、数据库或 XML Web services 的数据提供服务的。分配给这些属性的值是进程中每个 CPU 每类线程的最大数目。对于双处理器计算机,最大数是设置值的两倍。对于四处理器计算机,最大值是设置值的四倍。无论如何,对于有四个或八个 CPU 的计算机,最好更改默认值。对于有一个或两个处理器的计算机,默认值就可以,但对于有更多处理器的计算机的性能,进程中有一百或两百个线程则弊大于利。注 意进程中有太多线程往往会降低服务器的速度,因为额外的上下文交换导致操作系统将 CPU 周期花在维护线程而不是处理请求上。

  16. 适当地使用公共语言运行库的垃圾回收器和自动内存管理

  小心不要给每个请求分配过多内存,因为这样垃圾回收器将必须更频繁地进行更多的工作。另外,不要让不必要的指针指向对象,因为它们将使对象 保持活动状态,并且应尽量避免含 Finalize 方法的对象,因为它们在后面会导致更多的工作。特别是在 Finalize 调用中永远不要释放资源,因为资源在被垃圾回收器回收之前可能一直消耗着内存。最后这个问题经常会对 Web 服务器环境的性能造成毁灭性的打击,因为在等待 Finalize 运行时,很容易耗尽某个特定的资源。
  17. 如果有大型 Web 应用程序,可考虑执行预批编译

  每当发生对目录的第一次请求时都会执行批编译。如果目录中的页面没有被分析并编译,此功能会成批分析并编译目录中的所有页面,以便更好地利用磁 盘和内存。如果这需要很长时间,则将快速分析并编译单个页面,以便请求能被处理。此功能带给 ASP.NET 性能上的好处,因为它将许多页面编译为单个程序集。从已加载的程序集访问一页比每页加载新的程序集要快。批编译的缺点在于:如果服务器接收到许多对尚未编 译的页面的请求,那么当 Web 服务器分析并编译它们时,性能可能较差。为解决这个问题,可以执行预批编译。为此,只需在应用程序激活之前向它请求一个页面,无论哪页均可。然后,当用户 首次访问您的站点时,页面及其程序集将已被编译。没有简单的机制可以知道批编译何时发生。需一直等到 CPU 空闲或者没有更多的编译器进程(例如 csc.exe(C# 编译器)或 vbc.exe(Visual Basic 编译器))启动。还应尽量避免更改应用程序的 \bin 目录中的程序集。更改页面会导致重新分析和编译该页,而替换 \bin 目录中的程序集则会导致完全重新批编译该目录。在包含许多页面的大规模站点上,更好的办法可能是根据计划替换页面或程序集的频繁程度来设计不同的目录结 构。不常更改的页面可以存储在同一目录中并在特定的时间进行预批编译。经常更改的页面应在它们自己的目录中(每个目录最多几百页)以便快速编译。Web 应用程序可以包含许多子目录。批编译发生在目录级,而不是应用程序级。

  18. 不要依赖代码中的异常

  因为异常大大地降低性能,所以您不应该将它们用作控制正常程序流程的方式。如果有可能检测到代码中可能导致异常的状态,请执行这种操作。不要在 处理该状态之前捕获异常本身。常见的方案包括:检查 null,分配给将分析为数字值的 String 一个值,或在应用数学运算前检查特定值。下面的示例演示可能导致异常的代码以及测试是否存在某种状态的代码。两者产生相同的结果。

  try   {   result = 100 / num;   }   catch (Exception e)   {   result = 0;   }   // …to this.   if (num != 0)   result = 100 / num;   else   result = 0;

  19. 使用 HttpResponse.Write 方法进行字符串串联

  该方法提供非常有效的缓冲和连接服务。但是,如果您正在执行广泛的连接,请使用多个 Response.Write 调用。下面示例中显示的技术比用对 Response.Write 方法的单个调用连接字符串更快。

  Response.Write("a");   Response.Write(myString);   Response.Write("b");   Response.Write(myObj.ToString());   Response.Write("c");   Response.Write(myString2);   Response.Write("d"); 20. 除非有特殊的原因要关闭缓冲,否则使其保持打开

  禁用 Web 窗体页的缓冲会导致大量的性能开销。
  

  21. 只在必要时保存服务器控件视图状态

  自动视图状态管理是服务器控件的功能,该功能使服务器控件可以在往返过程上重新填充它们的属性值(您不需要编写任何代码)。但是,因为服务器控 件的视图状态在隐藏的窗体字段中往返于服务器,所以该功能确实会对性能产生影响。您应该知道在哪些情况下视图状态会有所帮助,在哪些情况下它影响页的性 能。例如,如果您将服务器控件绑定到每个往返过程上的数据,则将用从数据绑定操作获得的新值替换保存的视图状态。在这种情况下,禁用视图状态可以节省处理 时间。默认情况下,为所有服务器控件启用视图状态。若要禁用视图状态,请将控件的EnableViewState 属性设置为 false,如下面的 DataGrid 服务器控件示例所示。

  您还可以使用 @ Page 指令禁用整个页的视图状态。当您不从页回发到服务器时,这将十分有用:

  注意:@ Control 指令中也支持 EnableViewState 属性,该指令允许您控制是否为用户控件启用视图状态。若要分析页上服务器控件使用的视图状态的数量,请(通过将 trace="true" 属性包括在 @ Page 指令中)启用该页的跟踪并查看 Control Hierarchy 表的 Viewstate 列。有关跟踪和如何启用它的信息,请参见 ASP.NET 跟踪。

  22. 避免到服务器的不必要的往返过程

  虽然您很可能希望尽量多地使用 Web 窗体页框架的那些节省时间和代码的功能,但在某些情况下却不宜使用 ASP.NET 服务器控件和回发事件处理。通常,只有在检索或存储数据时,您才需要启动到服务器的往返过程。多数数据操作可在这些往返过程间的客户端上进行。例如,从 HTML 窗体验证用户输入经常可在数据提交到服务器之前在客户端进行。通常,如果不需要将信息传递到服务器以将其存储在数据库中,那么您不应该编写导致往返过程的 代码。如果您开发自定义服务器控件,请考虑让它们为支持 ECMAScript. 的浏览器呈现客户端代码。通过以这种方式使用服务器控件,您可以显著地减少信息被不必要的发送到 Web 服务器的次数。

  使用 Page.IsPostBack 避免对往返过程执行不必要的处理

  如果您编写处理服务器控件回发处理的代码,有时可能需要在首次请求页时执行其他代码,而不是当用户发送包含在该页中的 HTML 窗体时执行的代码。根据该页是否是响应服务器控件事件生成的。

  使用 Page.IsPostBack 属性有条件地执行代码

  例如,下面的代码演示如何创建数据库连接和命令,该命令在首次请求该页时将数据绑定到 DataGrid 服务器控件。

  void Page_Load(Object sender, EventArgs e)   {   // Set up a connection and command here.   if (!Page.IsPostBack)   {   String query = "select * from Authors where FirstName like '%JUSTIN%'";   myCommand.Fill(ds, "Authors");   myDataGrid.DataBind();   }   }

  由于每次请求时都执行 Page_Load 事件,上述代码检查 IsPostBack 属性是否设置为 false。如果是,则执行代码。如果该属性设置为 true,则不执行代码。注意 如果不运行这种检查,回发页的行为将不更改。Page_Load 事件的代码在执行服务器控件事件之前执行,但只有服务器控件事件的结果才可能在输出页上呈现。如果不运行该检查,仍将为 Page_Load 事件和该页上的任何服务器控件事件执行处理。

  23. 当不使用会话状态时禁用它

  并不是所有的应用程序或页都需要针对于具体用户的会话状态,您应该对任何不需要会话状态的应用程序或页禁用会话状态。   若要禁用页的会话状态,请将 @ Page 指令中的 EnableSessionState 属性设置为 false。例如:

  注意:如果页需要访问会话变量,但不打算创建或修改它们,则将@ Page 指令中的 EnableSessionState 属性设置为ReadOnly。还可以禁用 XML Web services 方法的会话状态。有关更多信息,请参见使用 ASP.NET 和 XML Web services 客户端创建的 XML Web services。若要禁用应用程序的会话状态,请在应用程序 Web.config 文件的 sessionstate 配置节中将 mode 属性设置为 off。例如:

  24. 仔细选择会话状态提供程序

  ASP.NET 为存储应用程序的会话数据提供了三种不同的方法:进程内会话状态、作为 Windows 服务的进程外会话状态和 SQL Server 数据库中的进程外会话状态。每种方法都有自己的优点,但进程内会话状态是迄今为止速度最快的解决方案。如果只在会话状态中存储少量易失数据,则建议您使用 进程内提供程序。进程外解决方案主要用于跨多个处理器或多个计算机缩放应用程序,或者用于服务器或进程重新启动时不能丢失数据的情况。有关更多信息,请参 见 ASP.NET 状态管理。

  25. 不使用不必要的Server Control

  ASP.net中,大量的服务器端控件方便了程序开发,但也可能带来性能的损失,因为用户每操作一次服务器端控件,就产生一次与服务器端的往返过程。因此,非必要,应当少使用Server Control。

  26. ASP.NET应用程序性能测试

  在对ASP.NET应用程序进行性能测试之前,应确保应用程序没有错误,而且功能正确。具体的性能测试可以采用以下工具进行:Web Application Strees Tool (WAS)是Microsoft发布的一个免费测试工具,可以从http://webtool.rte.microsoft.com/上下载。它可以模拟 成百上千个用户同时对web应用程序进行访问请求,在服务器上形成流量负载,从而达到测试的目的,可以生成平均TTFB、平均TTLB等性能汇总报告。 Application Center Test (ACT) 是一个测试工具,附带于Visual Studio.NET的企业版中,是Microsoft正式支持的web应用程序测试工具。它能够直观地生成图表结果,功能比WAS多,但不具备多个客户 机同时测试的能力。服务器操作系统"管理工具"中的"性能"计数器,可以对服务器进行监测以了解应用程序性能。

  结论:

  对于网站开发人员来说,在编写ASP.NET应用程序时注意性能问题,养成良好的习惯,提高应用程序性能,至少可以推迟必需的硬件升级,降低网站的成本。

[C#]关于--在 System.Threading.ThreadAbortException 中第

mikel阅读(537)

转载:http://www.cnblogs.com/wbcms/archive/2008/03/24/1119307.html
开发环境为VS2005,OS 为Windows 2003,系统登录后在跳转到另一页面时会报此错误:
在 System.Threading.ThreadAbortException 中第一次偶然出现的“mscorlib.dll”类型的异常
“System.Threading.ThreadAbortException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进行处理
但不影响程序的正常运行。于是在网上查了查,发现相关资料不多。后来找到微软的官方解释,搞定。
————————————————————————————————————–

症状

如果使用 Response.EndResponse.Redirect Server.Transfer 方法,则出现 ThreadAbortException 异常。 可使用 try-catch 语句捕捉此异常。

原因

Response.End 方法停止页的执行,并将该执行变换到应用程序的事件管线中的 Application_EndRequest 事件。 Response.End 后面的代码行将不执行。
此问题出现在 Response.Redirect Server.Transfer 方法中,这是由于这两种方法都在内部调用 Response.End

解决方案

若要解决此问题,请使用下列方法之一:

  • 对于 Response.End,调用 ApplicationInstance.CompleteRequest 方法而不调用 Response.End,以便跳过 Application_EndRequest 事件的代码执行。
  • 对于 Response.Redirect,使用重载 Response.Redirect(String url, bool endResponse),对 endResponse 参数它传递 false以取消对 Response.End 的内部调用。例如:
      Response.Redirect ("nextpage.aspx", false);

    如果使用这种解决方法,Response.Redirect 后面的代码将得到执行。

  • 对于 Server.Transfer,请改用 Server.Execute 方法。

状态

这种现象是设计使然。

[C#] CLR Debugger - 在程序抛出异常的时候中断程序的执行

mikel阅读(688)

转载:http://blog.csdn.net/Donjuan/archive/2008/12/05/3454650.aspx

1.1.1.                       在程序抛出异常的时候中断程序的执行

.NET对异常的良好支持,让我们摆脱了以前在CC++程序开发过程中,那种不停的检查返回值的编程模式,使我们的程序变的更为简洁。异常不仅方便我们更高效的编写代码,同时也提供了一个好用的调试技巧当然需要调试器的良好支持。在程序开发的过程中,可能会经常碰到这种情况,程序在运行很长时间后,突然抛出一个异常以后,就中断执行了。这种错误(Bug)在平常执行时,一般很难重现,除了异常里面的堆栈信息以外,你几乎没有任何其他信息让你知道程序内部到底发生了什么。这是你就可以使用CLR Debugger里面的异常断点。

CLR Debugger里面,点击菜单栏里的“Debug”菜单里的“Exceptions…”菜单项,打开“Exceptions…”对话框设置异常断点:

 

 

1-6 CLR Debugger 异常断点设置对话框

在“Exceptions”对话框里面,勾上相应异常类型名旁边的复选框就可以设置,在这些异常抛出的时候,“Break when an exception is”列表中有两列复选框:“Thrown”和“User-unhandled”列,这两列的区别是:

l  当“User-unhandled”一列的复选框被选中以后,调试器只在程序中抛出指定的异常以后,并且程序中没有捕捉这个异常,调试器才中断程序的执行。而程序中有try…catch块捕捉该异常时,调试器会让程序继续执行,并忽略这个异常。

l  当“Thrown”一列的复选框被选中以后,则无论程序是否有try…catch块捕捉该异常,只要扔出了指定的异常,则调试器都会中断程序的执行。

 

小技巧:

选择命名空间旁边的复选框,会将该命名空间中定义的所有异常选中。

Exceptions”对话框中只列出了CLR当中定义的异常,如果你希望调试器在自定义的异常被抛出的时候,也能中断程序的执行,则你可以在“Exceptions”对话框中将自定义异常添加进来。点击“Add”按钮添加自定义异常,注意,你必须提供自定义异常的完整类名即命名空间加上类名。下面的示例代码演示了这一过程:

using System;

using System.IO;

 

namespace TestNamespace

{

    public class TestException : Exception

    {

    }

 

    public class ExceptionBreakpoint

    {

        static void Main()

        {

            // “New Exception”中添加TestNamespace.TestException异常

            // 并且在“Throw”中勾上“TestNamespace.TestException”复选框

            // 下面的语句才会导致程序中断,并且跳入到调试器当中

            try

            {

                for (int i = 0; i < 10; ++i)

                {

                    if (i == 5)

                        throw new TestException();

 

                    Console.WriteLine(i);

                }

            }

            catch (Exception e)

            {

                Console.WriteLine(e.Message);

            }

 

            // 无论“Exception”对话框中的“Throw”“User-unhandled”是否

            // 被选中,下面的语句总能导致程序中断,并且跳入到调试器中

            using (StreamReader reader = new StreamReader(

                "notexists.txt"))

                Console.WriteLine(reader.ReadToEnd());

        }

    }

}

1-2 异常断点的演示代码

在上面的例子当中,细心的读者会发现,当调试器捕获在try…catch块中抛出的异常时,高亮显示的当前代码并不是包含throw语句的那一行,而是throw下面的一行,而捕捉到using语句那一行抛出的异常后,高亮显示的当前代码行正是扔出异常的那一行。出现代码行偏差(姑且叫做代码行偏差吧)的原因会在后面的文章讲解调试器的工作原理时讲到。

Exceptions”对话框中还有一种异常类型:“Managed Debugging Assistants”是CLR 2.0新增加的特性,我们将会在讲解使用Visual Studio进行调试的时候讲到它。