TinyFrame升级之五:全局缓存的设计及实现
在任何框架中,緩存都是不可或缺的一部分,本框架亦然。在這個(gè)框架中,我們的緩存分為兩部分:內(nèi)存緩存和單次請(qǐng)求緩存。簡(jiǎn)單說來,就是一個(gè)使用微軟提供的MemoryCache做擴(kuò)展,并提供全局唯一實(shí)例;另一個(gè)使用微軟提供的HttpContextBase做擴(kuò)展,用戶每發(fā)送一次請(qǐng)求,HttpContextBase都會(huì)被關(guān)聯(lián)創(chuàng)建。先來看下接口約束:
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: //根據(jù)key獲取緩存對(duì)象 11: T Get<T>(string key); 12: ? 13: //設(shè)置緩存對(duì)象 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返回緩存對(duì)象;Set方法可以添加緩存;IsSet方法可以檢測(cè)緩存是否存在;Remove方法可以清除已有的單個(gè)緩存;RemoveByPattern可以通過正則匹配清除緩存;Clear方法則清除全部緩存。
首先是MemoryCacheManager的實(shí)現(xiàn):
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的實(shí)現(xiàn):
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: }?
二者的實(shí)現(xiàn)方式差不多。這里我就不做過多的解釋了。
如果想使用的話,直接在Autofac容器中注冊(cè)一下就行了。在這次演示中,我們使用MemoryCacheManager來做緩存容器。
這里我以一個(gè)分頁為例:
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行:定義了一個(gè)Cache的Key,用于標(biāo)識(shí)保存ID
第23行:利用get方法檢查緩存容器,如果緩存中數(shù)據(jù)不存在,則將查詢數(shù)據(jù)添加到緩存;否則直接從緩存中拿出數(shù)據(jù)來。
我們來看看效果:
首先打開頁面,我們換換頁,目的是讓頁面被緩存住:
然后我們打開SQL的SQL Server Profile來進(jìn)行追蹤,現(xiàn)在,我們點(diǎn)擊頁面的刷新按鈕,看看測(cè)試效果 :
當(dāng)我們連續(xù)刷新頁面好幾次,但是并未見到有新的分頁查詢被追蹤到,說明我們的數(shù)據(jù)被緩存住了。
最后我們加個(gè)斷點(diǎn)調(diào)試一下緩存對(duì)象,可以找到被緩存的數(shù)據(jù):
轉(zhuǎn)載于:https://www.cnblogs.com/scy251147/p/3667541.html
總結(jié)
以上是生活随笔為你收集整理的TinyFrame升级之五:全局缓存的设计及实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sqlserver55555_sqlse
- 下一篇: 小程序“成语猜题”部分答案,总共2866