刚学asp.net,知道web页面的无序性会造成很多问题。比如页面由于相应用户的操作而造成的回送,此时页面仅会在viewstate中保存所有web控件的状态,而其他成员变量将会全部处于初始状态。比如DataSet和DataView等类型的变量。以一个实际例子说明,比如进行datagrid的分页,在那个asp.net程序员都熟知的DataGrid1_PageIndexChanged事件中的DataBind()函数中,必须有类似的代码出现:protected yournamespace.DataSet1 dataSet11; 
private System.Data.DataView dataView;
...if(sqlConnection1.State!=ConnectionState.Open)
    sqlConnection1.Open();
sqlDataAdapter1.Fill(dataSet11,"tablename");
dataView=new DataView(dataSet11.Tables["tablename"]);也就是说,每一次由用户导航到上页或者下页引起的回送,必定要求dataSet11和dataView的重新被填充和赋值,带来的影响还有要重新连接数据库。
这是由于页面的无序性导致的非控件成员变量需要重新初始化。如果觉得这样做会产生效率的问题,有人提出下面的做法,帖子见如下最后一个人的回复:http://search.csdn.net/Expert/topic/1171/1171715.xml?temp=.2312738他的方法是将dataset和dataview都定义为static变量,在页面的viewstate中似乎也保存了页面所有静态变量的状态(或者页面所有静态变量的状态由服务器端内存保留,具体如何还往大家指教),这样上面的代码也许就可以变成这样:if(DataGrid1.CurrentPageIndex==0) //仅在初次加载页面时初始化变量
{
    if(sqlConnection1.State!=ConnectionState.Open)
sqlConnection1.Open();
    sqlDataAdapter1.Fill(dataSet11,"Suppliers");
    dv_Suppliers=new DataView(dataSet11.Tables["Suppliers"]);
}这样做可以避免多次初始化成员变量并可以减少数据库连接,但带来的问题是静态变量的生存期在web状态下有多久??关于static变量在web下的生存期问题,在csdn里我只能找到这个帖子:
http://search.csdn.net/Expert/topic/2350/2350472.xml?temp=.144253但我不同意gOODiDEA(无语)的看法“只要由一个实例存在,Static变量的值就存在且不变”我认为即使类实例不存在,只要程序代码对static的变量进行了访问,它就会一直存在,至于是否可以改变,那要看具体代码了,static和const还是有很大区别的:)我只知道c#提供了类型构造函数来专门初始化类中的static变量,如:
class SomeRefType{
  static int x;
  static SomeRefType(){ x=10;}
}
至少在winform和console下,我知道该变量i的生存期应该和appdomain一样,只有appdomain关闭时才会被卸载,gc会回收该类型对象的内存。也就是说static的生存周期和程序本身一样长!那在asp.net中呢?我只知道一旦一个页面被用户调用,该页面如果没有保存在output cache中,runtime complier会编译一个运行时页面出来并保存在output cache中,以备后来的其他用户的可能调用(用语不专业,因为刚学asp.net,感觉大致就是这个意思吧?如果不对,还请各位指教!)。从此时算起,该页面中的static变量就算存在了。那它什么时候被析构呢?它的生存期如何?应该和谁一样长?直到该页面被清理出output cache中它才可能会析构吗?还是iis停止时它才析构?
呵呵,我觉得这里显然涉及到一个iis如何管理aspx页面的问题,感觉比较复杂,不敢多说,还请各位指教!说了这么多,问题也提了很多,还有一个切题的问题就是:该如何在web状态下抉择成员变量和static变量??
前者尽管初始化频繁,但生存期都很短;而后者尽管只需一次初始化,但生存期好像是无限长:)
究竟该如何选择呢?似乎微软已经给出了答案,看看它对dataset自动生成的定义代码就可以知道,ms希望这样的变量是非静态的,尽管会造成不断初始化的麻烦,但似乎ms认为这样要比把它变成static要划算的多?我也说不清楚,还望听听大家的意见!其实这个问题与具体编程无关,程序员只要记住了:我就要在databind函数中写入初始化代码就可以了。但我觉得有时候,打破沙锅问到底还是有好处的,至少可以让我们多思考一些问题,感觉我们不仅是代码工人,还可能是一个可以思考问题的人,你说对吗^_^

