缓存
来源:互联网 发布:不喜欢粗人知乎 编辑:程序博客网 时间:2024/04/30 11:48
缓存
缓存机制
页输出缓存:保存页处理输出,下次重用所保存的输出
应用程序缓存:允许缓存所生成的数据,如DataSet
㈠页输出缓存
1、页输出缓存的几中形式
① <%@ OutputCache Duration= "60 " VaryByParam= "None " Location= "Any "% >
Location指定在哪个地方缓存,Any任何地方都缓存。
60秒以内看到的都是一样的了。
②还可在配置文件里写,然后在页面调用配置文件的缓存名称。
③用编程的方式:
Response.Canche.SetExpires(DateTime.Now.AddSeconds(3));
Response.Canche.SetCacheabiliy(HttpCacheability.Public);
Response.Canche.SetValidUntilExpires(true);
相当于:
Public = > Any
Private = > Client
NoCache = > None
Server = > Server
ServerAndPrivate = >ServerAndClient
2、使用文件依赖项缓存页输出
产生背景:有时候,可能需要在文件发生更改时从输出缓存中移除某一项。就是说文件改了以后缓存立即失效。
string filepath = Server.MapPath( "TextFile1.txt ");
Response.AddFileDependency(filepath);//添加缓存依赖项
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntiExpires(true);
3、缓存多个版本
①使用请求的浏览器对页的各个版本进行缓存
<%@OutputCache Duration= "10 " VaryByParam= "None " VaryByCustom= "browser "% >
②使用参数对页的各个版本进行缓存
<%@OutputCache Duration= "60 " VaryByParam= "City "% >
这个调试可以在url后加QueryString
如:...url?City=shanghai
程序里得到这个上海然后再做其他的操作,这个时候如果参数传的还是shanghai它就不会在走到程序里了。
4、动态更新缓存页的部分,有三种方法可以实现部分不缓存
①已声明方式使用Substitution控件
<asp:Substitution ID= "Substitution1 " runat= "server " MethodName= "GetCurrentDateTime " / >
public static string GetCurrentDateTime(HttpContext context)
{
return DateTime.Now.ToString();
}
//方法签名必须和委托签名一致
②以编程的方式使用Substitution控件API
Response.WriteSubstitution(new HttpResponseSubstitutionCallback(GetCurrentDateTime))
③以隐式方式使用AdRotator控件
这个控件永远都是不缓存的
㈡SQL Server依赖的缓存,非常之有用
当表数据发生改变就清除缓存
1、为SQL Server启用缓存通知
aspnet_regsql.exe -S <Server > -U <Username > -P <Password >
-ed -d Northwind -et -t Employees
Server:服务器
Username:用户名
Password:密码
Northwind:数据库
Employees:表
2、为缓存功能配置网页
<%@OutputCache Duration= "3600 " SqlDependency= "Northind:Employees " VaryByParam= "none "% >
3、在Web.config文件中设置缓存配置
<caching >
<sqlCacheDependency enabled= "true " pollTime= "1000 " >
<database >
<add name= "Northind " connectionStringName= "... " pollTime = "1000 " / >
</database >
</sqlCacheDependency >
</caching >
//这里的name要是数据库名称
/////////////////////////////////////////////////////////////////////////////////////////////////////////
大家都应该清楚把实体对象更新到数据库必须经过一系列的转换;特别是SQL语句的生成是比较费资源的,因为中间处里的东西实大是太多了。
在设计的过程中我就想如果一个对象插入数据库后把相应的Command保存在缓存中;下一次同一个类型的对象做这个操作时检测一下缓存如果有就直接拿来用这样效率应该会高些。
抱着这种想法就开始设计了(不过心里还是上上下下的,毕竟第一次尝试)。
因为缓存中的对象处理比较复杂点,在多线程中存在共享的问题,如果两个线程同时调用同一个Command这样一定会产生处理错误的!
为了更好地控制Command对象的共享,特别为Command定义了持久化的接口。
经过一段时间的设计和编写,算有点成果吧,顺把自己做的东西共享一下。
以下是组件测试的情况
P4 2.4 1G
SqlServer sp3
运行的代码大概如下:
Entitys.Customers customer = new Test.Entitys.Customers();
DateTime dt = DateTime.Now;
using(HFSoft.Data.IDataSession session = mapcontainer.OpenSession())
{
session.Open();
for(int i =0;i <2000;i++)
{
customer.CustomerID = Guid.NewGuid().ToString();
customer.CompanyName = "henry ";
session.Save(customer);
}
}
tp1 = new TimeSpan(DateTime.Now.Ticks - dt.Ticks);
不开启缓存(5个线程运行时间)
00:00:05.7031250
00:00:06.8281250
00:00:05.0156250
00:00:06.6875000
00:00:06.4218750
--------------------------------------------------------
开启5个命令缓存(5个线程运行时间)
00:00:04.8906250
00:00:03.5625000
00:00:02.8750000
00:00:04.9375000
00:00:05.4843750
---------------------------------------------------------
以下是缓存类的源码
/// <summary >
/// 数据缓存保存信息异步处理委托
/// </summary >
delegate void EventSaveCache(object key,object value);
/// <summary >
/// 对象缓存类
/// </summary >
public class Cache
{
private MappingContainer mContainer;
/// <summary >
/// 获取或设置当前缓存对象所在的关系映象容器
/// </summary >
public MappingContainer Container
{
get
{
return mContainer;
}
set
{
mContainer = value;
}
}
/// <summary >
/// 构造缓存对象
/// </summary >
public Cache()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/// <summary >
/// 用于缓存数据的Hashtable
/// </summary >
protected System.Collections.Hashtable _Cache = new System.Collections.Hashtable();
protected Object _LockObj = new object();
/// <summary >
/// 获取指定键值的对象
/// </summary >
/// <param name= "key " >键值 </param >
/// <returns >object </returns >
public virtual object GetObject(object key)
{
if(_Cache.ContainsKey(key))
return _Cache[key];
return null;
}
/// <summary >
/// 把对象按指定的键值保存到缓存中
/// </summary >
/// <param name= "key " >键值 </param >
/// <param name= "value " >保存的对象 </param >
public void SaveCaech(object key,object value)
{
EventSaveCache save = new EventSaveCache(SetCache);
IAsyncResult ar = save.BeginInvoke(key,value,new System.AsyncCallback(Results),null);
}
private void Results(IAsyncResult ar)
{
EventSaveCache fd = (EventSaveCache)((AsyncResult)ar).AsyncDelegate;
fd.EndInvoke(ar);
}
/// <summary >
/// 把对象按指定的键值保存到缓存中
/// </summary >
/// <param name= "key " >键值 </param >
/// <param name= "value " >保存的对象 </param >
protected virtual void SetCache(object key ,object value)
{
lock(_LockObj)
{
if(!_Cache.ContainsKey(key))
_Cache.Add(key,value);
}
}
public int Count
{
get
{
return _Cache.Count;
}
}
/// <summary >
/// 在缓存中删除指定键值的对象
/// </summary >
/// <param name= "key " >键值 </param >
public virtual void DelObject(object key)
{
lock(_Cache.SyncRoot)
{
_Cache.Remove(key);
}
}
/// <summary >
/// 清除缓存中所有对象
/// </summary >
public virtual void Clear()
{
lock(_Cache.SyncRoot)
{
_Cache.Clear();
}
}
}
/// <summary >
///针对一条记录操作命令的缓存类
/// </summary >
public class CachePersistentCommand:Cache
{
/// <summary >
/// 把记录操作命令缓存到内存中
/// </summary >
/// <param name= "key " >标识 </param >
/// <param name= "value " >值 </param >
protected override void SetCache(object key, object value)
{
lock(_LockObj)
{
int count=0;
if(Container.Config.CommandsCache.ContainsKey(key))
count=(int) Container.Config.CommandsCache[key];
System.Collections.IList _list;
//如果缓存中已经存在这种命令的列表
if(_Cache.ContainsKey(key))
{
_list = (System.Collections.IList)_Cache[key];
if( count >0)//命令的缓存总数
{
if(_list.Count < count)//缓存数据量少于缓存总数
_list.Add(value);
}
else
{
if(_list.Count < Container.Config.CommandBuffer)//缓存数小于组件的默认列表
_list.Add(value);
}
}
else//如果不存在列表
{
if(count >0 ¦ ¦ Container.Config.CommandBuffer >0)//如果组件允许对象缓存
{
_list = new System.Collections.ArrayList();
_list.Add(value);
_Cache.Add(key,_list);
}
}
}
}
/// <summary >
/// 从缓存中获取相关命令对象
/// </summary >
/// <param name= "key " >标识 </param >
/// <returns >IPersistentCommand </returns >
public override object GetObject(object key)
{
if(_Cache.Contains(key))//如果命令存在缓冲中
{
foreach(IPersistentCommand cmd in (System.Collections.IList)_Cache[key])
{
if(!cmd.State)//命令是否可以过行锁定
if(cmd.Lock())//命令锁定
return cmd;
}
}
return null;
}
}