日期:2014-02-03  浏览次数:20428 次

ASP.NET中的新状态容器

  前面我们提到,ASP.NET为保存用户请求间的数据添加了几种新的途径。这些途径给了你如何保持状态信息更好的控制。这些技术的范围可以窄到只有一个请求那么小(Context对象),也可以宽到整个Web服务器和服务器上的所有应用程序(Machine.config文件)。在多数情况下你有多种保存特定数据片的选择--使用每个方法描述的问题和答案来决定某个对象是否适合你的需要。

  Cache

  Cache对象用于单个用户、一组用户或所有的用户。这种数据为多个请求保持。它可以保持很长时间,但是不能超过应用程序重新启动的时间,并且数据的终止基于时间或者其它的依赖关系。它可以高效率地保持大量或少量地数据。

  Cache 是ASP.NET中最"酷"的对象之一。它提供了难以置信的灵活性、通用性和性能,因此在ASP.NET应用程序中它通常是比Application或Sessions更好的保持数据的对象。本文没有详细介绍Cache对象的使用方法,但是仍然可以说它是一个万能对象。与其它的集合对象相似,它是一个简单的名称-值集合,但是通过使用指定特定用户的键值可以缓存特定用户的值。同样你可以缓存不同的相关数据的多个数据集,例如几个有键(如fordcars 、 chevycars、gmcars)的汽车集合。Cache中的数据可以给定一个绝对的、可变的或基于文件的终止时间。它们也实现了一个回调功能,在被缓存的值从缓存中提取时被调用,这个功能很有用,因为接着你能检查它是否为最新的数据变量,如果不是(或数据源不可用),就重新缓存被终止的值。

  添加和访问缓存中值的语法与先前谈到的相似。但是Cache给访问集合内容的标准索引器方法作了补充,它支持多种方法,允许对被缓存数据的更多的控制。最频繁使用的方法是Insert,它支持几种重载,允许你指定依赖、超时值、优先级和回调。下面是一些简单的例子:


// 给缓存添加项
Cache["myKey"] = myValue;

// 从缓存中读取项
Response.Write(Cache["myKey"]);

// 把CacheDuration增加10秒并把项添加到缓存中
Cache.Insert("myKey",myValue, null, System.DateTime.Now.AddSeconds(10),
System.Web.Caching.Cache.NoSlidingExpiration);
 

  Cache对象的最强大的特性之一是当缓存中的某个项终止时执行回调的能力。它使用了委托或函数指针,这在本文中没有讨论。幸运的是一旦你有了某些这些技术怎样工作的示例,就能通过简单的剪切和粘贴在应用程序中使用它们,不需要知道委托是怎样工作的复杂过程。有很多使用这种功能的原因,最通常的是在数据终止时用当前数据重新填充缓存,或者如果重新填充缓存的数据源不可用时恢复旧的缓存数据。

  在我的例子中,简单地缓存了当前时间,当缓存超期的时候,我将给缓存中的字符串末尾添加一个星号(*)。在超过时间后,你能通过计算星号的数量来确定缓存超期了多少次。图9演示了回调的重要概念,并且提供了给使用缓存建立更多功能回调程序的好模板。


private void Page_Load(object sender, System.EventArgs e)
{
 string cacheKey = "myKey";
 string data = "";
 // 检查数据是否已经被缓存了
 if(Cache[cacheKey]==null)
 {
  // 因为数据在缓存中,所有读取数据
  data = System.DateTime.Now.ToString();

  //建立回调委托的一个实例
  CacheItemRemovedCallback callBack =new CacheItemRemovedCallback(onRemove);

  Label1.Text = "Generated: " + data;

  Cache.Insert(cacheKey,data,null,
      System.DateTime.Now.AddSeconds(5),
      System.Web.Caching.Cache.NoSlidingExpiration,
      System.Web.Caching.CacheItemPriority.Default,
      callBack);
 }
 else
 {
  Label1.Text = "Cached: " + Cache[cacheKey].ToString();
 }
}

private void onRemove(string key, object val,CacheItemRemovedReason reason)
{
 //建立回调委托的一个实例
 CacheItemRemovedCallback callBack =new CacheItemRemovedCallback(onRemove);
    Cache.Insert(key,val.ToString() +
    "*",null,System.DateTime.Now.AddSeconds(5),Cache.NoSlidingExpiration,
    System.Web.Caching.CacheItemPriority.Default, callBack);
}
 

代码段5.缓存回调示例

  注意代码段中一个重要的特性是在Page_Load中使用模式(pattern)来确定是否使用缓存中的数据。当你处理缓存中的项时也可能使用这种模式。使用if语句来检查缓存的当前内容是否为空(因为要多次引用,为缓存键使用了一个变量)。如果是空的,从数据源生成数据并放入缓存中。如果不是空的,从缓存中返回数据。如果数据访问逻辑很复杂,你需要把整个if语句放入一个独立的函数,该函数的任务是检索数据。
Cache对象的功能比先前我们讨论的大多数对象多得多。这也是ASP.NET更强大的功能之一,并且我明确地推荐阅读关于它的更多内容。

  Context

  Context对象保持单个用户、单个请求的数据,并且数据只在该请求期间保持。Context容器可以保持大量的数据,但是典型的情况下是保存小的数据片,因为它经常通过global.asax中的某个处理方法为每个请求实现。

  Context容器(从Page对象访问或使用System.Web.HttpContext.Current)被提供用于保持需要在不同的HttpModules和HttpHandlers之间传递的值。它也可以用于保持某个完整请求的相应信息。例如,IbuySpy入口在global.asax中的Application_BeginRequest事件过程中给容器填满了许多配置信息。注意这只在当前请求中可用,如果你希望在下一个请求中也能使用,请考虑使用ViewState。

  从Context集合中设置和获取数据使用的语法与前面讨论的其它集合对象(如Application、Sessions和 Cache)的相似。下面是两个简单的例子:


// 给Context添加项
Context.Items["myKey"] = myValue;

// 从Context中读取项
Response.Write(Context["myKey"]);

  ViewState

  ViewState为单个用户保持状态信息,保持期为ASPX页面工作时间。ViewState容器可以保持大量的数据,但是必须小心管理ViewState的大小,因为它增加了每个请求和回应的下载(download)大小。

  ViewState是ASP.NET中的一个新容器,也许你已经使用它了,但是你可能还是不了解它。这是因为所有的内建Web控件都使用ViewState在页面回发(postback)间保持自己的值。但是你必须小心,因为它影响应用程序的性能。影响的大小依赖于回发之间使用ViewState的多少--对大多数Web窗体来说数量非常小。

  确定某个页面上每个控件使用的ViewState的数量最简单的方法是打开页面追踪并检查每个控件负载了多少个ViewState。如果某个特定控件不需要在回发之间保持数据,请通过把EnableViewState设置为false关闭该对象的ViewState。你也可以通过在浏览器中查看的HTML源并检查隐藏窗体字段__VIEWSTATE来确定某个给定的ASP.NET页面ViewState的总共大小。注意这些内容都是使用Base64编码的,用于放置偶然的查看和维护。ViewState也