From 17e5dbd7bd0364e27a33f1a7dab91cf33d5dcabc Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期三, 04 三月 2026 11:52:12 +0800
Subject: [PATCH] 增强Redis缓存服务与设备通信优化

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/RedisCacheService.cs |  226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 226 insertions(+), 0 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/RedisCacheService.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/RedisCacheService.cs
index fe19c5f..f52aa42 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/RedisCacheService.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_RedisService/Cache/RedisCacheService.cs
@@ -70,6 +70,209 @@
             Db.KeyDelete(redisKeys);
         }
 
+        #region 鍒犻櫎鎵╁睍鏂规硶
+
+        public string? RemoveAndGet(string key)
+        {
+            var fullKey = BuildKey(key);
+            var value = Db.StringGet(fullKey);
+            if (!value.IsNullOrEmpty)
+            {
+                Db.KeyDelete(fullKey);
+                return value.ToString();
+            }
+            return null;
+        }
+
+        public T? RemoveAndGet<T>(string key) where T : class
+        {
+            var fullKey = BuildKey(key);
+            var value = Db.StringGet(fullKey);
+            if (!value.IsNullOrEmpty)
+            {
+                Db.KeyDelete(fullKey);
+                return _serializer.Deserialize<T>(value!);
+            }
+            return default;
+        }
+
+        public int RemoveByPrefix(string prefix)
+        {
+            var fullPrefix = BuildKey(prefix);
+            var server = Db.Multiplexer.GetServer(Db.Multiplexer.GetEndPoints().First());
+            var keys = server.Keys(pattern: $"{fullPrefix}*").ToArray();
+            if (keys.Length == 0) return 0;
+            return (int)Db.KeyDelete(keys);
+        }
+
+        public int RemoveByPattern(string pattern)
+        {
+            var fullPattern = BuildKey(pattern).Replace("*", ""); // 淇濈暀鐢ㄦ埛浼犲叆鐨勯�氶厤绗�
+            var server = Db.Multiplexer.GetServer(Db.Multiplexer.GetEndPoints().First());
+            var keys = server.Keys(pattern: $"{_options.KeyPrefix}{pattern}").ToArray();
+            if (keys.Length == 0) return 0;
+            return (int)Db.KeyDelete(keys);
+        }
+
+        public int RemoveAll(IEnumerable<string> keys)
+        {
+            if (keys == null) return 0;
+            var redisKeys = keys.Select(k => (RedisKey)BuildKey(k)).ToArray();
+            return (int)Db.KeyDelete(redisKeys);
+        }
+
+        public int RemoveWhere(Func<string, bool> predicate)
+        {
+            if (predicate == null) return 0;
+            var server = Db.Multiplexer.GetServer(Db.Multiplexer.GetEndPoints().First());
+            var keys = server.Keys(pattern: $"{_options.KeyPrefix}*")
+                .Where(k => predicate(k.ToString().Replace(_options.KeyPrefix, "")))
+                .ToArray();
+            if (keys.Length == 0) return 0;
+            return (int)Db.KeyDelete(keys);
+        }
+
+        #endregion
+
+        #region 娣诲姞鍜屼慨鏀规墿灞曟柟娉�
+
+        public void AddAll(IDictionary<string, string> items, int expireSeconds = -1)
+        {
+            if (items == null) return;
+            var batch = Db.CreateBatch();
+            var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+            foreach (var item in items)
+            {
+                batch.StringSetAsync(BuildKey(item.Key), item.Value, expiry);
+            }
+            batch.Execute();
+        }
+
+        public void AddAllObjects(IDictionary<string, object> items, int expireSeconds = -1)
+        {
+            if (items == null) return;
+            var batch = Db.CreateBatch();
+            var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+            foreach (var item in items)
+            {
+                batch.StringSetAsync(BuildKey(item.Key), _serializer.Serialize(item.Value), expiry);
+            }
+            batch.Execute();
+        }
+
+        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
+        {
+            var fullKey = BuildKey(key);
+            if (!Db.KeyExists(fullKey)) return false;
+            var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+            return Db.StringSet(fullKey, _serializer.Serialize(newValue), expiry, When.Exists);
+        }
+
+        public string? GetAndRefresh(string key, int expireSeconds)
+        {
+            var fullKey = BuildKey(key);
+            var value = Db.StringGet(fullKey);
+            if (!value.IsNullOrEmpty)
+            {
+                Db.KeyExpire(fullKey, TimeSpan.FromSeconds(expireSeconds));
+                return value.ToString();
+            }
+            return null;
+        }
+
+        public T? GetAndRefresh<T>(string key, int expireSeconds) where T : class
+        {
+            var fullKey = BuildKey(key);
+            var value = Db.StringGet(fullKey);
+            if (!value.IsNullOrEmpty)
+            {
+                Db.KeyExpire(fullKey, TimeSpan.FromSeconds(expireSeconds));
+                return _serializer.Deserialize<T>(value!);
+            }
+            return default;
+        }
+
+        public bool RefreshExpire(string key, int expireSeconds)
+        {
+            return Db.KeyExpire(BuildKey(key), TimeSpan.FromSeconds(expireSeconds));
+        }
+
+        public bool ExpireIn(string key, int seconds)
+        {
+            return Db.KeyExpire(BuildKey(key), TimeSpan.FromSeconds(seconds));
+        }
+
+        public bool ExpireAt(string key, DateTime expireTime)
+        {
+            return Db.KeyExpire(BuildKey(key), expireTime);
+        }
+
+        public long? GetExpire(string key)
+        {
+            var ttl = Db.KeyTimeToLive(BuildKey(key));
+            return ttl.HasValue ? (long)ttl.Value.TotalSeconds : null;
+        }
+
+        public bool AddIfNotExists(string key, string value, int expireSeconds = -1)
+        {
+            var fullKey = BuildKey(key);
+            var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+            return Db.StringSet(fullKey, value, expiry, When.NotExists);
+        }
+
+        public bool AddIfNotExists<T>(string key, T value, int expireSeconds = -1) where T : class
+        {
+            var fullKey = BuildKey(key);
+            var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+            return Db.StringSet(fullKey, _serializer.Serialize(value), expiry, When.NotExists);
+        }
+
+        public string? GetAndSet(string key, string newValue, int expireSeconds = -1)
+        {
+            var fullKey = BuildKey(key);
+            var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+            var oldValue = Db.StringGetSet(fullKey, newValue);
+            if (expireSeconds > 0)
+            {
+                Db.KeyExpire(fullKey, expiry);
+            }
+            return oldValue.IsNullOrEmpty ? null : oldValue.ToString();
+        }
+
+        public T? GetAndSet<T>(string key, T newValue, int expireSeconds = -1) where T : class
+        {
+            var fullKey = BuildKey(key);
+            var serialized = _serializer.Serialize(newValue);
+            var oldValue = Db.StringGetSet(fullKey, serialized);
+            if (expireSeconds > 0)
+            {
+                Db.KeyExpire(fullKey, TimeSpan.FromSeconds(expireSeconds));
+            }
+            return oldValue.IsNullOrEmpty ? default : _serializer.Deserialize<T>(oldValue!);
+        }
+
+        public long Increment(string key, long value = 1)
+        {
+            return Db.StringIncrement(BuildKey(key), value);
+        }
+
+        public long Decrement(string key, long value = 1)
+        {
+            return Db.StringDecrement(BuildKey(key), value);
+        }
+
+        public long Append(string key, string value)
+        {
+            return Db.StringAppend(BuildKey(key), value);
+        }
+
+        #endregion
+
         public T? Get<T>(string key) where T : class
         {
             var value = Db.StringGet(BuildKey(key));
@@ -139,6 +342,29 @@
             return Db.StringSet(fullKey, newValue, expiry, When.Exists);
         }
 
