缓存

来源:互联网 发布:不喜欢粗人知乎 编辑:程序博客网 时间: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;
}




 

原创粉丝点击