/// <summary>向单对象缓存添加项</summary> /// <param name="key"></param> /// <param name="entity">数值</param> /// <returns></returns> Boolean Add(TKey key, TEntity entity) { // 如果找到项,返回 CacheItem item = null; if (Entities.TryGetValue(key, out item) && item != null && !item.Expired) { return(false); } // 加锁 lock (_SyncRoot) { // 如果已存在并且过期,则复制 // TryGetValue获取成功,Item为空说明同一时间另外线程做了删除操作 if (Entities.TryGetValue(key, out item) && item != null) { if (!item.Expired) { return(false); } item.SetEntity(entity); return(false); } else { return(TryAdd(entity)); } } }
/// <summary>向两个字典加入数据</summary> /// <param name="key"></param> /// <param name="entity"></param> /// <returns></returns> private CacheItem AddItem(TKey key, TEntity entity) { //if (!Using) { Using = true; //WriteLog("单对象缓存首次使用 {0} {1}", typeof(TEntity).FullName, XTrace.GetCaller(1, 16)); StartTimer(); } var skey = entity == null ? null : GetSlaveKeyMethod?.Invoke(entity); var item = new CacheItem { Key = key, SlaveKey = skey }; item.SetEntity(entity, Expire); var es = Entities; // 新增或更新 es[key] = item; if (!skey.IsNullOrWhiteSpace()) { var ses = SlaveEntities; // 新增或更新 ses[skey] = item; } return(item); }
/// <summary>内部处理返回对象。 /// 把对象传进来,而不是只传键值然后查找,是为了避免别的线程移除该项 /// </summary> /// <remarks>此方法只做更新操作,不再进行缓存新增操作</remarks> /// <param name="item"></param> /// <returns></returns> private TEntity GetData(CacheItem item) { if (item == null) { return(null); } Interlocked.Increment(ref Success); // 异步更新缓存 //var tid = Thread.CurrentThread.ManagedThreadId; if (item.Expired) { TaskEx.Run(() => { // 先修改过期时间 item.ExpireTime = DateTime.Now.AddSeconds(Expire); // 更新过期缓存,在原连接名表名里面获取 var entity = Invoke(FindKeyMethod, item.Key); if (entity != null) { item.SetEntity(entity, Expire); } else { // 数据库查不到,说明该数据可能已经被删除 RemoveKey(item.Key); } }); } return(item.Entity); }
/// <summary>尝试向两个字典加入数据</summary> /// <param name="entity"></param> /// <returns></returns> private Boolean TryAdd(TEntity entity) { //if (!Using) { Using = true; //WriteLog("单对象缓存首次使用 {0} {1}", typeof(TEntity).FullName, XTrace.GetCaller(1, 16)); if (_Timer == null) { // 启动一个定时器,用于定时清理过期缓存。因为比较耗时,最后一个参数采用线程池 _Timer = new TimerX(CheckExpire, null, Expire * 1000, Expire * 1000, "SC"); _Timer.Async = true; } } var item = new CacheItem(); var skey = GetSlaveKeyMethod?.Invoke(entity); var mkey = GetKeyMethod(entity); item.Key = mkey; item.SlaveKey = skey; item.SetEntity(entity, Expire); var success = false; var es = Entities; lock (es) { if (!es.ContainsKey(mkey)) { // 如果满了,删除前面一个 while (MaxEntity > 0 && es.Count >= MaxEntity) { var key = es.Keys.First(); RemoveKey(key); //WriteLog("单对象缓存满,删除{0}", key); } es.Add(mkey, item); success = true; } } if (success && !skey.IsNullOrWhiteSpace()) { var ses = SlaveEntities; lock (ses) { // 新增或更新 ses[skey] = item; } } return(success); }
/// <summary>尝试向两个字典加入数据</summary> /// <param name="entity"></param> /// <returns></returns> private Boolean TryAdd(TEntity entity) { if (!Using) { Using = true; if (Debug) { DAL.WriteLog("单对象缓存首次使用 {0} {1}", typeof(TEntity).FullName, XTrace.GetCaller(1, 16)); } } var item = new CacheItem { sc = this }; String slaveKey = null; if (GetSlaveKeyMethod != null) { slaveKey = GetSlaveKeyMethod(entity); } var mkey = GetKeyMethod(entity); item.Key = mkey; item.SlaveKey = slaveKey; item.SetEntity(entity); var success = false; lock (Entities) { if (!Entities.ContainsKey(mkey)) { Entities.Add(mkey, item); success = true; } } if (success && !slaveKey.IsNullOrWhiteSpace()) { lock (SlaveEntities) { // 新增或更新 SlaveEntities[slaveKey] = item; } } return(success); }
/// <summary>向单对象缓存添加项</summary> /// <param name="key"></param> /// <param name="entity">数值</param> /// <returns></returns> Boolean Add(TKey key, TEntity entity) { var es = Entities; // 如果找到项,返回 CacheItem item = null; lock (es) { if (!es.TryGetValue(key, out item) || item == null) { return(TryAdd(entity)); } item.SetEntity(entity, Expire); return(false); } }
/// <summary>向单对象缓存添加项</summary> /// <param name="key"></param> /// <param name="entity">数值</param> /// <returns></returns> Boolean Add(TKey key, TEntity entity) { var es = Entities; // 如果找到项,返回 CacheItem item = null; lock (es) { if (es.TryGetValue(key, out item) && item != null) { item.SetEntity(entity); return(false); } else { return(TryAdd(entity)); } } }
/// <summary>向两个字典加入数据</summary> /// <param name="key"></param> /// <param name="entity"></param> /// <returns></returns> private CacheItem AddItem(TKey key, TEntity entity) { //if (!Using) { Using = true; //WriteLog("单对象缓存首次使用 {0} {1}", typeof(TEntity).FullName, XTrace.GetCaller(1, 16)); StartTimer(); } var skey = entity == null ? null : GetSlaveKeyMethod?.Invoke(entity); var item = new CacheItem { Key = key, SlaveKey = skey }; item.SetEntity(entity, Expire); var es = Entities; // 新增或更新 es[key] = item; //// 如果满了,删除前面一个 //while (MaxEntity > 0 && es.Count >= MaxEntity) //{ // RemoveKey(es.Keys.First()); // WriteLog("单对象缓存满,删除{0}", key); //} if (!skey.IsNullOrWhiteSpace()) { var ses = SlaveEntities; // 新增或更新 ses[skey] = item; } return(item); }
/// <summary>内部处理返回对象。 /// 把对象传进来,而不是只传键值然后查找,是为了避免别的线程移除该项 /// </summary> /// <remarks>此方法只做更新操作,不再进行缓存新增操作</remarks> /// <param name="item"></param> /// <returns></returns> private TEntity GetData(CacheItem item) { if (item == null) { return(null); } // 未过期,直接返回 //if (HoldCache || item.ExpireTime > DateTime.Now) // 这里不能判断独占缓存,否则将失去自动保存的机会 if (!item.Expired) { Interlocked.Increment(ref Shoot); return(item.Entity); } // 自动保存 AutoUpdate(item, "获取缓存过期"); // 判断别的线程是否已更新 if (HoldCache || !item.Expired) { return(item.Entity); } // 更新过期缓存,在原连接名表名里面获取 var entity = Invoke(FindKeyMethod, item.Key); if (entity != null || AllowNull) { item.SetEntity(entity); } else { Interlocked.Increment(ref Invalid); } return(entity); }