From aefdecd0aa3226b7d00d1dc764241b82658b3be8 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期五, 06 三月 2026 10:41:02 +0800
Subject: [PATCH] 添加机器人客户端;更新 WCS 缓存及任务

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/HybridCacheService.cs |  652 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 648 insertions(+), 4 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/HybridCacheService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/HybridCacheService.cs
index 55c3c22..36f0375 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/HybridCacheService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/HybridCacheService.cs
@@ -53,9 +53,20 @@
         public bool Add(string key, string value, int expireSeconds = -1, bool isSliding = false)
         {
             var fullKey = BuildKey(key);
-            SetMemoryCache(fullKey, value, expireSeconds, isSliding);
+
+            // 鍙湁鍚敤L1缂撳瓨鏃舵墠鍐欏叆鍐呭瓨缂撳瓨
+            if (_options.EnableL1Cache)
+            {
+                SetMemoryCache(fullKey, value, expireSeconds, isSliding);
+            }
+
             if (!RedisAvailable)
             {
+                if (!_options.EnableL1Cache)
+                {
+                    _logger.LogWarning("Redis涓嶅彲鐢ㄤ笖L1缂撳瓨宸茬鐢�, key={Key}", key);
+                    return false;
+                }
                 _logger.LogWarning("Redis涓嶅彲鐢紝浠呬娇鐢ㄥ唴瀛樼紦瀛�, key={Key}", key);
                 return true;
             }
@@ -69,7 +80,7 @@
             catch (Exception ex)
             {
                 _logger.LogWarning(ex, "Redis Add澶辫触, key={Key}", key);
-                return _options.FallbackToMemory;
+                return _options.FallbackToMemory && _options.EnableL1Cache;
             }
         }
 