+        public bool TryUpdateIfChanged(string key, string newValue, int expireSeconds = -1)
+        {
+            var fullKey = BuildKey(key);
+            var existing = Db.StringGet(fullKey);
+            if (existing.IsNullOrEmpty) return false;
+            if (existing.ToString() == newValue) return false; // 鍊肩浉鍚岋紝涓嶆洿鏂�
+            var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+            return Db.StringSet(fullKey, newValue, expiry, When.Exists);
+        }
+
+        public bool TryUpdateIfChanged<T>(string key, T newValue, int expireSeconds = -1) where T : class
+        {
+            var fullKey = BuildKey(key);
+            var existing = Db.StringGet(fullKey);
+            if (existing.IsNullOrEmpty) return false;
+
+            var newJson = _serializer.Serialize(newValue);
+            if (existing.ToString() == newJson) return false; // JSON瀛楃涓茬浉鍚岋紝涓嶆洿鏂�
+
+            var expiry = expireSeconds > 0 ? TimeSpan.FromSeconds(expireSeconds) : (TimeSpan?)null;
+            return Db.StringSet(fullKey, newJson, expiry, When.Exists);
+        }
+
         public string GetOrAdd(string key, string value, int expireSeconds = -1)
         {
             var fullKey = BuildKey(key);

--
Gitblit v1.9.3