zoukankan      html  css  js  c++  java
  • TinyFrame升级之五:全局缓存的设计及实现

    在任何框架中,缓存都是不可或缺的一部分,本框架亦然。在这个框架中,我们的缓存分为两部分:内存缓存和单次请求缓存。简单说来,就是一个使用微软提供的MemoryCache做扩展,并提供全局唯一实例;另一个使用微软提供的HttpContextBase做扩展,用户每发送一次请求,HttpContextBase都会被关联创建。先来看下接口约束:

       1:  using System;
       2:  using System.Collections.Generic;
       3:  using System.Linq;
       4:  using System.Text;
       5:   
       6:  namespace TinyFrame.Framework.Caching
       7:  {
       8:      public interface ICacheManager
       9:      {
      10:          //根据key获取缓存对象
      11:          T Get<T>(string key);
      12:   
      13:          //设置缓存对象
      14:          void Set(string key, object data, int cacheTime);
      15:   
      16:          //查询key是否被缓存
      17:          bool IsSet(string key);
      18:   
      19:          //从缓存移除
      20:          void Remove(string key);
      21:   
      22:          //缓存移除匹配
      23:          void RemoveByPattern(string pattern);
      24:   
      25:          //清空所有缓存
      26:          void Clear();
      27:      }
      28:  }

    方法不多,但是包含了缓存的增删查。其中Get泛型方法可以通过Key返回缓存对象;Set方法可以添加缓存;IsSet方法可以检测缓存是否存在;Remove方法可以清除已有的单个缓存;RemoveByPattern可以通过正则匹配清除缓存;Clear方法则清除全部缓存。

    首先是MemoryCacheManager的实现:

       1:  using System;
       2:  using System.Collections.Generic;
       3:  using System.Linq;
       4:  using System.Text;
       5:  using System.Runtime.Caching;
       6:  using System.Text.RegularExpressions;
       7:   
       8:  namespace TinyFrame.Framework.Caching
       9:  {
      10:      public class MemoryCacheManager:ICacheManager
      11:      {
      12:          protected ObjectCache Cache
      13:          {
      14:              get { return MemoryCache.Default; }
      15:          }
      16:   
      17:          public T Get<T>(string key)
      18:          {
      19:              return (T)Cache[key];
      20:          }
      21:   
      22:          public void Set(string key, object data, int cacheTime)
      23:          {
      24:              if (data == null)
      25:                  return;
      26:              var policy = new CacheItemPolicy();
      27:              policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
      28:              Cache.Add(new CacheItem(key,data),policy);
      29:   
      30:          }
      31:   
      32:          public bool IsSet(string key)
      33:          {
      34:              return Cache.Contains(key);
      35:          }
      36:   
      37:          public void Remove(string key)
      38:          {
      39:              Cache.Remove(key);
      40:          }
      41:   
      42:          public void RemoveByPattern(string pattern)
      43:          {
      44:              var regex = new Regex(pattern, RegexOptions.Singleline
      45:                                              | RegexOptions.Compiled
      46:                                              | RegexOptions.IgnoreCase);
      47:              var keysToRemove = new List<string>();
      48:              foreach (var item in Cache)
      49:                  if (regex.IsMatch(item.Key))
      50:                      keysToRemove.Add(item.Key);
      51:   
      52:              foreach (string key in keysToRemove)
      53:              {
      54:                  Remove(key);
      55:              }
      56:          }
      57:   
      58:          public void Clear()
      59:          {
      60:              foreach (var item in Cache)
      61:              {
      62:                  Remove(item.Key);
      63:              }
      64:          }
      65:      }
      66:  }

    然后是PerRequestCacheManager的实现:

       1:  using System;
       2:  using System.Collections.Generic;
       3:  using System.Linq;
       4:  using System.Text;
       5:  using System.Web;
       6:  using System.Collections;
       7:  using System.Text.RegularExpressions;
       8:   
       9:  namespace TinyFrame.Framework.Caching
      10:  {
      11:      public class PerRequestCacheManager : ICacheManager
      12:      {
      13:          public PerRequestCacheManager(HttpContextBase context)
      14:          {
      15:              this.context = context;
      16:          }
      17:   
      18:          private readonly HttpContextBase context;
      19:   
      20:          protected virtual IDictionary GetItems()
      21:          {
      22:              if (context != null)
      23:                  return context.Items;
      24:   
      25:              return null;
      26:          }
      27:   
      28:          public T Get<T>(string key)
      29:          {
      30:              var items = GetItems();
      31:              if (items == null)
      32:                  return default(T);
      33:   
      34:              return (T)items[key];
      35:          }
      36:   
      37:          public void Set(string key, object data, int cacheTime)
      38:          {
      39:              var items = GetItems();
      40:              if (items == null)
      41:                  return;
      42:   
      43:              if (data != null)
      44:              {
      45:                  if (items.Contains(key))
      46:                      items[key] = data;
      47:                  else
      48:                      items.Add(key, data);
      49:              }
      50:          }
      51:   
      52:          public bool IsSet(string key)
      53:          {
      54:              var items = GetItems();
      55:              if (items == null)
      56:                  return false;
      57:   
      58:              return items[key] != null;
      59:          }
      60:   
      61:          public void Remove(string key)
      62:          {
      63:              var items = GetItems();
      64:              if (items == null)
      65:                  return;
      66:   
      67:              items.Remove(key);
      68:          }
      69:   
      70:          public void RemoveByPattern(string pattern)
      71:          {
      72:              var items = GetItems();
      73:              if (items == null)
      74:                  return;
      75:   
      76:              var enumerator = items.GetEnumerator();
      77:              var regex = new Regex(pattern, RegexOptions.Singleline
      78:                                            | RegexOptions.Compiled
      79:                                            | RegexOptions.IgnoreCase);
      80:              var keysToRemove = new List<string>();
      81:              while (enumerator.MoveNext())
      82:              {
      83:                  if (regex.IsMatch(enumerator.Key.ToString()))
      84:                  {
      85:                      keysToRemove.Add(enumerator.Key.ToString());
      86:                  }
      87:              }
      88:   
      89:              foreach (string key in keysToRemove)
      90:              {
      91:                  items.Remove(key);
      92:              }
      93:          }
      94:   
      95:          public void Clear()
      96:          {
      97:              var items = GetItems();
      98:              if (items == null)
      99:                  return;
     100:   
     101:              var enumerator = items.GetEnumerator();
     102:              var keysToRemove = new List<string>();
     103:              while (enumerator.MoveNext())
     104:              {
     105:                  keysToRemove.Add(enumerator.Key.ToString());
     106:              }
     107:   
     108:              foreach (string key in keysToRemove)
     109:              {
     110:                  items.Remove(key);
     111:              }
     112:          }
     113:      }
     114:  }

    二者的实现方式差不多。这里我就不做过多的解释了。

    如果想使用的话,直接在Autofac容器中注册一下就行了。在这次演示中,我们使用MemoryCacheManager来做缓存容器。

    这里我以一个分页为例:

       1:  string BookPaggerKey = "Books-{0}-{1}-{2}-{3}";
       2:          //分页查询
       3:          public IList<Book> GetBooksPagger(int pageCount
       4:                                          , int currentIndex
       5:                                          , out int totalCount
       6:                                          , string propertyName=""
       7:                                          , string propertyValue=""
       8:                                          )
       9:          {
      10:              IQueryable<Book> bookList = null;
      11:              int skipRows = 0;
      12:              if (currentIndex > 0) skipRows = currentIndex * pageCount;
      13:   
      14:              if (!string.IsNullOrEmpty(propertyName))
      15:                  bookList = GetBooksByConstruct(propertyName, propertyValue);
      16:              else
      17:                  bookList = bookRepository.GetMany(m => m.ID >= 0);
      18:              totalCount = bookList.Count();
      19:              
      20:              //return bookList.OrderBy(p => p.ID).Skip(skipRows).Take(pageCount).ToList();
      21:              string key = string.Format(BookPaggerKey, pageCount, currentIndex, propertyName, propertyValue);
      22:   
      23:              return cacheManager.Get(key, () => bookList.OrderBy(p => p.ID).Skip(skipRows).Take(pageCount).ToList());
      24:          }

    第1行:定义了一个Cache的Key,用于标识保存ID

    第23行:利用get方法检查缓存容器,如果缓存中数据不存在,则将查询数据添加到缓存;否则直接从缓存中拿出数据来。

    我们来看看效果:

    首先打开页面,我们换换页,目的是让页面被缓存住:

    QQ截图20140415223519

    然后我们打开SQL的SQL Server Profile来进行追踪,现在,我们点击页面的刷新按钮,看看测试效果 :

    QQ截图20140415223805

    当我们连续刷新页面好几次,但是并未见到有新的分页查询被追踪到,说明我们的数据被缓存住了。

    最后我们加个断点调试一下缓存对象,可以找到被缓存的数据:

    QQ截图20140415223959

  • 相关阅读:
    多帐套,多组织 登录系统设计
    Git常用命令速查05
    一步步搭建java信息管理系统00
    Git常用命令速查04
    Git常用命令速查03
    Git常用命令速查02
    Git常用命令速查01
    无法创建k/3中间层组件或组件正在调用中间层问题解决
    jQuery.i18n.properties实现前端国际化
    ORACLE telnet 1521 不通及ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务的解决
  • 原文地址:https://www.cnblogs.com/scy251147/p/3667541.html
Copyright © 2011-2022 走看看