@@ -91,8 +102,14 @@
         public bool Remove(string key)
         {
             var fullKey = BuildKey(key);
-            _memoryCache.Remove(fullKey);
-            if (!RedisAvailable) return true;
+
+            // 鍙湁鍚敤L1缂撳瓨鏃舵墠浠庡唴瀛樼紦瀛樹腑绉婚櫎
+            if (_options.EnableL1Cache)
+            {
+                _memoryCache.Remove(fullKey);
+            }
+
+            if (!RedisAvailable) return _options.EnableL1Cache;
             try
             {
                 return _connectionManager.GetDatabase().KeyDelete(fullKey);
@@ -109,9 +126,434 @@
             foreach (var key in keys) Remove(key);
         }
 
+        #region 鍒犻櫎鎵╁睍鏂规硶
+
+        public string? RemoveAndGet(string key)
+        {
+            var value = Get(key);
+            if (value != null) Remove(key);
+            return value;
+        }
+
+        public T? RemoveAndGet<T>(string key) where T : class
+        {
+            var value = Get<T>(key);
+            if (value != null) Remove(key);
+            return value;
+        }
+
+        public int RemoveByPrefix(string prefix)
+        {
+            if (string.IsNullOrEmpty(prefix)) return 0;
+            var fullPrefix = BuildKey(prefix);
+            int count = 0;
+
+            // 鍒犻櫎鍐呭瓨缂撳瓨涓殑鍖归厤椤�
+            // MemoryCache鏃犳硶鏋氫妇锛岃烦杩�
+
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var server = _connectionManager.GetServer();
+                    var keys = server.Keys(pattern: $"{fullPrefix}*").ToArray();
+                    if (keys.Length > 0)
+                    {
+                        count = (int)_connectionManager.GetDatabase().KeyDelete(keys);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis RemoveByPrefix澶辫触, prefix={Prefix}", prefix);
+                }
+            }
+
+            return count;
+        }
+
+        public int RemoveByPattern(string pattern)
+        {
+            if (string.IsNullOrEmpty(pattern)) return 0;
+            int count = 0;
+
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var server = _connectionManager.GetServer();
+                    var keys = server.Keys(pattern: $"{_options.KeyPrefix}{pattern}").ToArray();
+                    if (keys.Length > 0)
+                    {
+                        count = (int)_connectionManager.GetDatabase().KeyDelete(keys);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis RemoveByPattern澶辫触, pattern={Pattern}", pattern);
+                }
+            }
+
+            return count;
+        }
+
+        public int RemoveAll(IEnumerable<string> keys)
+        {
+            if (keys == null) return 0;
+            int count = 0;
+            foreach (var key in keys)
+            {
+                if (Remove(key)) count++;
+            }
+            return count;
+        }
+
+        public int RemoveWhere(Func<string, bool> predicate)
+        {
+            if (predicate == null) return 0;
+            int count = 0;
+
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var server = _connectionManager.GetServer();
+                    var keys = server.Keys(pattern: $"{_options.KeyPrefix}*").ToArray();
+                    var keysToDelete = keys.Where(k =>
+                    {
+                        var originalKey = k.ToString().Replace(_options.KeyPrefix, "");
+                        return predicate(originalKey);
+                    }).ToArray();
+
+                    if (keysToDelete.Length > 0)
+                    {
+                        count = (int)_connectionManager.GetDatabase().KeyDelete(keysToDelete);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis RemoveWhere澶辫触");
+                }
+            }
+
+            return count;
+        }
+
+        #endregion
+
+        #region 娣诲姞鍜屼慨鏀规墿灞曟柟娉�
+
+        public void AddAll(IDictionary<string, string> items, int expireSeconds = -1)
+        {
+            if (items == null) return;
+            foreach (var item in items)
+            {
+                Add(item.Key, item.Value, expireSeconds);
+            }
+        }
+
+        public void AddAllObjects(IDictionary<string, object> items, int expireSeconds = -1)
+        {
+            if (items == null) return;
+            foreach (var item in items)
+            {
+                AddObject(item.Key, item.Value, expireSeconds);
+            }
+        }
+
+        public bool Replace(string key, string newValue, int expireSeconds = -1)
+        {
+            return TryUpdate(key, newValue, expireSeconds);
+        }
+
+        public bool Replace<T>(string key, T newValue, int expireSeconds = -1) where T : class
+        {
+            if (!Exists(key)) return false;
+            AddObject(key, newValue, expireSeconds);
+            return true;
+        }
+
+        public string? GetAndRefresh(string key, int expireSeconds)
+        {
+            var fullKey = BuildKey(key);
+            string? value = null;
+
+            // 浠嶳edis鑾峰彇鍊�
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var redisValue = _connectionManager.GetDatabase().StringGet(fullKey);
+                    if (!redisValue.IsNullOrEmpty)
+                    {
+                        value = redisValue.ToString();
+                        // 鍒锋柊Redis杩囨湡鏃堕棿
+                        _connectionManager.GetDatabase().KeyExpire(fullKey, TimeSpan.FromSeconds(expireSeconds));
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis GetAndRefresh澶辫触, key={Key}", key);
+                }
+            }
+
+            // 濡傛灉Redis涓嶅彲鐢紝灏濊瘯浠庡唴瀛樼紦瀛樿幏鍙�
+            if (value == null && _options.EnableL1Cache)
+            {
+                if (_memoryCache.TryGetValue(fullKey, out string? cached))
+                    value = cached;
+            }
+
+            // 鏇存柊鍐呭瓨缂撳瓨锛堝鏋滄湁鍊硷級
+            if (value != null && _options.EnableL1Cache)
+            {
+                SetMemoryCache(fullKey, value, expireSeconds, false);
+            }
+
+            return value;
+        }
+
+        public T? GetAndRefresh<T>(string key, int expireSeconds) where T : class
+        {
+            var fullKey = BuildKey(key);
+            T? value = default;
+
+            // 浠嶳edis鑾峰彇鍊�
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var redisValue = _connectionManager.GetDatabase().StringGet(fullKey);
+                    if (!redisValue.IsNullOrEmpty)
+                    {
+                        var json = redisValue.ToString();
+                        value = _serializer.Deserialize<T>(json);
+                        // 鍒锋柊Redis杩囨湡鏃堕棿
+                        _connectionManager.GetDatabase().KeyExpire(fullKey, TimeSpan.FromSeconds(expireSeconds));
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis GetAndRefresh<T>澶辫触, key={Key}", key);
+                }
+            }
+
+            // 濡傛灉Redis涓嶅彲鐢紝灏濊瘯浠庡唴瀛樼紦瀛樿幏鍙�
+            if (value == null && _options.EnableL1Cache)
+            {
+                if (_memoryCache.TryGetValue(fullKey, out string? cached) && cached != null)
+                    value = _serializer.Deserialize<T>(cached);
+            }
+
+            // 鏇存柊鍐呭瓨缂撳瓨锛堝鏋滄湁鍊硷級
+            if (value != null && _options.EnableL1Cache)
+            {
+                SetMemoryCache(fullKey, _serializer.Serialize(value), expireSeconds, false);
+            }
+
+            return value;
+        }
+
+        public bool RefreshExpire(string key, int expireSeconds)
+        {
+            var fullKey = BuildKey(key);
+            bool result = false;
+
+            // 鍒锋柊Redis杩囨湡鏃堕棿
+            if (RedisAvailable)
+            {
+                try
+                {
+                    result = _connectionManager.GetDatabase().KeyExpire(fullKey, TimeSpan.FromSeconds(expireSeconds));
+                }
+                catch { }
+            }
+
+            // 鏇存柊鍐呭瓨缂撳瓨杩囨湡鏃堕棿锛堥渶瑕侀噸鏂拌缃�兼潵鍒锋柊杩囨湡鏃堕棿锛�
+            if (_options.EnableL1Cache && _memoryCache.TryGetValue(fullKey, out string? cached) && cached != null)
+            {
+                SetMemoryCache(fullKey, cached, expireSeconds, false);
+                return true;
+            }
+
+            return result;
+        }
+
+        public bool ExpireIn(string key, int seconds)
+        {
+            return RefreshExpire(key, seconds);
+        }
+
+        public bool ExpireAt(string key, DateTime expireTime)
+        {
+            var seconds = (long)(expireTime - DateTime.Now).TotalSeconds;
+            if (seconds <= 0) return Remove(key);
+            return RefreshExpire(key, (int)seconds);
+        }
+
+        public long? GetExpire(string key)
+        {
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var ttl = _connectionManager.GetDatabase().KeyTimeToLive(BuildKey(key));
+                    return ttl.HasValue ? (long)ttl.Value.TotalSeconds : null;
+                }
+                catch { }
+            }
+            return null; // MemoryCache涓嶆敮鎸乀TL鏌ヨ
+        }
+
+        public bool AddIfNotExists(string key, string value, int expireSeconds = -1)
+        {
+            return TryAdd(key, value, expireSeconds);
+        }
+
+        public bool AddIfNotExists<T>(string key, T value, int expireSeconds = -1) where T : class
+        {
+            return TryAdd(key, value, expireSeconds);
+        }
+
+        public string? GetAndSet(string key, string newValue, int expireSeconds = -1)
+        {
+            var fullKey = BuildKey(key);
+            string? oldValue = null;
+
+            // 浠嶳edis鑾峰彇鏃у��
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var value = _connectionManager.GetDatabase().StringGet(fullKey);
+                    oldValue = value.IsNullOrEmpty ? null : value.ToString();
+                }
+                catch { }
+            }
+
+            // 濡傛灉Redis涓嶅彲鐢紝浠庡唴瀛樼紦瀛樿幏鍙�
+            if (oldValue == null && _options.EnableL1Cache)
+            {
+                _memoryCache.TryGetValue(fullKey, out oldValue);
+            }
+
+            // 鍐欏叆Redis
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+                    _connectionManager.GetDatabase().StringSet(fullKey, newValue, expiry);
+                }
+                catch { }
+            }
+
+            // 鏇存柊鍐呭瓨缂撳瓨
+            if (_options.EnableL1Cache)
+            {
+                SetMemoryCache(fullKey, newValue, expireSeconds, false);
+            }
+
+            return oldValue;
+        }
+
+        public T? GetAndSet<T>(string key, T newValue, int expireSeconds = -1) where T : class
+        {
+            var fullKey = BuildKey(key);
+            T? oldValue = default;
+            string? oldJson = null;
+
+            // 浠嶳edis鑾峰彇鏃у��
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var value = _connectionManager.GetDatabase().StringGet(fullKey);
+                    if (!value.IsNullOrEmpty)
+                    {
+                        oldJson = value.ToString();
+                        oldValue = _serializer.Deserialize<T>(oldJson);
+                    }
+                }
+                catch { }
+            }
+
+            var newJson = _serializer.Serialize(newValue);
+
+            // 鍐欏叆Redis
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+                    _connectionManager.GetDatabase().StringSet(fullKey, newJson, expiry);
+                }
+                catch { }
+            }
+
+            // 鏇存柊鍐呭瓨缂撳瓨
+            if (_options.EnableL1Cache)
+            {
+                SetMemoryCache(fullKey, newJson, expireSeconds, false);
+            }
+
+            return oldValue;
+        }
+
+        public long Increment(string key, long value = 1)
+        {
+            if (RedisAvailable)
+            {
+                try
+                {
+                    return _connectionManager.GetDatabase().StringIncrement(BuildKey(key), value);
+                }
+                catch { }
+            }
+
+            // Fallback to memory
+            var current = long.TryParse(Get(key), out var v) ? v : 0;
+            var newValue = current + value;
+            Add(key, newValue.ToString());
+            return newValue;
+        }
+
+        public long Decrement(string key, long value = 1)
+        {
+            return Increment(key, -value);
+        }
+
+        public long Append(string key, string value)
+        {
+            var current = Get(key) ?? "";
+            var newValue = current + value;
+            Add(key, newValue);
+            return newValue.Length;
+        }
+
+        #endregion
+
         public T? Get<T>(string key) where T : class
         {
             var fullKey = BuildKey(key);
+
+            // 濡傛灉绂佺敤浜哃1缂撳瓨锛岀洿鎺ユ煡Redis
+            if (!_options.EnableL1Cache)
+            {
+                if (!RedisAvailable) return default;
+                try
+                {
+                    var value = _connectionManager.GetDatabase().StringGet(fullKey);
+                    if (value.IsNullOrEmpty) return default;
+                    return _serializer.Deserialize<T>(value!);
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis Get<T>澶辫触, key={Key}", key);
+                    return default;
+                }
+            }
+
+            // 姝e父鐨凩1+L2閫昏緫
             if (_memoryCache.TryGetValue(fullKey, out string? cached) && cached != null)
                 return _serializer.Deserialize<T>(cached);
 
@@ -131,9 +573,126 @@
             }
         }
 
