最近做一个C#项目,刚做完基础数据,现把缓存机制给大家分享一下:
做过基础数据的同学应该都知道,每次涉及到查询数据时都会去数据库把配置好的基础数据查询出来,这样每次在操作是会很慢。那么我们每次点开一个新页面都会去数据库查询一下基础数据,这样会频繁的连接数据库,用户多了之后肯定就会特别慢。因为数据一旦配好之后就会很少去改动它,所以我们可以做一个缓存把每次查询出来的基础数据缓存起来,这样就可以提高查询效率。好了,废话不多说了,上代码。
我声明一下我用的是Dictionary数据字典,您也可以使用Cache等等别的技术,实现机制都一样。
我使用了一个接口,一个抽象类,一个工厂类,一个普通类。
首先我们得定义设置缓存,获取缓存,删除缓存的方法,还要定义缓存的大小,太大了就会不好控制,消耗内存。在接口中定义方法,然后用抽象类继承接口实现方法,因为缓存是一直保存在整个网站运行期间,所以不能实例化它,我们得用abstract类,用工厂模式实现调用。 需要注意一点就是我们可以定义Dictionary里面的类型为泛型类而不用object类型,这样在使用的时候就不用装箱,拆箱。
以下是接口ICache代码:
/// <summary>
/// 设置缓存
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
void SetCache(TKey key, TValue value);
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
TValue GetCache(TKey key);
/// <summary>
/// 清空指定缓存
/// </summary>
void Clear(TKey key);
/// <summary>
/// 清空当前登录用户的缓存
/// </summary>
/// <param name="key"></param>
void ClearAll();
/// <summary>
/// 定义缓存Key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
TKey JoinKey(TKey key);
/// <summary>
/// 缓存大小
/// </summary>
int CacheSize { get; set; }
接着,我们用一个抽象类(AbstractCache)继承接口,这里面的大部分都是虚方法,因为我们在使用的时候考虑到还有别的缓存,所以可以在继承类里面重写这些方法。
public AbstractCache(string type)
{
this._type = type;
if (AbstractCache<TKey, TValue>._cacheList == null)
{
AbstractCache<TKey, TValue>._cacheList = new Dictionary<string, Dictionary<TKey, TValue>>();
}
if (!AbstractCache<TKey, TValue>._cacheList.ContainsKey(_type))
{
AbstractCache<TKey, TValue>._cacheList.Add(this._type, new Dictionary<TKey, TValue>());
}
}
private static Dictionary<string, Dictionary<TKey, TValue>> _cacheList;
private string _type;
private int _cacheSize = 100;
public virtual void SetCache(TKey key, TValue value)
{
Dictionary<TKey, TValue> dic = this.getTypeCache();
lock (AbstractCache<TKey, TValue>._cacheList)
{
TKey fullKey = this.JoinKey(key);
if (!dic.ContainsKey(fullKey))
{
if (dic.Count >= this._cacheSize)
{
if (dic.Keys.Count > 0)
{
TKey tmpKey = default(TKey);
foreach (TKey k in dic.Keys)
{
tmpKey = k;
break;
}
dic.Remove(tmpKey);
}
}
if (value != null)
{
dic.Add(fullKey, value);
}
else
{
dic.Add(fullKey, default(TValue));
}
}
else
{
if (value != null)
{
dic[fullKey] = value;
}
else
{
dic[fullKey] = default(TValue);
}
}
}
}
public virtual TValue GetCache(TKey key)
{
Dictionary<TKey, TValue> dic = this.getTypeCache();
TKey fullKey = this.JoinKey(key);
if (dic.ContainsKey(fullKey))
{
return dic[fullKey];
}
return default(TValue);
}
public virtual void Clear(TKey key)
{
Dictionary<TKey, TValue> dic = this.getTypeCache();
lock (AbstractCache<TKey, TValue>._cacheList)
{
TKey fullKey = this.JoinKey(key);
if (dic.ContainsKey(fullKey))
{
dic.Remove(fullKey);
}
}
}
public virtual void ClearAll()
{
throw new NotImplementedException();
}
public abstract TKey JoinKey(TKey key);
public int CacheSize
{
get
{
return _cacheSize;
}
set
{
_cacheSize = value;
}
}
/// <summary>
/// 获取当前类型的缓存数据
/// </summary>
/// <returns></returns>
protected Dictionary<TKey, TValue> getTypeCache()
{
Dictionary<TKey, TValue> dic = AbstractCache<TKey, TValue>._cacheList[this._type];
if (dic == null)
{
throw new Exception("不正确的初始化方式");
}
return dic;
}
接下来我们需要顶一个DataAuthCache类来继承抽象类重写一些自己需要的方法,
public DataAuthCache()
: base("DataAuthCache") //这个参数是区分缓存那一部分类容的
{
}
private static object _lockObj = new object();
public override string JoinKey(string entityName)
{
return Entity.Session.Manage.Current.AuthContext.OrgID + "_" + Entity.Session.Manage.Current.AuthContext.UserID + "_" + entityName;
}
public override void ClearAll()
{
long orgKey = Entity.Session.Manage.Current.AuthContext.OrgID;
long userKey = Entity.Session.Manage.Current.AuthContext.UserID;
lock (_lockObj)
{
Dictionary<string, string> dic = this.getTypeCache();
string containKey = orgKey + "_" + userKey;
List<string> keys = new List<string>();
//Dictionary里面Keys不能用索引直接访问
foreach (string key in dic.Keys)
{
keys.Add(key);
}
if (keys.Count > 0)
{
foreach (string key in keys)
{
if (key.IndexOf(containKey) > 0)
{
dic.Remove(key);
}
}
}
}
}
然后,我们可以定义一个工厂类(AbstractCacheFactory)来实现外部的调用
private static ICache<string, string> _dataAuthCache = null;
public static AbstractCache<string, string> GetDataAuthCache()
{
if (_dataAuthCache == null)
{
_dataAuthCache = new DataAuthCache();
}
return (AbstractCache<string, string>)_dataAuthCache;
}
好了,到这,我们就完成缓存了,很简单吧!
AbstractCache<string, string> dac =AbstractCacheFactory.GetDataAuthCache();
string cacheHql = dac.GetCache(tpl.EntityName);
cacheHql就是我们缓存的数据查询片段,好了,就分享到这儿了。欢迎大家提出宝贵意见,和分享搞好的方法。