Пример #1
0
        /// <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));
                }
            }
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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);
            }
        }
Пример #7
0
        /// <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));
                }
            }
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        /// <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);
        }