+        /// <summary>
+        /// 瀹夊叏鏇存柊锛氫粎褰撳唴瀛樼紦瀛樹腑鐨勫�间笌expectedVersion鍖归厤鏃舵墠鏇存柊
+        /// 闃叉骞跺彂鍐欏叆鏃舵棫鍊艰鐩栨柊鍊�
+        /// </summary>
+        /// <typeparam name="T">鍊肩被鍨�</typeparam>
+        /// <param name="key">缂撳瓨閿�</param>
+        /// <param name="newValue">鏂板��</param>
+        /// <param name="expectedVersion">鏈熸湜鐨勭増鏈紙閫氬父鏄棫瀵硅薄鐨勫搱甯屽�兼垨鏃堕棿鎴筹級</param>
+        /// <param name="versionExtractor">浠庡璞℃彁鍙栫増鏈彿鐨勫嚱鏁�</param>
+        /// <param name="expireSeconds">杩囨湡鏃堕棿</param>
+        /// <returns>鏄惁鏇存柊鎴愬姛</returns>
+        public bool TrySafeUpdate<T>(
+            string key,
+            T newValue,
+            object? expectedVersion,
+            Func<T, object?> versionExtractor,
+            int expireSeconds = -1) where T : class
+        {
+            var fullKey = BuildKey(key);
+
+            // 浠嶳edis鑾峰彇褰撳墠鍊�
+            string? existingJson = null;
+            T? existingValue = default;
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var value = _connectionManager.GetDatabase().StringGet(fullKey);
+                    if (!value.IsNullOrEmpty)
+                    {
+                        existingJson = value.ToString();
+                        existingValue = _serializer.Deserialize<T>(existingJson);
+                    }
+                }
+                catch { }
+            }
+
+            // 濡傛灉Redis涓嶅彲鐢紝浠庡唴瀛樼紦瀛樿幏鍙�
+            if (existingValue == null && _options.EnableL1Cache)
+            {
+                if (_memoryCache.TryGetValue(fullKey, out string? cached) && cached != null)
+                {
+                    existingValue = _serializer.Deserialize<T>(cached);
+                    existingJson = cached;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+
+            // 妫�鏌ョ増鏈槸鍚﹀尮閰�
+            if (existingValue != null)
+            {
+                var currentVersion = versionExtractor(existingValue);
+                if (!Equals(currentVersion, expectedVersion))
+                {
+                    _logger.LogWarning("TrySafeUpdate鐗堟湰涓嶅尮閰�, key={Key}, expected={Expected}, current={Current}",
+                        key, expectedVersion, currentVersion);
+                    return false; // 鐗堟湰涓嶅尮閰嶏紝鎷掔粷鏇存柊
+                }
+            }
+
+            // 鐗堟湰鍖归厤锛屾墽琛屾洿鏂�
+            var newJson = _serializer.Serialize(newValue);
+
+            // 鍏堝啓鍏edis
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+                    if (!_connectionManager.GetDatabase().StringSet(fullKey, newJson, expiry))
+                    {
+                        _logger.LogWarning("Redis TrySafeUpdate鍐欏叆澶辫触, key={Key}", key);
+                        return _options.FallbackToMemory && _options.EnableL1Cache;
+                    }
+                    else
+                    {
+                        _logger.LogInformation("Redis TrySafeUpdate鍐欏叆鎴愬姛, key={Key}", key);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis TrySafeUpdate鍐欏叆澶辫触, key={Key}", key);
+                    return _options.FallbackToMemory && _options.EnableL1Cache;
+                }
+            }
+
+            // 鏇存柊鍐呭瓨缂撳瓨
+            if (_options.EnableL1Cache)
+            {
+                SetMemoryCache(fullKey, newJson, expireSeconds, false);
+            }
+
+            return true;
+        }
+
         public object? Get(Type type, string key)
         {
             var fullKey = BuildKey(key);
+
+            // 濡傛灉绂佺敤浜哃1缂撳瓨锛岀洿鎺ユ煡Redis
+            if (!_options.EnableL1Cache)
+            {
+                if (!RedisAvailable) return null;
+                try
+                {
+                    var value = _connectionManager.GetDatabase().StringGet(fullKey);
+                    if (value.IsNullOrEmpty) return null;
+                    return _serializer.Deserialize(value!, type);
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis Get(Type)澶辫触, key={Key}", key);
+                    return null;
+                }
+            }
+
+            // 姝e父鐨凩1+L2閫昏緫
             if (_memoryCache.TryGetValue(fullKey, out string? cached) && cached != null)
                 return _serializer.Deserialize(cached, type);
 
@@ -156,6 +715,24 @@
         public string? Get(string key)
         {
             var fullKey = BuildKey(key);
+
+            // 濡傛灉绂佺敤浜哃1缂撳瓨锛岀洿鎺ユ煡Redis
+            if (!_options.EnableL1Cache)
+            {
+                if (!RedisAvailable) return null;
+                try
+                {
+                    var value = _connectionManager.GetDatabase().StringGet(fullKey);
+                    return value.IsNullOrEmpty ? null : value.ToString();
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis Get澶辫触, key={Key}", key);
+                    return null;
+                }
+            }
+
+            // 姝e父鐨凩1+L2閫昏緫
             if (_memoryCache.TryGetValue(fullKey, out string? cached))
                 return cached;
 
@@ -229,6 +806,73 @@
             return true;
         }
 
+        public bool TryUpdateIfChanged(string key, string newValue, int expireSeconds = -1)
+        {
+            var existing = Get(key);
+            if (existing == null) return false;
+            if (existing == newValue) return false; // 鍊肩浉鍚岋紝涓嶆洿鏂�
+            Add(key, newValue, expireSeconds);
+            return true;
+        }
+
+        public bool TryUpdateIfChanged<T>(string key, T newValue, int expireSeconds = -1) where T : class
+        {
+            var fullKey = BuildKey(key);
+
+            // 鎬绘槸浠嶳edis鑾峰彇褰撳墠瀹為檯鍊艰繘琛屾瘮杈冿紝纭繚鏁版嵁涓�鑷存��
+            string? existingJson = null;
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var value = _connectionManager.GetDatabase().StringGet(fullKey);
+                    if (!value.IsNullOrEmpty)
+                        existingJson = value.ToString();
+                }
+                catch { }
+            }
+
+            if (existingJson == null)
+            {
+                // Redis涓嶅彲鐢紝妫�鏌ュ唴瀛樼紦瀛�
+                if (_options.EnableL1Cache && _memoryCache.TryGetValue(fullKey, out string? cached) && cached != null)
+                    existingJson = cached;
+                else
+                    return false;
+            }
+
+            var newJson = _serializer.Serialize(newValue);
+            if (existingJson == newJson) return false; // JSON瀛楃涓茬浉鍚岋紝涓嶆洿鏂�
+
+            // 鍏堝啓鍏edis锛屾垚鍔熷悗鍐嶆洿鏂板唴瀛樼紦瀛�
+            if (RedisAvailable)
+            {
+                try
+                {
+                    var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+                    if (!_connectionManager.GetDatabase().StringSet(fullKey, newJson, expiry))
+                    {
+                        // Redis鍐欏叆澶辫触
+                        _logger.LogWarning("Redis TryUpdateIfChanged鍐欏叆澶辫触, key={Key}", key);
+                        return _options.FallbackToMemory && _options.EnableL1Cache;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogWarning(ex, "Redis TryUpdateIfChanged鍐欏叆澶辫触, key={Key}", key);
+                    return _options.FallbackToMemory && _options.EnableL1Cache;
+                }
+            }
+
+            // Redis鍐欏叆鎴愬姛锛堟垨Redis涓嶅彲鐢ㄦ椂锛夛紝鏇存柊鍐呭瓨缂撳瓨
+            if (_options.EnableL1Cache)
+            {
+                SetMemoryCache(fullKey, newJson, expireSeconds, false);
+            }
+
+            return true;
+        }
+
         public string GetOrAdd(string key, string value, int expireSeconds = -1)
         {
             var existing = Get(key);

--
Gitblit v1.9.3