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

  • 相关阅读:
    select、poll和epoll
    Linux 常用命令之文件和目录
    SmartPlant Review 帮助文档机翻做培训手册
    SmartPlant Foundation 基础教程 3.4 菜单栏
    SmartPlant Foundation 基础教程 3.3 标题栏
    SmartPlant Foundation 基础教程 3.2 界面布局
    SmartPlant Foundation 基础教程 3.1 DTC登陆界面
    SmartPlant Foundation 基础教程 1.4 SPF架构
    SmartPlant Foundation 基础教程 1.3 SPF其他功能
    SmartPlant Foundation 基础教程 1.2 SPF集成设计功能
  • 原文地址:https://www.cnblogs.com/scy251147/p/3667541.html
Copyright © 2011-2022 走看看