ASPNET中的新状态容器
前面我们提到ASPNET为保存用户请求间的数据添加了几种新的途径这些途径给了你如何保持状态信息更好的控制这些技术的范围可以窄到只有一个请求那么小(Context对象)也可以宽到整个Web服务器和服务器上的所有应用程序(Machineconfig文件)在多数情况下你有多种保存特定数据片的选择使用每个方法描述的问题和答案来决定某个对象是否适合你的需要
Cache
Cache对象用于单个用户一组用户或所有的用户这种数据为多个请求保持它可以保持很长时间但是不能超过应用程序重新启动的时间并且数据的终止基于时间或者其它的依赖关系它可以高效率地保持大量或少量地数据
Cache 是ASPNET中最酷的对象之一它提供了难以置信的灵活性通用性和性能因此在ASPNET应用程序中它通常是比Application或Sessions更好的保持数据的对象本文没有详细介绍Cache对象的使用方法但是仍然可以说它是一个万能对象与其它的集合对象相似它是一个简单的名称-值集合但是通过使用指定特定用户的键值可以缓存特定用户的值同样你可以缓存不同的相关数据的多个数据集例如几个有键(如fordcars chevycarsgmcars)的汽车集合Cache中的数据可以给定一个绝对的可变的或基于文件的终止时间它们也实现了一个回调功能在被缓存的值从缓存中提取时被调用这个功能很有用因为接着你能检查它是否为最新的数据变量如果不是(或数据源不可用)就重新缓存被终止的值
添加和访问缓存中值的语法与先前谈到的相似但是Cache给访问集合内容的标准索引器方法作了补充它支持多种方法允许对被缓存数据的更多的控制最频繁使用的方法是Insert它支持几种重载允许你指定依赖超时值优先级和回调下面是一些简单的例子
// 给缓存添加项
Cache[myKey] = myValue;
// 从缓存中读取项
ResponseWrite(Cache[myKey]);
// 把CacheDuration增加秒并把项添加到缓存中
CacheInsert(myKeymyValue null SystemDateTimeNowAddSeconds()
SystemWebCachingCacheNoSlidingExpiration);
Cache对象的最强大的特性之一是当缓存中的某个项终止时执行回调的能力它使用了委托或函数指针这在本文中没有讨论幸运的是一旦你有了某些这些技术怎样工作的示例就能通过简单的剪切和粘贴在应用程序中使用它们不需要知道委托是怎样工作的复杂过程有很多使用这种功能的原因最通常的是在数据终止时用当前数据重新填充缓存或者如果重新填充缓存的数据源不可用时恢复旧的缓存数据
在我的例子中简单地缓存了当前时间当缓存超期的时候我将给缓存中的字符串末尾添加一个星号(*)在超过时间后你能通过计算星号的数量来确定缓存超期了多少次图演示了回调的重要概念并且提供了给使用缓存建立更多功能回调程序的好模板
private void Page_Load(object sender SystemEventArgs e)
{
string cacheKey = myKey;
string data = ;
// 检查数据是否已经被缓存了
if(Cache[cacheKey]==null)
{
// 因为数据在缓存中所有读取数据
data = SystemDateTimeNowToString();
//建立回调委托的一个实例
CacheItemRemovedCallback callBack =new CacheItemRemovedCallback(onRemove);
LabelText = Generated: + data;
CacheInsert(cacheKeydatanull
SystemDateTimeNowAddSeconds()
SystemWebCachingCacheNoSlidingExpiration
SystemWebCachingCacheItemPriorityDefault
callBack);
}
else
{
LabelText = Cached: + Cache[cacheKey]ToString();
}
}
private void onRemove(string key object valCacheItemRemovedReason reason)
{
//建立回调委托的一个实例
CacheItemRemovedCallback callBack =new CacheItemRemovedCallback(onRemove);
CacheInsert(keyvalToString() +
*nullSystemDateTimeNowAddSeconds()CacheNoSlidingExpiration
SystemWebCachingCacheItemPriorityDefault callBack);
}
代码段缓存回调示例
注意代码段中一个重要的特性是在Page_Load中使用模式(pattern)来确定是否使用缓存中的数据当你处理缓存中的项时也可能使用这种模式使用if语句来检查缓存的当前内容是否为空(因为要多次引用为缓存键使用了一个变量)如果是空的从数据源生成数据并放入缓存中如果不是空的从缓存中返回数据如果数据访问逻辑很复杂你需要把整个if语句放入一个独立的函数该函数的任务是检索数据
Cache对象的功能比先前我们讨论的大多数对象多得多这也是ASPNET更强大的功能之一并且我明确地推荐阅读关于它的更多内容
Context
Context对象保持单个用户单个请求的数据并且数据只在该请求期间保持Context容器可以保持大量的数据但是典型的情况下是保存小的数据片因为它经常通过globalasax中的某个处理方法为每个请求实现
Context容器(从Page对象访问或使用SystemWebHttpContextCurrent)被提供用于保持需要在不同的HttpModules和HttpHandlers之间传递的值它也可以用于保持某个完整请求的相应信息例如IbuySpy入口在globalasax中的Application_BeginRequest事件过程中给容器填满了许多配置信息注意这只在当前请求中可用如果你希望在下一个请求中也能使用请考虑使用ViewState
从Context集合中设置和获取数据使用的语法与前面讨论的其它集合对象(如ApplicationSessions和 Cache)的相似下面是两个简单的例子
// 给Context添加项
ContextItems[myKey] = myValue;
// 从Context中读取项
ResponseWrite(Context[myKey]);
ViewState
ViewState为单个用户保持状态信息保持期为ASPX页面工作时间ViewState容器可以保持大量的数据但是必须小心管理ViewState的大小因为它增加了每个请求和回应的下载(download)大小
ViewState是ASPNET中的一个新容器也许你已经使用它了但是你可能还是不了解它这是因为所有的内建Web控件都使用ViewState在页面回发(postback)间保持自己的值但是你必须小心因为它影响应用程序的性能影响的大小依赖于回发之间使用ViewState的多少对大多数Web窗体来说数量非常小
确定某个页面上每个控件使用的ViewState的数量最简单的方法是打开页面追蹤并检查每个控件负载了多少个ViewState如果某个特定控件不需要在回发之间保持数据请通过把EnableViewState设置为false关闭该对象的ViewState你也可以通过在浏览器中查看的HTML源并检查隐藏窗体字段__VIEWSTATE来确定某个给定的ASPNET页面ViewState的总共大小注意这些内容都是使用Base编码的用于放置偶然的查看和维护ViewState也可以通过给@Page指令添加EnableViewState=false在整个页面中禁止
典型的Web窗体不需要直接维护ViewState但是如果你建立自定义Web控件就需要了解它是怎样工作的并为你的控件实现它这样该控件的工作方式才能与随ASPNET发布的Web控件同样地工作向ViewState读取或写入值都可以通过上面讨论地其它集合对象的语法完成
// 给ViewState添加项
ViewState[myKey] = myValue;
//从Context读取项
ResponseWrite(ViewState[myKey]);
当建立自定义Web控件时你也许希望它们有ViewState的好处这在控件的属性层可以简单实现代码段演示了怎样保存一个简单的自定义控件的PersonName属性到ViewState中并在该控件的Render方法中使用它
namespace MSDNStateManagement
{
public class HelloPerson : SystemWebUIControl
{
public string PersonName
{
get
{
string s = (string)ViewState[PersonName];
return ((s == null) ? : s);
}
set
{
ViewState[PersonName] = value;
}
}
protected override void Render(SystemWebUIHtmlTextWriter writer)
{
writerWrite(Hello + PersonName);
}
}
}
代码段在ViewState中保存数据
Webconfig和Machineconfig文件
这些文件中的数据对于某个应用程序的所有用户来说都可以使用Webconfig文件中存储的数据可用于应用程序的整个生命周期这些数据一般很小该对象一般用于保持文件位置和数据库连接的字符串大的数据片最好保存在其它位置
作为其它多样集合对象的补充ASPNET引入了一组XML配置文件用于管理应用程序甚至于整个服务器的很多设置每个ASPNET应用程序使用Webconfig文件来设置它的许多属性每个服务器在系统文件夹下有一个作为应用程序基础的Machineconfig文件这些设置都作为默认值使用除非重载作为保存配置数据的补充这些文件可以保存应用程序(或多个应用程序)需要的数据
无论什么时候应用程序启动都会读取配置信息接着这些信息被缓沖由于被缓沖了应用程序可以快速读取它们因此不需要考虑应用程序的瓶颈因为它经常执行某个文本文件的一些整型信息此外某个应用程序的Webconfig的改变将导致应用程序重新启动这确保了对配置文件信息的修改立即反映到应用程序中
数据库连接信息默认图像路径和XML数据文件路径是通常保存在Webconfig文件中的数据片在Webconfig文件中保存数据的语法如下在理想的情况下你也许希望使用集成的SQL身分验证
<configuration>
<!应用程序特殊设置 >
<appSettings>
<add key=connectionString value=server=myDBServer;
uid=myUID;pwd=myPassword;database=myDB />
</appSettings>
<systemweb>
<!所有的wsb设置 >
</systemweb>
</configuration>
为了访问ASPNET页面中的值可以使用ConfigurationSettings集合它在SystemConfiguration名字空间中下面的简单例子演示了怎样提取前面的连接字符串到一个本地变量中
using SystemConfiguration;
ooo
String strConnString =
ConfigurationSettingsAppSettings[connectionString];
给SystemConfiguration名字空间添加一个引用减少了引用这些值的代码数量因为对Webconfig或 Machineconfig的修改将导致应用程序立即重新启动典型情况下这些值只由服务器系统管理员手动修改因此你可以认为这些文件是保存只读数据而不是应用程序中修改的数据的好位置
结论
有效的状态管理意味着识别的用户经验数据错误与快速的页面或事务处理之间的巨大差别尽管状态管理在ASP 中不太适用但是ASPNET把它带到了本文讨论的状态对象的控制之下小心地使用它们将使你给用户展示最佳的Web经验