You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
5.8 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Utils
{
public class ConcurrentCache<Key, Value> where Value : class
{
private ConcurrentDictionary<Key, Value> _cache;
private Func<Key, Value> _getData;
private Func<Value, Key> _getKey;
/// <summary>
/// 初始化构造函数
/// </summary>
/// <param name="getKey">从Value中获取Key</param>
/// <param name="getData">传入根据Key从数据库获取Value的方法</param>
public ConcurrentCache(Func<Value, Key> getKey, Func<Key, Value> getData)
{
_getData = getData;
_getKey = getKey;
_cache = new ConcurrentDictionary<Key, Value>();
}
/// <summary>
/// 尝试根据Key获取Value若不存在则返回null
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Value TryGetOne(Key key)
{
Value rtnValue = null;
bool isSuccess = _cache.TryGetValue(key, out rtnValue);
return rtnValue;
}
/// <summary>
/// 根据Key获取Value若不存在则访问数据库获取若还是不存在则返回null
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Value GetOne(Key key)
{
Value rtnValue = TryGetOne(key);
if (rtnValue == null)
{
rtnValue = _getData(key);
if (rtnValue != null)
{
AddOrUpdate(rtnValue);
}
}
return rtnValue;
}
/// <summary>
/// 根据列表ID获取对应值
/// </summary>
/// <param name="func">委托获取列表方法</param>
/// <param name="ids">主键ID集合</param>
/// <returns></returns>
public List<Value> GetList(Func<List<Key>, List<Value>> func, List<Key> ids)
{
List<Value> list = new List<Value>();
List<Key> keyList = new List<Key>();
foreach (var item in ids)
{
if (TryGetOne(item) == null)
{
keyList.Add(item);
}
}
try
{
list = func(keyList);
if (list != null && list.Count > 0)
{
foreach (var item in list)
{
Key key = _getKey(item);
_cache[key] = item;
}
}
}
catch (Exception ex)
{
LogHelper.Log.WriteError("获取列表缓存出错", ex);
}
return list;
}
/// <summary>
/// 增加或更新缓存建议使用SyncCache方法
/// </summary>
/// <param name="v"></param>
public void AddOrUpdate(Value value)
{
Key key = _getKey(value);
if (_cache.ContainsKey(key))
{
Value temp = TryGetOne(key);
_cache.TryUpdate(key, value, temp);
}
else
{
_cache.TryAdd(key, value);
}
}
/// <summary>
/// 批量插入缓存
/// </summary>
/// <param name="listV"></param>
public void AddList(List<Value> listV)
{
if (listV != null && listV.Count > 0)
{
try
{
foreach (var item in listV)
{
Key key = _getKey(item);
if (!_cache.ContainsKey(key))
{
_cache.TryAdd(key, item);
}
else
{
_cache[key] = item;
}
}
}
catch (Exception ex)
{
LogHelper.Log.WriteError("[批量插入缓存错误]", ex);
}
}
}
/// <summary>
/// 根据Key移除缓存建议使用SyncCache方法
/// </summary>
/// <param name="key"></param>
public void Remove(Key key)
{
Value tmpV = null;
try
{
if (_cache.ContainsKey(key))
{
_cache.TryRemove(key, out tmpV);
}
}
catch (Exception ex)
{
LogHelper.Log.WriteError("移除缓存出错", ex);
}
}
/// <summary>
/// 根据传入方法初始化缓存列表(会清除原有缓存)
/// </summary>
/// <param name="func">获取列表方法</param>
public void InitList(Func<List<Value>> func)
{
this._cache.Clear();
var list = func();
AddList(list);
}
/// <summary>
/// 同步缓存
/// </summary>
/// <param name="key">缓存键</param>
/// <param name="value">缓存值</param>
/// <param name="del">是否删除</param>
/// <remarks>
/// 新增:SyncCache(Id,Value,false)
/// 修改:SyncCache(Id,Value,false)
/// 删除:SyncCache(Id,null,true)
/// </remarks>
public void SyncCache(Key key, Value value, bool del)
{
if (del)
{
Remove(key);
}
else
{
AddOrUpdate(value);
}
}
}
}