zoukankan      html  css  js  c++  java
  • .NET程序优化

    一、数据库 操作

    1、 用完马上关闭数据库连接

      访问数据库资源需要创建连接、打开连接和关闭连接几个操作。这些过程需要多次与数据库交换信息以通过身份验证, 比较耗费服务器资

    源。ASP .NET 中提供了连接池(Connection Pool)改善打开和关闭数据库对性能的影响。系统将用户的数据库连接放在连接池中,需要时取出,关闭时收回连接,等待下一次的连接请求。


       连接池的大小是有限的,如果在连接池达到最大限度后仍要求创建连接,必然大大影响性能。因此,在建立数据库连接后只有在真正需要操作时才打开连接,使用完 毕后马上关闭,从而尽量减少数据库连接打开的时间,避免出现超出连接限制的情况。

    用(推荐)
    using(SqlConnection Conn=new SqlConnection(connstr)) 
    {}//不必显示关闭


    try{conn.Open();}
    catch{} 
    finally{conn.Close();}


    2、尽量使用存储过程,并优化查询语句

       存储过程是存储在服务器上的一组预编译的SQL 语 句,类似于DOS系统中的批处理文件。存储过程具有对数据库立即访问的功能,信息处理极为迅速。使用存储过程可以避免对命令的多次编译,在执行一次后其执 行规划就驻留在高速缓存中,以后需要时只需直接调用缓存中的二进制代码即可。在 .NET Framework 提供的所有数据访问方法中,基于 SQL Server 的数据访问是生成高性能、可缩放 Web 应用程序的推荐选择。使用托管 SQL Server 提供程序时,可通过使用编译的存储过程而不是特殊查询获得额外的性能提高。

      另 外,存储过程在服务器端运行,独立于ASP.NET程序,便于修改,最重要的是它可以减少数据库操作语句在网络中的传输。

      优化查询语句

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


    3、只读数据访问用SqlDataReader,不要使用 DataSet

      SqlDataReader 类提供了一种读取从 SQL Server 数据库检索的只进数据流的方法。如果当创建 ASP.NET 应用程序时出现允许您使用它的情况,则 SqlDataReader 类提供比 DataSet 类更高的性能。情况之所以这样,是因为 SqlDataReader 使用 SQL Server 的本机网络数据传输格式从数据库连接直接读取数据。另外,SqlDataReader 类实现 IEnumerable 接口,该接口也允许您将数据绑定到服务器控件。DataSet作为一个功能强大的、支持离线的数据库,其对性能的开销也相对较大。

    Sqldataread 优点:读取数据非常快。如果对返回的数据不需做大量处理的情况下,建议使用SqlDataReader,其性能要比datset好很多。缺点:直到数据读 完才可close掉于数据库的连接。


    Dataset是把数据读出,缓存在内存中。缺点:对内存的占用较高。如果对返回的数据需做大量的处 理用Dataset比较好些可以减少对数据库的连接操作。优点:只需连接一次就可close于数据库的连接。

    一般情况下,读取大量数据,对 返回数据不做大量处理用SqlDataReader.对返回数据大量处理用datset比较合适.对SqlDataReader和Dataset的选择取 决于程序功能的实现。


    4、数据的绑定DataBinder

    一般的绑定方法<%# DataBinder.Eval(Container.DataItem, "字段名") %>

    用DataBinder.eval 绑定不必关心数据来源(read或dataset)。不必关心数据的类型eval会把这个数据对象转换为一个字符串。在底层绑定做了很多工作,使用了反射 性能。正因为使用方便了,但却影响了数据性能。

    来看下<%# DataBinder.Eval(Container.DataItem, "字段名") %>。当于dataset绑定时,DataItem其实式一个DataRowView(如果绑定的是一个数据读取器(dataread)它就是一个 IdataRecord。)因此直接转换成DataRowView的话,将会给性能带来很大提升。

    <%# ctype(Container.DataItem,DataRowView).Row("字段名") %>

    对数据的绑定建议使 用<%# ctype(Container.DataItem,DataRowView).Row("字段名") %>。使用时注意两个方面:
    1.需在页面添加<%@ Import namespace="System.Data"%>. 
    2.注意字段名的大小写(要特 别注意)。如果和查询的不一致,在某些情况下会导致比<%# DataBinder.Eval(Container.DataItem, "字段名") %>还要慢。如果想进一步提高速度,可采用<%# ctype(Container.DataItem,DataRowView).Row(0) %>的方法。不过其可读性不高。

    以上 的是vb.net的写法。在c#中:<%# ((DataRowView)Container.DataItem)["字段名"] %>

    5、 返回多个结果集

    无论SqlDataReader还是datset,返回多个结果集,然后用rd.NextResult()或 ds.Tables[i]来分别处理数据,减少重复连接数据库的次数。同时尽量用比较高效的SQL代替后续复杂的DataSet二次加工。

    二、 页面优化


    1、不使用不必要的服 务器控件(Server Control)

    ASP.net中,大量的服务器端控件方便了程序开发,但也可能带来性能的损失,因为用户每操作 一次服务器端控件,就产生一次与服务器端的往返过程。因此,非必要,应当少使用Server Control。还有许多其他情况,在这些情况中呈现或数据绑定比使用服务器控件更有效,甚至是在使用服务器控件模板时。但是,如果要以编程方式操作服务 器控件的属性、处理服务器控件事件或利用视图状态保存,则使用服务器控件是适当的。

    所以,尽量选择html控件。能在客户端实现的功能就在 客户端实现(熟练掌握JavaScript),减少服务器的压力。


    2、不使用不必要的ViewState

    默认情况下,ASP.Net对所有的Server Control都启用了ViewState(视图状态)。但ViewState需要在客户端保存一些信息,这会造成性能的消耗。当必须使用Server Control时,可以考虑禁止ViewState。
    只在必要时保存服务器控件视图状态。自动视图状态管 理 是服务器控件的功能,该功能使服务器控件可以在往返过程上重新填充它们的属性值(您不需要编写任何代码)。但是,因 为服务器控件的视图状态在隐藏的窗体字段中往返于服务器,所以该功能确实会对性能产生影响。您应该知道在哪些情况下视图状态会有所帮助,在哪些情况下它影 响页的性能。例如,如果您将服务器控件绑定到每个往返过程上的数据,则将用从数据绑定操作获得的新值替换保存的视图状态。在这种情况下,禁用视图状态可以 节省处理时间。

    默认情况下,为所有服务器控件启用视图状态。若要禁用视图状态,请将控件的 EnableViewState 属性设置为 false,如下面的 DataGrid 服务器控件示例所示。

    <asp:datagrid EnableViewState="false" runat="server"/>
    您还可以使用 @ Page 指令禁用整个页的视图状态。当您不从页回发到服务器时,这将十分有用: <%@ Page EnableViewState="false" %>

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

    3、避免到服务器的不必 要的往返过程

      虽然您很可能希望尽量多地使用 Web 窗体页框架的那些节省时间和代码的功能,但在某些情况下却不宜使用 ASP.NET 服务器控件和回发事件处理。

      通常,只有在检索或存储数据时,您才需要启动到服务器的往返过程。多数数据操作可在这些往 返过程间的客户端上进行。例如,从 HTML 窗体验证用户输入经常可在数据提交到服务器之前在客户端进行。通常,如果不需要将信息传递到服务器以将其存储在数据库中,那么您不应该编写导致往返过程的 代码。

      如果您开发自定义服务器控件,请考虑让它们为支持 ECMAScript. 的浏览器呈现客户端代码。通过以这种方式使用服务器控件,您可以显著地减少信息被不必要的发送到 Web 服务器的次数。

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

      如果您编写处理服务器控件回发处理的代码,有时可能需要在首次请求页 时执行其他代码,而不是当用户发送包含在该页中的 HTML 窗体时执行的代码。根据该页是否是响应服务器控件事件生成的,使用 Page.IsPostBack 属性有条件地执行代码。例如,下面的代码演示如何创建数据库连接和命令,该命令在首次请求该页时将数据绑定到 DataGrid 服务器控件。

    void Page_Load(Object sender, EventArgs e)
    {
    if(!Page.IsPostBack) 
    {}
    }

      由于每次请求时都执行 Page_Load 事件,上述代码检查 IsPostBack 属性是否设置为 false。如果是,则执行代码。如果该属性设置为true,则不执行代码。

      注意 如果不运行这种检查,回发页的行为将不更改。Page_Load 事件的代码在执行服务器控件事件之前执行,但只有服务器控件事件的结果才可能在输出页上呈现。如果不运行该检查,仍将为 Page_Load 事件和该页上的任何服务器控件事件执行处理。


    4、当不使用会话状态时禁用它,并且程序开发中尽量少用Session

      并不是所有的应用程序或 页都需要针对于具体用户的会话状态,您应该对任何不需要会话状态的应用程序或页禁用会话状态。

      若要禁用页的会话状态,请将 @ Page 指令中的 EnableSessionState 属性设置为 false。例如: <%@ Page EnableSessionState="false" %>

      注意 如果页需要访问会话变量,但不打算创建或修改它们,则将 @ Page 指令中的 EnableSessionState 属性设置为 ReadOnly。


       若要禁用应用程序的会话状态,请在应用程序 Web.config 文件的 sessionstate 配置节中将 mode 属性设置为 off。例如:<sessionstate mode="off" />


    5、 合理使用DataGrid(在asp.net2.0中为GridView)控件

      DataGrid控件带有最强大的数据显示功能,还内置 了对数据的修改、删除、添加、分页等很多功能。如果只需简单的显示数据, DataGrid并非最佳选择。DataGrid控件的分页功能,数据的存储方式(存储在viewstate中)等,虽然让程序开发者使用方便快捷,但由 此产生的性能开销不容小视。

      DataList控件比DataGrid功能少了很多。但自定义性强了很多。特有的多行数据显示还是比较方 便的。DataGrid能实现的功能,它基本能实现。

      Repeater控件功能最少,但自定义性非常强。由于减少了很多功能,对服务器 的性能带来消耗最小。

      因此,在只需简单显示数据列表时,选择Repeater或DataList控件同样可以达到目的,而且减轻了性能 上的开销。

    建议选择顺序:Repeater然后DataList最后DataGrid(GridView)

    6、对数据进行分 页

      ASP.NET的DataGrid(在asp.net2.0中为GridView)有一个非常有用的功能:分页。如果 DataGrid允许分页,在某一时刻它只下载某一页的数据,另外,它有一个数据分页的浏览导航栏,它让你可以选择浏览某一页,而且每次只下载一页的数 据。

      但是它有一个小小的缺点,就是你必须把所有的数据都绑定到DataGrid中。也就是说,你的数据层必须返回所有的数据,然后 DataGrid再根据当前页过滤出当前页所需要的数据显示出来。如果有一个一万条记录的结果集要用DataGrid进行分页,假设DataGrid每页 只显示25条数据,那就意味着每次请求都有9975条数据都是要丢弃的。每次请求都要返回这么大的数据集,对应用程序的性能影响是非常大的。

       一个好的解决方案是写一个分页的存储过程,
    如:

    CREATE PROCEDURE dbo.sp_DataPages 
    @Sql nVARCHAR(2000), 
    @PK varchar(50), --主键字段名(可以是任何数据类型;不能,并且也不需要带表名前缀,如:不可以是users.id)
    @Order varchar(50), --排序方式(带desc或asc,可以是多个组合;不能,并且也不需要带表名前缀,如:不可以是users.id desc)
    @Page int, 
    @PageSize int = 30 
    AS

    set nocount on

    DECLARE @Str nVARCHAR(4000)

    if(@Page=1)
    SET @Str= 'Select Top '+ CAST((@PageSize) As VARCHAR(20)) + ' * From ('+ @Sql + ') As table1 Order By table1.' + @Order
    else 
    SET @Str= 'Select Top '+ CAST((@PageSize) As VARCHAR(20)) + ' * From ('+ @Sql + ') As table1 Where table1.' + @PK + ' Not In (Select Top ' + CAST((@PageSize*(@Page-1)) AS VARCHAR(20)) + ' ' + @PK + ' From (' + @Sql + ') As table2 Order By table2.' + @Order + ' ) Order By table1.' + @Order

    --print @str 
    --exec (@Str)
    EXEC sp_ExecuteSql @Str

    set nocount off

    Go

    或者,使用sql server 2005中的row_number()函数

    declare @sql varchar(8000)


    set @sql='select *'
    +' from' 
    +' ('

    +' select row_number() over (order by id desc) as rowNumber,*' 
    +' from Users' 
    +' where id>0 and name<>'''''

    +' )' 
    +' as table1'

    +' where rowNumber between '+str((@page-1)*@pagesize+1)+' AND '+str(@page*@pagesize)
    +' order by id desc'

    --exec (@sql) 
    EXEC sp_ExecuteSql @sql

    (小技巧:将记 录总数保为Cache或Session来提高分页性能。)

    7、不要禁用 Web 窗体页的缓冲

    除非有特殊的原因要关闭缓冲, 否则使其保持打开。禁用 Web 窗体页的缓冲会导致大量的性能开销。

    启用页面输出的缓冲区(Buffer)
    如果Buffer的机制被关闭,可以用下面的方法打开。
    使用程序打开页面输出缓存: 
    Response.BufferOutput = true;

    使用@Page开关打开页面输出缓冲机制: 
    <%@ Page Buffer = "true" %>

    使用 Web.config或Machine.config配置文件的<pages>节点:
    <pages buffer="true"/>

    8、设置page的smart navigation属性

    smart navigation设置为true能让用户明显的感觉性能提高。启用此属性后对客户端和服务端影响不大.它能智能刷新需要刷新的部分。

    在 大多数情况下不要在代码中设置该属性。 
    在 .aspx 文件的 @ Page 指令中将 SmartNavigation 属性设置为 true。请求该页时,动态生成的类将设置该属性。

    Internet Explorer 5 或更高版本浏览器请求页时(或稍后),智能导航将通过执行下列功能提高用户对该页的操作能力: 
    消除导航导致的闪烁。
    从 一页移动到另一页时保持滚动位置。 
    保持导航之间的元素焦点。
    在 浏览器的历史记录中只保留最后一页的状态。

    智能导航最适用于需要频繁回发,但是其内容在返回时不会发生显著更改的 ASP.NET 页。在决定是否将该属性设置为 true 时,请仔细考虑这一点。


    三、c#(或vb.net)程序改进

    1、使用值类型的ToString方法

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

      使用值类型的ToString方法可以避免装箱操作,从而提高应用程序性能。

    int num=1; 
    string str="go"+num.ToString();


    2、运用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、使用 HttpServerUtility.Transfer 方法在同一应用程序的页面间重定向

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

    4、避免使用ArrayList。

    因 为任何对象添加到ArrayList都要封箱为System.Object类型,从ArrayList取出数据时,要拆箱回实际的类型。建议使用自定义的 集合类型代替ArrayList。asp.net 2.0提供了一个新的类型,叫泛型,这是一个强类型,使用泛型集合就可以避免了封箱和拆箱的发生,提高了性能。

    5、使用HashTale代 替其他字典集合类型
    (如 StringDictionary,NameValueCollection,HybridCollection),存放少量数据的时候可以使用 HashTable.

    转载至 http://blog.csdn.net/t_long/article/details/5610186

     
  • 相关阅读:
    D. Constructing the Array
    B. Navigation System
    B. Dreamoon Likes Sequences
    A. Linova and Kingdom
    G. Special Permutation
    B. Xenia and Colorful Gems
    Firetrucks Are Red
    java getInstance()的使用
    java 静态代理和动态代理
    java 类加载机制和反射机制
  • 原文地址:https://www.cnblogs.com/mengtao/p/6103611.html
Copyright © 2011-2022 走看看