解决方案 »

  1.   

    一直都没有认真想过楼上的问题,,,看来的好好研究研究,UP一下,别沉了不过我一般都不用DataGrid自带的分页,如果是Sql Server 就直接用存储过程分页,Access就自定义分页,每次只读取需要的数据
      

  2.   

    >>>页面的无序性????stateless??>>>static变量这样的话,在同一个服务器的同一个AppDomain里,一般只有一份数据,如果同时有很多请求的话,这个static变量里的数据就谁也不清楚了所以static变量最好放不变的数据,其他存储的方式有Session变量(那么你不用担心别的用户请求了),或者Application/Cache变量(跟static变量有同样的问题)>>>>我只知道一旦一个页面被用户调用,该页面如果没有保存在output cache中,runtime complier会>>>>编译一个运行时页面出来并保存在output cache中,以备后来的其他用户的可能调用Output Cache里的东西是HTML,不是类,编译过的类一般总是Cache的(假如不关AppDomain/Server的话)>>>static变量就算存在了。那它什么时候被析构呢?它的生存期如何?应该和谁一样长?static变量一般是一个类第一次被调用时开始存在,直到该类所在的Assembly被卸载为止,一般是在当前AppDomain被关闭时
      

  3.   

    谢谢saucer的回答,
    >>>页面的无序性????是我表述的问题,似乎应该是状态的无序性。>>>static变量对于很多用户的同一请求,似乎static变量中的数据还是可以使用的。如果可能存在用户不同请求导致的static变量数据混乱,那应该由类编写者负责:)>>>>Output Cache里的东西是HTML,不是类,编译过的类一般总是Cache的(假如不关AppDomain/Server的话)那么,我想问问思归大哥,运行时编译的页面dll如何保存?何时可能会被卸载?(似乎理论上只有appdomain结束才能卸载加载的dll吧?我记得)
    >>>>static变量一般是一个类第一次被调用时开始存在,直到该类所在的Assembly被卸载为止,一般是在当前AppDomain被关闭时那在web状态下,该如何具体解释static变量生存期?这里的assembly指谁?页面的dll吗?appdomain又是谁?最后,是不是说static变量的生存期就和application变量是一样的了?呵呵,初学asp.net,而且计算机基础也不好,碰上思归大哥来做答,感觉问题提的到处是空窿和漏洞:)
    希望思归大哥继续指教,我就是能不耻下问:)
      

  4.   

    >>>那在web状态下,该如何具体解释static变量生存期?这里的assembly指谁?页面的dll吗?appdomain又是谁?页面的 assembly 应该在这里
    C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Filesappdomain在这里是指当前的应用所在的一个逻辑进程,即物理进程里的一个类似进程的东西http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemappdomainclasstopic.asp>>>>最后,是不是说static变量的生存期就和application变量是一样的了?对,除非你自己Load/UnLoad AppDomain
      

  5.   

    >>>>最后,是不是说static变量的生存期就和application变量是一样的了?sorry, 不完全对,Application这个变量,当前这个应用启动时就有了,但静态变量是所在类第一次调用时才开始存在的,但应该是差不多的时间终止的
      

  6.   

    >>>>页面的 assembly 应该在这里那么题外话,是否能请思归大哥具体解释一下或者提供链接,aspx页面在被编译完成并保存到
    %WINDOWS%Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\your web project
    后,是如何被加载并显示给客户端的?
    思归大哥认为,在偶所说的datagrid分页情况下,应该继续使用成员变量呢还是选择使用static变量比较好?是否也是一个it depends的问题?:)
      

  7.   

    1. ASP.NET First Principles
    http://dotnetdan.com/articles/aspnet/FirstPrinciples.htm2.分页的情形下,如果你访问数据库耗费不太大,那么就每次访问数据,只返回当前页需要的数据(即在数据库里做分页),使用连接池,注意关闭数据库连接如果你访问数据库耗费比较大,那么争取把返回的数据存在Session变量或可过期的Cache变量(可以使用一个以SessionID起头的KEY)里,如果可以跟别的用户享用的,可以采用static/Application/Cache变量,但需要注意访问冲突问题
      

  8.   

    当然也可以使用别的缓存机制,参考微软的Caching Application Blockhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/caching1.asp