First of all, nuget:

  1. ServiceStack.Redis
  2. ServiceStack.Common
  3. ServiceStack.interfaces
  4. ServiceStack.Text

The basic version

public sealed class RedisConfigInfo
    {
        /// <summary>
        ///Writable Redis link address
        /// format:ip1,ip2
        /// 
        ///The default port is 6379
        /// </summary>
        public string WriteServerList = "127.0.0.1:6379";
        /// <summary>
        ///Readable Redis link address
        /// format:ip1,ip2
        /// </summary>
        public string ReadServerList = "127.0.0.1:6379";
        /// <summary>
        ///Maximum number of uppercase links
        /// </summary>
        public int MaxWritePoolSize = 60;
        /// <summary>
        ///Maximum number of read links
        /// </summary>
        public int MaxReadPoolSize = 60;
        /// <summary>
        ///Local cache expiration time, in seconds
        /// </summary>
        public int LocalCacheTime = 180;
        /// <summary>
        ///Automatic restart
        /// </summary>
        public bool AutoStart = true;
        /// <summary>
        ///Log or not. This setting is only used to troubleshoot problems that occur when Redis is running.
        ///If Redis works properly, close this item
        /// </summary>
        public bool RecordeLog = false;
    }
Copy the code
/// <summary>
    ///Redis Management Center
    /// </summary>
    public class RedisManager
    {
        /// <summary>
        ///Redis configuration file information
        /// </summary>
        private static RedisConfigInfo RedisConfigInfo = new RedisConfigInfo();

        /// <summary>
        ///Redis client pool management
        /// </summary>
        private static PooledRedisClientManager prcManager;

        /// <summary>
        ///Static constructor that initializes a link pool managed object
        /// </summary>
        static RedisManager()
        {
            CreateManager();
        }

        /// <summary>
        ///Example Create a link pool managed object
        /// </summary>
        private static void CreateManager()
        {
            string[] WriteServerConStr = RedisConfigInfo.WriteServerList.Split(', ');
            string[] ReadServerConStr = RedisConfigInfo.ReadServerList.Split(', ');
            prcManager = new PooledRedisClientManager(ReadServerConStr, WriteServerConStr,
                             new RedisClientManagerConfig
                             {
                                 MaxWritePoolSize = RedisConfigInfo.MaxWritePoolSize,
                                 MaxReadPoolSize = RedisConfigInfo.MaxReadPoolSize,
                                 AutoStart = RedisConfigInfo.AutoStart,
                             });
        }

        /// <summary>
        ///The client caches the operation object
        /// </summary>
        public static IRedisClient GetClient()
        {
            returnprcManager.GetClient(); }}Copy the code
 /// <summary>
    ///The RedisBase class, which is the base of redis operations, inherits from the IDisposable interface and is mainly used to free memory
    /// </summary>
    public abstract class RedisBase : IDisposable
    {
        public IRedisClient iClient { get; private set; }
        /// <summary>
        ///Construction completes the opening of the link
        /// </summary>
        public RedisBase()
        {
            iClient = RedisManager.GetClient();
        }

        //public static IRedisClient iClient { get; private set; }
        //static RedisBase()
        / / {
        // iClient = RedisManager.GetClient();
        / /}


        private bool _disposed = false;
        protected virtual void Dispose(bool disposing)
        {
            if (!this._disposed)
            {
                if (disposing)
                {
                    iClient.Dispose();
                    iClient = null; }}this._disposed = true;
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public void Transcation()
        {
            using (IRedisTransaction irt = this.iClient.CreateTransaction())
            {
                try
                {
                    irt.QueueCommand(r => r.Set("key".20));
                    irt.QueueCommand(r => r.Increment("key".1));
                    irt.Commit(); // Commit the transaction
                }
                catch (Exception ex)
                {
                    irt.Rollback();
                    throwex; }}}/// <summary>
        ///Be careful to erase all data
        /// </summary>
        public virtual void FlushAll()
        {
            iClient.FlushAll();
        }

        /// <summary>
        ///Save data DB files to hard disk
        /// </summary>
        public void Save()
        {
            iClient.Save();// block save
        }

        /// <summary>
        ///Asynchronously saves DB files to hard disks
        /// </summary>
        public void SaveAsync()
        {
            iClient.SaveAsync();/ / asynchronous save}}Copy the code

Service layer: Five data structures

public class RedisHashService : RedisBase
    {
        #regionadd
        /// <summary>
        ///Add a key/value to the Hashid collection
        /// </summary>       
        public bool SetEntryInHash(string hashid, string key, string value)
        {
            return base.iClient.SetEntryInHash(hashid, key, value);
        }
        /// <summary>
        ///If a key/value is present in the hashid collection, return false without adding it,
        ///Return true if no key/value is being added
        /// </summary>
        public bool SetEntryInHashIfNotExists(string hashid, string key, string value)
        {
            return base.iClient.SetEntryInHashIfNotExists(hashid, key, value);
        }
        /// <summary>
        ///Store objects T T into the Hash set
        ///You need to include the Id and get it with the Id
        /// </summary>
        public void StoreAsHash<T> (T t)
        {
            base.iClient.StoreAsHash<T>(t);
        }
        #endregion

        #regionTo obtain
        /// <summary>
        ///Get data with ID in object T.
        /// </summary>
        public T GetFromHash<T> (object id)
        {
            return base.iClient.GetFromHash<T>(id);
        }
        /// <summary>
        ///Get the key/value data set for all hashid data sets
        /// </summary>
        public Dictionary<string.string> GetAllEntriesFromHash(string hashid)
        {
            return base.iClient.GetAllEntriesFromHash(hashid);
        }
        /// <summary>
        ///Gets the total number of data in the Hashid dataset
        /// </summary>
        public long GetHashCount(string hashid)
        {
            return base.iClient.GetHashCount(hashid);
        }
        /// <summary>
        ///Gets a collection of all keys in the Hashid dataset
        /// </summary>
        public List<string> GetHashKeys(string hashid)
        {
            return base.iClient.GetHashKeys(hashid);
        }
        /// <summary>
        ///Get all value collections in the Hashid dataset
        /// </summary>
        public List<string> GetHashValues(string hashid)
        {
            return base.iClient.GetHashValues(hashid);
        }
        /// <summary>
        ///Get the value of the key in the Hashid dataset
        /// </summary>
        public string GetValueFromHash(string hashid, string key)
        {
            return base.iClient.GetValueFromHash(hashid, key);
        }
        /// <summary>
        ///Get the value set of keys in the hashid dataset
        /// </summary>
        public List<string> GetValuesFromHash(string hashid, string[] keys)
        {
            return base.iClient.GetValuesFromHash(hashid, keys);
        }
        #endregion

        #regiondelete
        /// <summary>
        ///Delete key data from the hashid dataset
        /// </summary>
        public bool RemoveEntryFromHash(string hashid, string key)
        {
            return base.iClient.RemoveEntryFromHash(hashid, key);
        }
        #endregion

        #regionother
        /// <summary>
        ///Check whether key data exists in the hashid dataset
        /// </summary>
        public bool HashContainsEntry(string hashid, string key)
        {
            return base.iClient.HashContainsEntry(hashid, key);
        }
        /// <summary>
        ///Add countby to the value of the hashid dataset key and return the sum
        /// </summary>
        public double IncrementValueInHash(string hashid, string key, double countBy)
        {
            return base.iClient.IncrementValueInHash(hashid, key, countBy);
        }
        #endregion
    }
Copy the code
 public class RedisListService : RedisBase
    {
        #regionThe assignment
        /// <summary>
        ///Add values to the list from the left
        /// </summary>
        public void LPush(string key, string value)
        {
            base.iClient.PushItemToList(key, value);
        }
        /// <summary>
        ///Add values to the list from the left and set the expiration time
        /// </summary>
        public void LPush(string key, string value, DateTime dt)
        {

            base.iClient.PushItemToList(key, value);
            base.iClient.ExpireEntryAt(key, dt);
        }
        /// <summary>
        ///Add values from the left side to the list to set the expiration time
        /// </summary>
        public void LPush(string key, string value, TimeSpan sp)
        {
            base.iClient.PushItemToList(key, value);
            base.iClient.ExpireEntryIn(key, sp);
        }
        /// <summary>
        ///Add values to the list from the right
        /// </summary>
        public void RPush(string key, string value)
        {
            base.iClient.PrependItemToList(key, value);
        }
        /// <summary>
        ///Add a value to the list from the right and set the expiration time
        /// </summary>    
        public void RPush(string key, string value, DateTime dt)
        {
            base.iClient.PrependItemToList(key, value);
            base.iClient.ExpireEntryAt(key, dt);
        }
        /// <summary>
        ///Add a value to the list from the right and set the expiration time
        /// </summary>        
        public void RPush(string key, string value, TimeSpan sp)
        {
            base.iClient.PrependItemToList(key, value);
            base.iClient.ExpireEntryIn(key, sp);
        }
        /// <summary>
        ///Add a key/value
        /// </summary>     
        public void Add(string key, string value)
        {
            base.iClient.AddItemToList(key, value);
        }
        /// <summary>
        ///Add key/value and set the expiration time
        /// </summary>  
        public void Add(string key, string value, DateTime dt)
        {
            base.iClient.AddItemToList(key, value);
            base.iClient.ExpireEntryAt(key, dt);
        }
        /// <summary>
        ///Add a key/value. And add an expiration time
        /// </summary>  
        public void Add(string key, string value, TimeSpan sp)
        {
            base.iClient.AddItemToList(key, value);
            base.iClient.ExpireEntryIn(key, sp);
        }
        /// <summary>
        ///Add multiple values for key
        /// </summary>  
        public void Add(string key, List<string> values)
        {
            base.iClient.AddRangeToList(key, values);
        }
        /// <summary>
        ///Add multiple values for key and set an expiration time
        /// </summary>  
        public void Add(string key, List<string> values, DateTime dt)
        {
            base.iClient.AddRangeToList(key, values);
            base.iClient.ExpireEntryAt(key, dt);
        }
        /// <summary>
        ///Add multiple values for key and set an expiration time
        /// </summary>  
        public void Add(string key, List<string> values, TimeSpan sp)
        {
            base.iClient.AddRangeToList(key, values);
            base.iClient.ExpireEntryIn(key, sp);
        }
        #endregion

        #regionGet the value
        /// <summary>
        ///Gets the amount of data that the key in the list contains
        /// </summary>  
        public long Count(string key)
        {
            return base.iClient.GetListCount(key);
        }
        /// <summary>
        ///Gets all the data sets that the key contains
        /// </summary>  
        public List<string> Get(string key)
        {
            return base.iClient.GetAllItemsFromList(key);
        }
        /// <summary>
        ///Gets the set of values from key with subscripts star through end
        /// </summary>  
        public List<string> Get(string key, int star, int end)
        {
            return base.iClient.GetRangeFromList(key, star, end);
        }
        #endregion

        #regionBlocking the command
        /// <summary>
        ///Block command: removes a value from the end of list as key and returns the removed value, blocking time sp
        /// </summary>  
        public string BlockingPopItemFromList(string key, TimeSpan? sp)
        {
            return base.iClient.BlockingPopItemFromList(key, sp);
        }
        /// <summary>
        ///Block command: removes a value at the end of a list and returns the removed value &key with block time sp
        /// </summary>  
        public ItemRef BlockingPopItemFromLists(string[] keys, TimeSpan? sp)
        {
            return base.iClient.BlockingPopItemFromLists(keys, sp);
        }


        /// <summary>
        ///Block command: Removes a value from the end of keys in the list and returns the removed value, blocking for sp
        /// </summary>  
        public string BlockingDequeueItemFromList(string key, TimeSpan? sp)
        {
            return base.iClient.BlockingDequeueItemFromList(key, sp);
        }

        /// <summary>
        ///Block command: removes a value at the end of a list and returns the removed value &key with block time sp
        /// </summary>  
        public ItemRef BlockingDequeueItemFromLists(string[] keys, TimeSpan? sp)
        {
            return base.iClient.BlockingDequeueItemFromLists(keys, sp);
        }

        /// <summary>
        ///Block command: removes a fromkey from the end of a list, adds it to the head of another tokey, and returns the removed value, blocking for sp
        /// </summary>  
        public string BlockingPopAndPushItemBetweenLists(string fromkey, string tokey, TimeSpan? sp)
        {
            return base.iClient.BlockingPopAndPushItemBetweenLists(fromkey, tokey, sp);
        }
        #endregion

        #regiondelete
        /// <summary>
        ///Removes data from tail and returns removed data
        /// </summary>  
        public string PopItemFromList(string key)
        {
            var sa = base.iClient.CreateSubscription();
            return base.iClient.PopItemFromList(key);
        }
        /// <summary>
        ///Removes data from tail and returns removed data
        /// </summary>  
        public string DequeueItemFromList(string key)
        {
            return base.iClient.DequeueItemFromList(key);
        }

        /// <summary>
        ///Removes the key/value from the list and returns the number of values removed
        /// </summary>  
        public long RemoveItemFromList(string key, string value)
        {
            return base.iClient.RemoveItemFromList(key, value);
        }
        /// <summary>
        ///Removes data from the end of the list and returns the removed data
        /// </summary>  
        public string RemoveEndFromList(string key)
        {
            return base.iClient.RemoveEndFromList(key);
        }
        /// <summary>
        ///Removes a datum from the head of a list and returns the removed value
        /// </summary>  
        public string RemoveStartFromList(string key)
        {
            return base.iClient.RemoveStartFromList(key);
        }
        #endregion

        #regionother
        /// <summary>
        ///Remove data from the end of one list, add it to the head of another list, and return the moved value
        /// </summary>  
        public string PopAndPushItemBetweenLists(string fromKey, string toKey)
        {
            return base.iClient.PopAndPushItemBetweenLists(fromKey, toKey);
        }
        #endregion

        #regionRelease subscription
        public void Publish(string channel, string message)
        {
            base.iClient.PublishMessage(channel, message);
        }

        public void Subscribe(string channel, Action<string.string, IRedisSubscription> actionOnMessage)
        {
            var subscription = base.iClient.CreateSubscription();
            subscription.OnSubscribe = c =>
            {
                Console.WriteLine($" Subscribe channel{c}");
                Console.WriteLine();
            };
            // Unsubscribe
            subscription.OnUnSubscribe = c =>
            {
                Console.WriteLine($" Unsubscribe{c}");
                Console.WriteLine();
            };
            subscription.OnMessage += (c, s) =>
            {
                actionOnMessage(c, s, subscription);
            };
            Console.WriteLine($" Starts listening{channel}");
            subscription.SubscribeToChannels(channel); //blocking
        }

        public void UnSubscribeFromChannels(string channel)
        {
            var subscription = base.iClient.CreateSubscription();
            subscription.UnSubscribeFromChannels(channel);
        }
        #endregion
    }
Copy the code
public class RedisSetService : RedisBase
    {
        #regionadd
        /// <summary>
        ///Add a value to the key collection
        /// </summary>
        public void Add(string key, string value)
        {
            base.iClient.AddItemToSet(key, value);
        }
        /// <summary>
        ///Add the list collection to the key collection
        /// </summary>
        public void Add(string key, List<string> list)
        {
            base.iClient.AddRangeToSet(key, list);

        }
        #endregion

        #regionTo obtain
        /// <summary>
        ///Gets a random value from the key collection
        /// </summary>
        public string GetRandomItemFromSet(string key)
        {
            return base.iClient.GetRandomItemFromSet(key);
        }
        /// <summary>
        ///Gets the number of key set values
        /// </summary>
        public long GetCount(string key)
        {
            return base.iClient.GetSetCount(key);
        }
        /// <summary>
        ///Gets the values of all key sets
        /// </summary>
        public HashSet<string> GetAllItemsFromSet(string key)
        {
            return base.iClient.GetAllItemsFromSet(key);
        }
        #endregion

        #regiondelete
        /// <summary>
        ///Randomly remove a value from the key set
        /// </summary>
        public string RandomRemoveItemFromSet(string key)
        {
            return base.iClient.PopItemFromSet(key);
        }
        /// <summary>
        ///Delete the value from the key set
        /// </summary>
        public void RemoveItemFromSet(string key, string value)
        {
            base.iClient.RemoveItemFromSet(key, value);
        }
        #endregion

        #regionother
        /// <summary>
        ///Removes value from fromKey collection and adds value to tokey collection
        /// </summary>
        public void MoveBetweenSets(string fromkey, string tokey, string value)
        {
            base.iClient.MoveBetweenSets(fromkey, tokey, value);
        }
        /// <summary>
        ///Return keys union of multiple collections, return hashSet
        /// </summary>
        public HashSet<string> GetUnionFromSets(params string[] keys)
        {
            return base.iClient.GetUnionFromSets(keys);
        }
        /// <summary>
        ///Returns the intersection of keys collections, returning the hashSet
        /// </summary>
        public HashSet<string> GetIntersectFromSets(params string[] keys)
        {
            return base.iClient.GetIntersectFromSets(keys);
        }
        /// <summary>
        ///Returns the difference set in keys multiple collections, returning the hashSet
        /// </summary>
        /// <param name="fromKey">The original set</param>
        /// <param name="keys">Other collections</param>
        /// <returns>Appears in the original collection, but is not included in other collections</returns>
        public HashSet<string> GetDifferencesFromSet(string fromKey, params string[] keys)
        {
            return base.iClient.GetDifferencesFromSet(fromKey,keys);
        }
        /// <summary>
        ///Keys The union of multiple sets into the newkey set
        /// </summary>
        public void StoreUnionFromSets(string newkey, string[] keys)
        {
            base.iClient.StoreUnionFromSets(newkey, keys);
        }
        /// <summary>
        ///Compare the fromKey set to the keys set. If the fromKey set does not exist in the keys set, put the non-existing data into the Newkey set
        /// </summary>
        public void StoreDifferencesFromSet(string newkey, string fromkey, string[] keys)
        {
            base.iClient.StoreDifferencesFromSet(newkey, fromkey, keys);
        }
        #endregion
    }
Copy the code
 public class RedisStringService : RedisBase
    {
        #regionThe assignment
        /// <summary>
        ///Set the value of the key
        /// </summary>
        public bool Set<T> (string key, T value)
        {
            return base.iClient.Set<T>(key, value);
        }
        /// <summary>
        ///Set the value of the key and the expiration time
        /// </summary>
        public bool Set<T> (string key, T value, DateTime dt)
        {
            return base.iClient.Set<T>(key, value, dt);
        }
        /// <summary>
        ///Set the value of the key and the expiration time
        /// </summary>
        public bool Set<T> (string key, T value, TimeSpan sp)
        {
            return base.iClient.Set<T>(key, value, sp);
        }
        /// <summary>
        ///Set multiple keys and values
        /// </summary>
        public void Set(Dictionary<string.string> dic)
        {
            base.iClient.SetAll(dic);
        }

        #endregion

        #regionadditional
        /// <summary>
        ///Append the value of the key after the value of the original key
        /// </summary>
        public long Append(string key, string value)
        {
            return base.iClient.AppendToValue(key, value);
        }
        #endregion

        #regionGet the value
        /// <summary>
        ///Get the value of the key
        /// </summary>
        public string Get(string key)
        {
            return base.iClient.GetValue(key);
        }
        /// <summary>
        ///Gets the value of multiple keys
        /// </summary>
        public List<string> Get(List<string> keys)
        {
            return base.iClient.GetValues(keys);
        }
        /// <summary>
        ///Gets the value of multiple keys
        /// </summary>
        public List<T> Get<T> (List<string> keys)
        {
            return base.iClient.GetValues<T>(keys);
        }
        #endregion

        #regionGet the old value and assign the new value
        /// <summary>
        ///Get the old value and assign the new value
        /// </summary>
        public string GetAndSetValue(string key, string value)
        {
            return base.iClient.GetAndSetValue(key, value);
        }
        #endregion

        #regionHelper method
        /// <summary>
        ///Gets the length of the value
        /// </summary>
        public long GetLength(string key)
        {
            return base.iClient.GetStringCount(key);
        }
        /// <summary>
        ///Increment by 1, returns the increment value
        /// </summary>
        public long Incr(string key)
        {
            return base.iClient.IncrementValue(key);
        }
        /// <summary>
        ///Increment count returns the increment value
        /// </summary>
        public long IncrBy(string key, int count)
        {
            return base.iClient.IncrementValueBy(key, count);
        }
        /// <summary>
        ///Decrement by 1, returns the value after decrement
        /// </summary>
        public long Decr(string key)
        {
            return base.iClient.DecrementValue(key);
        }
        /// <summary>
        ///Decrement count, returns the decrement value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public long DecrBy(string key, int count)
        {
            return base.iClient.DecrementValueBy(key, count);
        }
        #endregion
    }
Copy the code
public class RedisZSetService : RedisBase
    {
        #regionadd
        /// <summary>
        ///Add key/value. The default score is incremented from 1. *10 ^ 9
        /// </summary>
        public bool Add(string key, string value)
        {
            return base.iClient.AddItemToSortedSet(key, value);
        }
        /// <summary>
        ///Add key/value and set the value score
        /// </summary>
        public bool AddItemToSortedSet(string key, string value.double score)
        {
            return base.iClient.AddItemToSortedSet(key, value, score);
        }
        /// <summary>
        ///Add a set of values for the key, and set the score for each value in the set to score
        /// </summary>
        public bool AddRangeToSortedSet(string key, List<string> values, double score)
        {
            return base.iClient.AddRangeToSortedSet(key, values, score);
        }
        /// <summary>
        ///Add a set of values for the key, and set the score for each value in the set to score
        /// </summary>
        public bool AddRangeToSortedSet(string key, List<string> values, long score)
        {
            return base.iClient.AddRangeToSortedSet(key, values, score);
        }
        #endregion

        #regionTo obtain
        /// <summary>
        ///Gets all collections of keys
        /// </summary>
        public List<string> GetAll(string key)
        {
            return base.iClient.GetAllItemsFromSortedSet(key);
        }
        /// <summary>
        ///Get all sets of keys, output backwards
        /// </summary>
        public List<string> GetAllDesc(string key)
        {
            return base.iClient.GetAllItemsFromSortedSetDesc(key);
        }
        /// <summary>
        ///Get set, mixed number
        /// </summary>
        public IDictionary<string.double> GetAllWithScoresFromSortedSet(string key)
        {
            return base.iClient.GetAllWithScoresFromSortedSet(key);
        }
        /// <summary>
        ///Gets the subscript value of key as value
        /// </summary>
        public long GetItemIndexInSortedSet(string key, string value)
        {
            return base.iClient.GetItemIndexInSortedSet(key, value);
        }
        /// <summary>
        ///Retrieves the subscript value of key as value in reverse order
        /// </summary>
        public long GetItemIndexInSortedSetDesc(string key, string value)
        {
            return base.iClient.GetItemIndexInSortedSetDesc(key, value);
        }
        /// <summary>
        ///Get the score whose key is value
        /// </summary>
        public double GetItemScoreInSortedSet(string key, string value)
        {
            return base.iClient.GetItemScoreInSortedSet(key, value);
        }
        /// <summary>
        ///Gets the total number of data for all collections of key
        /// </summary>
        public long GetSortedSetCount(string key)
        {
            return base.iClient.GetSortedSetCount(key);
        }
        /// <summary>
        ///Key sets the total number of data fromscore fromscore toscore toscore
        /// </summary>
        public long GetSortedSetCount(string key, double fromScore, double toScore)
        {
            return base.iClient.GetSortedSetCount(key, fromScore, toScore);
        }
        /// <summary>
        ///Get key set from high score to low score sort data, score from fromscore toscore for toscore data
        /// </summary>
        public List<string> GetRangeFromSortedSetByHighestScore(string key, double fromscore, double toscore)
        {
            return base.iClient.GetRangeFromSortedSetByHighestScore(key, fromscore, toscore);
        }
        /// <summary>
        ///Get key set from low score to high score sorted data, score from fromscore toscore for toscore data
        /// </summary>
        public List<string> GetRangeFromSortedSetByLowestScore(string key, double fromscore, double toscore)
        {
            return base.iClient.GetRangeFromSortedSetByLowestScore(key, fromscore, toscore);
        }
        /// <summary>
        ///Get key set from high score to low score sort data, score from fromscore toscore for toscore data, mixed score
        /// </summary>
        public IDictionary<string.double> GetRangeWithScoresFromSortedSetByHighestScore(string key, double fromscore, double toscore)
        {
            return base.iClient.GetRangeWithScoresFromSortedSetByHighestScore(key, fromscore, toscore);
        }
        /// <summary>
        ///Get key set from low score to high score sorting data, score from fromscore toscore for toscore data, mixed score
        /// </summary>
        public IDictionary<string.double> GetRangeWithScoresFromSortedSetByLowestScore(string key, double fromscore, double toscore)
        {
            return base.iClient.GetRangeWithScoresFromSortedSetByLowestScore(key, fromscore, toscore);
        }
        /// <summary>
        ///Get key set data, subscript fromRank to data with a score of toRank
        /// </summary>
        public List<string> GetRangeFromSortedSet(string key, int fromRank, int toRank)
        {
            return base.iClient.GetRangeFromSortedSet(key, fromRank, toRank);
        }
        /// <summary>
        ///Get the key set in reverse order data, subscript fromRank to the score of toRank data
        /// </summary>
        public List<string> GetRangeFromSortedSetDesc(string key, int fromRank, int toRank)
        {
            return base.iClient.GetRangeFromSortedSetDesc(key, fromRank, toRank);
        }
        /// <summary>
        ///Get key set data, subscript from fromRank to toRank data, mixed score
        /// </summary>
        public IDictionary<string.double> GetRangeWithScoresFromSortedSet(string key, int fromRank, int toRank)
        {
            return base.iClient.GetRangeWithScoresFromSortedSet(key, fromRank, toRank);
        }
        /// <summary>
        ///Get key set in reverse order data, subscript from fromRank to the score of toRank data, mixed score
        /// </summary>
        public IDictionary<string.double> GetRangeWithScoresFromSortedSetDesc(string key, int fromRank, int toRank)
        {
            return base.iClient.GetRangeWithScoresFromSortedSetDesc(key, fromRank, toRank);
        }
        #endregion

        #regiondelete
        /// <summary>
        ///Delete the data whose key is value
        /// </summary>
        public bool RemoveItemFromSortedSet(string key, string value)
        {
            return base.iClient.RemoveItemFromSortedSet(key, value);
        }
        /// <summary>
        ///Delete key set index from minRank to maxRank
        /// </summary>
        public long RemoveRangeFromSortedSet(string key, int minRank, int maxRank)
        {
            return base.iClient.RemoveRangeFromSortedSet(key, minRank, maxRank);
        }
        /// <summary>
        ///Delete key set data from fromScore to toscore
        /// </summary>
        public long RemoveRangeFromSortedSetByScore(string key, double fromscore, double toscore)
        {
            return base.iClient.RemoveRangeFromSortedSetByScore(key, fromscore, toscore);
        }
        /// <summary>
        ///Delete the data with the highest score from the key set
        /// </summary>
        public string PopItemWithHighestScoreFromSortedSet(string key)
        {
            return base.iClient.PopItemWithHighestScoreFromSortedSet(key);
        }
        /// <summary>
        ///Delete the data with the smallest score from the key set
        /// </summary>
        public string PopItemWithLowestScoreFromSortedSet(string key)
        {
            return base.iClient.PopItemWithLowestScoreFromSortedSet(key);
        }
        #endregion

        #regionother
        /// <summary>
        ///Check whether value data exists in the key set
        /// </summary>
        public bool SortedSetContainsItem(string key, string value)
        {
            return base.iClient.SortedSetContainsItem(key, value);
        }
        /// <summary>
        ///Is the key set value of the data, score plus scoreby, return the sum of the score
        /// </summary>
        public double IncrementItemInSortedSet(string key, string value.double scoreBy)
        {
            return base.iClient.IncrementItemInSortedSet(key, value, scoreBy);
        }
        /// <summary>
        ///Get the intersection of multiple sets of keys, and add the intersection to the newKey set, return the total number of intersection data
        /// </summary>
        public long StoreIntersectFromSortedSets(string newkey, string[] keys)
        {
            return base.iClient.StoreIntersectFromSortedSets(newkey, keys);
        }
        /// <summary>
        ///Gets the union of multiple sets of keys and adds the union data to the newkey collection, returning the total number of union data
        /// </summary>
        public long StoreUnionFromSortedSets(string newkey, string[] keys)
        {
            return base.iClient.StoreUnionFromSortedSets(newkey, keys);
        }
        #endregion
    }
Copy the code

Extended edition

/// <summary>
    ///Redis basic information initializes helper classes
    /// </summary>
    internal class RedisManager
    {
        //private static LogHelper log = LogHelper.LogInterface<RedisManager>();
        private static readonly object Locker = new object(a);private static ConnectionMultiplexer _instance;
        private static readonly ConcurrentDictionary<string.ConnectionMultiplexer> ConnectionCache = new ConcurrentDictionary<string, ConnectionMultiplexer>();
        /// <summary>
        ///The Key prefix saved by Redis is automatically added to the specified Key name
        /// </summary>
        internal static readonly string RedisSysCustomKey = ConfigurationManager.AppSettings["RedisSysCustomKey"];
        /// <summary>
        ///The DataBase index in the currently connected Redis, 0-16 by default, can be configured in service.conf, up to 64
        /// </summary>
        internal static readonly int RedisDataBaseIndex = int.Parse(ConfigurationManager.AppSettings["RedisDataBaseIndex"]);
        /// <summary>
        ///Redis connection string, the current connection format for: 127.0.0.1:6379, allowadmin = true, passowrd = PWD
        /// </summary>
        internal static readonly string RedisHostConnection = ConfigurationManager.AppSettings["RedisHostConnection"];

        /// <summary>
        ///Singleton access
        /// </summary>
        public static ConnectionMultiplexer Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (Locker)
                    {
                        if (_instance == null| |! _instance.IsConnected) { _instance = GetManager(); }}}return_instance; }}/// <summary>
        ///Cache access
        /// </summary>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        public static ConnectionMultiplexer GetConnectionMultiplexer(string connectionString)
        {
            if(! ConnectionCache.ContainsKey(connectionString)) { ConnectionCache[connectionString] = GetManager(connectionString); }return ConnectionCache[connectionString];
        }

        /// <summary>
        ///Internal method to get the Redis connection
        /// </summary>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        private static ConnectionMultiplexer GetManager(string connectionString = null)
        {
            connectionString = connectionString ?? RedisHostConnection;
            var connect = ConnectionMultiplexer.Connect(connectionString);

            // Register the following events
            connect.ConnectionFailed += MuxerConnectionFailed;
            connect.ConnectionRestored += MuxerConnectionRestored;
            connect.ErrorMessage += MuxerErrorMessage;
            connect.ConfigurationChanged += MuxerConfigurationChanged;
            connect.HashSlotMoved += MuxerHashSlotMoved;
            connect.InternalError += MuxerInternalError;

            return connect;
        }

        #regionThe event

        /// <summary>
        ///When configuration changes
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
        {
            //log.InfoAsync($"Configuration changed: {e.EndPoint}");
        }

        /// <summary>
        ///When an error occurs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
        {
            //log.InfoAsync($"ErrorMessage: {e.Message}");
        }

        /// <summary>
        ///Error before reestablishing connection
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
        {
            //log.InfoAsync($"ConnectionRestored: {e.EndPoint}");
        }

        /// <summary>
        ///Connection failed, you will not receive this notification if reconnection succeeds
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            // log.infoAsync ($" Reconnect: Endpoint failed: {e.edpoint}, {e.ailureType}, {(e.e.eption == null? "" : e.Exception.Message)}");
        }

        /// <summary>
        ///Changes to the cluster
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
        {
            //log.InfoAsync($"HashSlotMoved:NewEndPoint{e.NewEndPoint}, OldEndPoint{e.OldEndPoint}");
        }

        /// <summary>
        ///Redis class library error
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
        {
            //log.InfoAsync($"InternalError:Message{ e.Exception.Message}");
        }

        #endregionThe event
    }
Copy the code
/// <summary>
    ///Redis operation method base class
    /// </summary>
    public abstract class RedisBase : IDisposable
    {

        #regionProperty field
        /// <summary>
        ///The Redis system defines the Key prefix
        /// </summary>
        protected string CustomKey = RedisManager.RedisSysCustomKey;
        /// <summary>
        ///Site Redis link string
        /// </summary>
        protected readonly ConnectionMultiplexer _conn;
        /// <summary>
        ///Redis operates on objects
        /// </summary>
        protected readonly IDatabase redis = null;
        #endregion

        #regionThe constructor
        /// <summary>
        ///Initializes the Redis operation method base class
        /// </summary>
        /// <param name="dbNum">Database indexes for the operation 0-64(need to be configured in conf file)</param>
        protected RedisBase(int? dbNum = null)
        {
            _conn = RedisManager.Instance;
            if(_conn ! =null)
            {
                redis = _conn.GetDatabase(dbNum ?? RedisManager.RedisDataBaseIndex);
            }
            else
            {
                throw new ArgumentNullException("Redis connection initialization failed"); }}private bool _disposed = false;
        protected virtual void Dispose(bool disposing)
        {
            if (!this._disposed)
            {
                if(disposing) { _conn.Dispose(); }}this._disposed = true;
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregionThe constructor

        #regionExternal calls to static methods
        /// <summary>
        ///Gets the String data type operation helper method class of Redis
        /// </summary>
        /// <returns></returns>
        public static RedisStringService StringService => new RedisStringService();
        /// <summary>
        ///Gets the Redis Hash data type operation helper method class
        /// </summary>
        /// <returns></returns>
        public static RedisHashService HashService => new RedisHashService();
        /// <summary>
        ///Get the List data type operation helper method class of Redis
        /// </summary>
        /// <returns></returns>
        public static RedisListService ListService => new RedisListService();
        /// <summary>
        ///Gets Redis' Set unordered collection data type operation helper method class
        /// </summary>
        /// <returns></returns>
        public static RedisSetService SetService => new RedisSetService();
        /// <summary>
        ///Get Redis SortedSet(ZSet) ordered set data type operation helper method class
        /// </summary>
        /// <returns></returns>
        public static RedisSortedSetService SortedSetService => new RedisSortedSetService();

        #endregion

        #regionCommon operation method

        #regionIt is not recommended to expose these methods, or to comment or delete them if they are not used in the project
        /// <summary>
        ///Get the Redis transaction object
        /// </summary>
        /// <returns></returns>
        public ITransaction CreateTransaction() => redis.CreateTransaction();

        /// <summary>
        ///Get the Redis service and common operation objects
        /// </summary>
        /// <returns></returns>
        public IDatabase GetDatabase() => redis;

        /// <summary>
        ///Get the Redis service
        /// </summary>
        /// <param name="hostAndPort"></param>
        /// <returns></returns>
        public IServer GetServer(string hostAndPort) => _conn.GetServer(hostAndPort);

        /// <summary>
        ///Perform Redis transactions
        /// </summary>
        /// <param name="act"></param>
        /// <returns></returns>
        public bool RedisTransaction(Action<ITransaction> act)
        {
            var tran = redis.CreateTransaction();
            act.Invoke(tran);
            bool committed = tran.Execute();
            return committed;
        }
        /// <summary>
        ///Redis lock
        /// </summary>
        /// <param name="act"></param>
        /// <param name="ts">Lock the time</param>
        public void RedisLockTake(Action act, TimeSpan ts)
        {
            RedisValue token = Environment.MachineName;
            string lockKey = "lock_LockTake";
            if (redis.LockTake(lockKey, token, ts))
            {
                try
                {
                    act();
                }
                finally{ redis.LockRelease(lockKey, token); }}}#endregionother

        #regionCommon Key Operations
        /// <summary>
        ///Set the prefix
        /// </summary>
        /// <param name="customKey"></param>
        public void SetSysCustomKey(string customKey) => CustomKey = customKey;

        /// <summary>
        ///Name of the composite cache Key
        /// </summary>
        /// <param name="oldKey"></param>
        /// <returns></returns>
        public string AddSysCustomKey(string oldKey)= >$"{CustomKey}_{oldKey}";

        #regionSynchronized methods

        /// <summary>
        ///Deleting a Single Key
        /// </summary>
        /// <param name="key">The key to delete</param>
        /// <returns>Check whether the deletion is successful.</returns>
        public bool KeyDelete(string key)
        {
            key = AddSysCustomKey(key);
            return redis.KeyDelete(key);
        }

        /// <summary>
        ///Delete multiple Keys
        /// </summary>
        /// <param name="keys">The set of keys to delete</param>
        /// <returns>Number of successful deletes</returns>
        public long KeyDelete(params string[] keys)
        {
            RedisKey[] newKeys = keys.Select(o => (RedisKey)AddSysCustomKey(o)).ToArray();
            return redis.KeyDelete(newKeys);
        }

        /// <summary>
        ///Clear all keys in the current DataBase
        /// </summary>
        public void KeyFulsh()
        {
            // Run the clear command
            redis.Execute("FLUSHDB");
        }

        /// <summary>
        ///Check whether the key exists
        /// </summary>
        /// <param name="key">The key to judge</param>
        /// <returns></returns>
        public bool KeyExists(string key)
        {
            key = AddSysCustomKey(key);
            return redis.KeyExists(key);
        }

        /// <summary>
        ///Rename key
        /// </summary>
        /// <param name="key">The redis key</param>
        /// <param name="newKey">New redis key</param>
        /// <returns></returns>
        public bool KeyRename(string key, string newKey)
        {
            key = AddSysCustomKey(key);
            newKey = AddSysCustomKey(newKey);
            return redis.KeyRename(key, newKey);
        }

        /// <summary>
        ///Set the expiration time of the Key
        /// </summary>
        /// <param name="key">redis key</param>
        /// <param name="expiry">Expiration time</param>
        /// <returns></returns>
        public bool KeyExpire(string key, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            return redis.KeyExpire(key, expiry);
        }


        #endregion

        #regionAsynchronous methods

        /// <summary>
        ///Deleting a Single Key
        /// </summary>
        /// <param name="key">The key to delete</param>
        /// <returns>Check whether the deletion is successful.</returns>
        public async Task<bool> KeyDeleteAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await redis.KeyDeleteAsync(key);
        }

        /// <summary>
        ///Delete multiple Keys
        /// </summary>
        /// <param name="keys">The set of keys to delete</param>
        /// <returns>Number of successful deletes</returns>
        public async Task<long> KeyDeleteAsync(params string[] keys)
        {
            RedisKey[] newKeys = keys.Select(o => (RedisKey)AddSysCustomKey(o)).ToArray();
            return await redis.KeyDeleteAsync(newKeys);
        }

        /// <summary>
        ///Clear all keys in the current DataBase
        /// </summary>
        public async Task KeyFulshAsync()
        {
            // Run the clear command
            await redis.ExecuteAsync("FLUSHDB");
        }

        /// <summary>
        ///Check whether the key exists
        /// </summary>
        /// <param name="key">The key to judge</param>
        /// <returns></returns>
        public async Task<bool> KeyExistsAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await redis.KeyExistsAsync(key);
        }

        /// <summary>
        ///Rename key
        /// </summary>
        /// <param name="key">The redis key</param>
        /// <param name="newKey">New redis key</param>
        /// <returns></returns>
        public async Task<bool> KeyRenameAsync(string key, string newKey)
        {
            key = AddSysCustomKey(key);
            newKey = AddSysCustomKey(newKey);
            return await redis.KeyRenameAsync(key, newKey);
        }

        /// <summary>
        ///Set the expiration time of the Key
        /// </summary>
        /// <param name="key">redis key</param>
        /// <param name="expiry">Expiration time</param>
        /// <returns></returns>
        public async Task<bool> KeyExpireAsync(string key, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            return await redis.KeyExpireAsync(key, expiry);
        }
        #endregion

        #endregion 

        #endregion

        #regionHelper method

        /// <summary>
        ///Convert an object to a string
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        protected string ConvertJson<T> (T value)
        {
            string result = value is string ? value.ToString() :
                JsonConvert.SerializeObject(value, Formatting.None);
            return result;
        }
        /// <summary>
        ///Invert values into objects
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        protected T ConvertObj<T> (RedisValue value)
        {
            return value.IsNullOrEmpty ? default(T) : JsonConvert.DeserializeObject<T>(value);
        }

        /// <summary>
        ///Invert values into collections of objects
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="values"></param>
        /// <returns></returns>
        protected List<T> ConvetList<T> (RedisValue[] values)
        {
            List<T> result = new List<T>();
            foreach (var item in values)
            {
                var model = ConvertObj<T>(item);
                result.Add(model);
            }
            return result;
        }
        /// <summary>
        ///Convert a Key of type string to<see cref="RedisKey"/>The Key of
        /// </summary>
        /// <param name="redisKeys"></param>
        /// <returns></returns>
        protected RedisKey[] ConvertRedisKeys(List<string> redisKeys) => redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray();

        /// <summary>
        ///Convert a Key of type string to<see cref="RedisKey"/>The Key of
        /// </summary>
        /// <param name="redisKeys"></param>
        /// <returns></returns>
        protected RedisKey[] ConvertRedisKeys(params string[] redisKeys) => redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray();

        /// <summary>
        ///Convert a Key of type string to<see cref="RedisKey"/>Type Key and prefixes the string
        /// </summary>
        /// <param name="redisKeys"></param>
        /// <returns></returns>
        protected RedisKey[] ConvertRedisKeysAddSysCustomKey(params string[] redisKeys) => redisKeys.Select(redisKey => (RedisKey)AddSysCustomKey(redisKey)).ToArray();
        /// <summary>
        ///Convert a collection of values to a Collection of Redisvalues
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisValues"></param>
        /// <returns></returns>
        protected RedisValue[] ConvertRedisValue<T> (params T[] redisValues) => redisValues.Select(o => (RedisValue)ConvertJson<T>(o)).ToArray();
        #endregionHelper method

    }
Copy the code

Service layer: Five data structures

/// <summary>
    ///Hash: similar to a dictionary, it uses an index to locate a specified element quickly and takes equal time. Unlike string, it directly modifies a field without deserializing it
    ///String is either 001: serialize the entire entity
    ///Either 001_name: 001_PWd: multiple key-values
    ///Hash, a hashid-{key:value; key:value; key:value; }
    ///Entities can be found at once, individually, or modified individually
    /// </summary>
    public class RedisHashService : RedisBase
    {

        #regionThe constructor

        /// <summary>
        ///Initializes the Redis Hash data structure operation
        /// </summary>
        /// <param name="dbNum">Database indexes for the operation 0-64(need to be configured in conf file)</param>
        public RedisHashService(int? dbNum = null) :
            base(dbNum){}#endregion

        #regionSynchronized methods

        /// <summary>
        ///Determines whether data has been cached
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        public bool HashExists(string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            return base.redis.HashExists(key, dataKey);
        }

        /// <summary>
        ///Stores data to the hash table
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public bool HashSet<T> (string key, string dataKey, T t)
        {
            key = AddSysCustomKey(key);
            string json = ConvertJson(t);
            return base.redis.HashSet(key, dataKey, json);
        }

        /// <summary>
        ///Removes a value from the hash
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        public bool HashDelete(string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            return base.redis.HashDelete(key, dataKey);
        }

        /// <summary>
        ///Removes multiple values from the hash
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKeys"></param>
        /// <returns></returns>
        public long HashDelete(string key, params string[] dataKeys)
        {
            key = AddSysCustomKey(key);
            var newValues = dataKeys.Select(o => (RedisValue)o).ToArray();
            return base.redis.HashDelete(key, newValues);
        }

        /// <summary>
        ///Get data from the hash table
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        public T HashGet<T> (string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            string value = base.redis.HashGet(key, dataKey);
            return ConvertObj<T>(value);
        }

        /// <summary>
        ///Increment val returns the increment value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <param name="val">You can have a negative</param>
        /// <returns>The value of the increment</returns>
        public double HashIncrement(string key, string dataKey, double val = 1)
        {
            key = AddSysCustomKey(key);
            return base.redis.HashIncrement(key, dataKey, val);
        }

        /// <summary>
        ///The numeric decrement val returns the self-decrement value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <param name="val">You can have a negative</param>
        /// <returns>The reduced value</returns>
        public double HashDecrement(string key, string dataKey, double val = 1)
        {
            key = AddSysCustomKey(key);
            return base.redis.HashDecrement(key, dataKey, val);
        }

        /// <summary>
        ///Get all key names of the hashkey
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string[] HashKeys(string key)
        {
            key = AddSysCustomKey(key);
            RedisValue[] values = base.redis.HashKeys(key);
            return values.Select(o=>o.ToString()).ToArray();
        }

        /// <summary>
        ///Obtain all keys and values in the hashkey. Ensure that all data types in the key are consistent
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public Dictionary<string.T> HashGetAll<T> (string key)
        {
            key = AddSysCustomKey(key);
            var query = base.redis.HashGetAll(key);
            Dictionary<string, T> dic = new Dictionary<string, T>();
            foreach (var item in query)
            {
                dic.Add(item.Name, ConvertObj<T>(item.Value));
            }
            return dic;
        }

        #endregionSynchronized methods

        #regionAsynchronous methods

        /// <summary>
        ///The asynchronous method determines whether the data has been cached
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        public async Task<bool> HashExistsAsync(string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            return await base.redis.HashExistsAsync(key, dataKey);
        }

        /// <summary>
        ///Asynchronous methods store data to hash tables
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task<bool> HashSetAsync<T> (string key, string dataKey, T t)
        {
            key = AddSysCustomKey(key);
            string json = ConvertJson(t);
            return await base.redis.HashSetAsync(key, dataKey, json);
        }

        /// <summary>
        ///The asynchronous method removes a value from the hash
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        public async Task<bool> HashDeleteAsync(string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            return await base.redis.HashDeleteAsync(key, dataKey);
        }

        /// <summary>
        ///Asynchronous methods remove multiple values from the hash
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKeys"></param>
        /// <returns></returns>
        public async Task<long> HashDeleteAsync(string key, params string[] dataKeys)
        {
            key = AddSysCustomKey(key);
            var newValues = dataKeys.Select(o => (RedisValue)o).ToArray();
            return await base.redis.HashDeleteAsync(key, newValues);
        }

        /// <summary>
        ///Asynchronous methods get data from the hash table
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <returns></returns>
        public async Task<T> HashGetAsync<T> (string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            string value = await base.redis.HashGetAsync(key, dataKey);
            return ConvertObj<T>(value);
        }

        /// <summary>
        ///The asynchronous method increments val numerically and returns the incremented value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <param name="val">You can have a negative</param>
        /// <returns>The value of the increment</returns>
        public async Task<double> HashIncrementAsync(string key, string dataKey, double val = 1)
        {
            key = AddSysCustomKey(key);
            return await base.redis.HashIncrementAsync(key, dataKey, val);
        }

        /// <summary>
        ///The asynchronous method decrement val, which returns a self-decrement value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dataKey"></param>
        /// <param name="val">You can have a negative</param>
        /// <returns>The reduced value</returns>
        public async Task<double> HashDecrementAsync(string key, string dataKey, double val = 1)
        {
            key = AddSysCustomKey(key);
            return await base.redis.HashDecrementAsync(key, dataKey, val);
        }

        /// <summary>
        ///The asynchronous method gets all the key names of the hashkey
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<string[]> HashKeysAsync(string key)
        {
            key = AddSysCustomKey(key);
            RedisValue[] values = await base.redis.HashKeysAsync(key);
            return values.Select(o => o.ToString()).ToArray();
        }

        /// <summary>
        ///Obtain all keys and values in the hashkey. Ensure that all data types in the key are consistent
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<Dictionary<string.T>> HashGetAllAsync<T> (string key)
        {
            key = AddSysCustomKey(key);
            var query = await base.redis.HashGetAllAsync(key);
            Dictionary<string, T> dic = new Dictionary<string, T>();
            foreach (var item in query)
            {
                dic.Add(item.Name, ConvertObj<T>(item.Value));
            }
            return dic;
        }

        #endregionAsynchronous methods

    }
Copy the code
/// <summary>
    ///The implementation of Redis List is a bidirectional linked list, that is, it can support reverse lookup and traversal, which is more convenient to operate, but it brings some extra memory overhead.
    ///Many implementations inside Redis, including sending buffer queues, also use this data structure.
    ///Usually left in and right out or right in and left out
    /// </summary>
    public class RedisListService : RedisBase
    {
        #regionThe constructor

        /// <summary>
        ///Initialize the Redis List data structure operation
        /// </summary>
        /// <param name="dbNum">Database indexes for the operation 0-64(need to be configured in conf file)</param>
        public RedisListService(int? dbNum = null) :
            base(dbNum){}#endregion

        #regionSynchronized methods
        /// <summary>
        ///Returns the total number of collections by adding a value to the list from the left
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public long ListLeftPush<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return base.redis.ListLeftPush(key, jValue);
        }

        /// <summary>
        ///Return the total number of collections by adding multiple values to the list from the left
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public long ListLeftPush<T> (string key, List<T> value)
        {
            key = AddSysCustomKey(key);
            RedisValue[] valueList = base.ConvertRedisValue(value.ToArray());
            return base.redis.ListLeftPush(key, valueList);
        }

        /// <summary>
        ///Returns the total number of collections by adding a value to the list from the right
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public long ListRightPush<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return base.redis.ListRightPush(key, jValue);
        }

        /// <summary>
        ///Add multiple values to the list from the right to return the total number of collections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public long ListRightPush<T> (string key, List<T> value)
        {
            key = AddSysCustomKey(key);
            RedisValue[] valueList = base.ConvertRedisValue(value.ToArray());
            return base.redis.ListRightPush(key, valueList);
        }

        /// <summary>
        ///Takes a value from the left side into the list and deletes it from the list
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T ListLeftPop<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = base.redis.ListLeftPop(key);
            return base.ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Removes a value from the list from the right
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T ListRightPop<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = base.redis.ListRightPop(key);
            return base.ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Retrieves a value from the List of keys on the right and adds it to the Destination collection from the left, and returns the data object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">The name of the List to retrieve data from</param>
        /// <param name="destination">The name of the List to add to</param>
        /// <returns></returns>
        public T ListRightPopLeftPush<T> (string key, string destination)
        {
            key = AddSysCustomKey(key);
            destination = AddSysCustomKey(destination);
            var rValue = base.redis.ListRightPopLeftPush(key, destination);
            return base.ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Return the total number of collections by inserting value after key's List specified value pivot
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pivot">The index value</param>
        /// <param name="value">The value to insert</param>
        /// <returns></returns>
        public long ListInsertAfter<T> (string key, T pivot, T value)
        {
            key = AddSysCustomKey(key);
            string pValue = ConvertJson(pivot);
            string jValue = ConvertJson(value);
            return base.redis.ListInsertAfter(key, pValue, jValue);
        }

        /// <summary>
        ///Return the total number of collections by inserting value before key's List specified value pivot
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pivot">The index value</param>
        /// <param name="value">The value to insert</param>
        /// <returns></returns>
        public long ListInsertBefore<T> (string key, T pivot, T value)
        {
            key = AddSysCustomKey(key);
            string pValue = ConvertJson(pivot);
            string jValue = ConvertJson(value);
            return base.redis.ListInsertBefore(key, pValue, jValue);
        }

        /// <summary>
        ///Fetch all data from key's list
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public List<T> ListRange<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = base.redis.ListRange(key);
            return base.ConvetList<T>(rValue);
        }

        /// <summary>
        ///Gets the value of the specified index from the key's List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public T ListGetByIndex<T> (string key, long index)
        {
            key = AddSysCustomKey(key);
            var rValue = base.redis.ListGetByIndex(key, index);
            return base.ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Get the number of keys in the list
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long ListLength(string key)
        {
            key = AddSysCustomKey(key);
            return base.redis.ListLength(key);
        }

        /// <summary>
        ///Removes the specified value from the List of keys. Returns the number of deletions
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public long ListRemove<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return base.redis.ListRemove(key, jValue);
        }
        #endregion

        #regionAsynchronous methods
        /// <summary>
        ///Returns the total number of collections by adding a value to the list from the left
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<long> ListLeftPushAsync<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return await base.redis.ListLeftPushAsync(key, jValue);
        }

        /// <summary>
        ///Return the total number of collections by adding multiple values to the list from the left
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<long> ListLeftPushAsync<T> (string key, List<T> value)
        {
            key = AddSysCustomKey(key);
            RedisValue[] valueList = base.ConvertRedisValue(value.ToArray());
            return await base.redis.ListLeftPushAsync(key, valueList);
        }

        /// <summary>
        ///Returns the total number of collections by adding a value to the list from the right
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<long> ListRightPushAsync<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return await base.redis.ListRightPushAsync(key, jValue);
        }

        /// <summary>
        ///Add multiple values to the list from the right to return the total number of collections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<long> ListRightPushAsync<T> (string key, List<T> value)
        {
            key = AddSysCustomKey(key);
            RedisValue[] valueList = base.ConvertRedisValue(value.ToArray());
            return await base.redis.ListRightPushAsync(key, valueList);
        }

        /// <summary>
        ///Takes a value from the left side into the list and deletes it from the list
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<T> ListLeftPopAsync<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = await base.redis.ListLeftPopAsync(key);
            return base.ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Removes a value from the list from the right
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<T> ListRightPopAsync<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = await base.redis.ListRightPopAsync(key);
            return base.ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Retrieves a value from the List of keys on the right and adds it to the Destination collection from the left, and returns the data object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">The name of the List to retrieve data from</param>
        /// <param name="destination">The name of the List to add to</param>
        /// <returns></returns>
        public async Task<T> ListRightPopLeftPushAsync<T> (string key, string destination)
        {
            key = AddSysCustomKey(key);
            destination = AddSysCustomKey(destination);
            var rValue = await base.redis.ListRightPopLeftPushAsync(key, destination);
            return base.ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Return the total number of collections by inserting value after key's List specified value pivot
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pivot">The index value</param>
        /// <param name="value">The value to insert</param>
        /// <returns></returns>
        public async Task<long> ListInsertAfterAsync<T> (string key, T pivot, T value)
        {
            key = AddSysCustomKey(key);
            string pValue = ConvertJson(pivot);
            string jValue = ConvertJson(value);
            return await  base.redis.ListInsertAfterAsync(key, pValue, jValue);
        }

        /// <summary>
        ///Return the total number of collections by inserting value before key's List specified value pivot
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pivot">The index value</param>
        /// <param name="value">The value to insert</param>
        /// <returns></returns>
        public async Task<long> ListInsertBeforeAsync<T> (string key, T pivot, T value)
        {
            key = AddSysCustomKey(key);
            string pValue = ConvertJson(pivot);
            string jValue = ConvertJson(value);
            return await  base.redis.ListInsertBeforeAsync(key, pValue, jValue);
        }

        /// <summary>
        ///Fetch all data from key's list
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<List<T>> ListRangeAsync<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = await base.redis.ListRangeAsync(key);
            return base.ConvetList<T>(rValue);
        }

        /// <summary>
        ///Gets the value of the specified index from the key's List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public async Task<T> ListGetByIndexAsync<T> (string key, long index)
        {
            key = AddSysCustomKey(key);
            var rValue = await base.redis.ListGetByIndexAsync(key, index);
            return base.ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Get the number of keys in the list
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<long> ListLengthAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await base.redis.ListLengthAsync(key);
        }

        /// <summary>
        ///Removes the specified value from the List of keys. Returns the number of deletions
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<long> ListRemoveAsync<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return await base.redis.ListRemoveAsync(key, jValue);
        }
        #endregion
    }
Copy the code
/// <summary>
    ///Set: A hash table used to keep strings unique, out of order, and store aggregated data
    ///1. Mutual friend, second friend
    ///2. Using uniqueness, you can count all the independent IP addresses that visit the website
    /// </summary>
    public class RedisSetService : RedisBase
    {
        #regionThe constructor

        /// <summary>
        ///Initialize Redis' Set unordered data structure operation
        /// </summary>
        /// <param name="dbNum">Database indexes for the operation 0-64(need to be configured in conf file)</param>
        public RedisSetService(int? dbNum = null) :
            base(dbNum){}#endregion

        #regionSynchronized methods
        /// <summary>
        ///Add a value to the Key collection
        /// </summary>
        /// <typeparam name="T">The data type</typeparam>
        /// <param name="key">The Key name</param>
        /// <param name="value">value</param>
        /// <returns></returns>
        public bool SetAdd<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return base.redis.SetAdd(key, jValue);
        }
        /// <summary>
        ///Add multiple values to the Key collection
        /// </summary>
        /// <typeparam name="T">The data type</typeparam>
        /// <param name="key">The Key name</param>
        /// <param name="value">List of values</param>
        /// <returns></returns>
        public long SetAdd<T> (string key, List<T> value)
        {
            key = AddSysCustomKey(key);
            RedisValue[] valueList = base.ConvertRedisValue(value.ToArray());
            return base.redis.SetAdd(key, valueList);
        }

        /// <summary>
        ///Gets the number of key set values
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long SetLength(string key)
        {
            key = AddSysCustomKey(key);
            return base.redis.SetLength(key);
        }

        /// <summary>
        ///Checks whether the Key collection contains the specified value
        /// </summary>
        /// <typeparam name="T">Value types</typeparam>
        /// <param name="key"></param>
        /// <param name="value">You have to determine the value</param>
        /// <returns></returns>
        public bool SetContains<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return base.redis.SetContains(key, jValue);
        }

        /// <summary>
        ///Gets a random value from the key collection
        /// </summary>
        /// <typeparam name="T">The data type</typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T SetRandomMember<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = base.redis.SetRandomMember(key);
            return ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Gets the collection of all key values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public List<T> SetMembers<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = base.redis.SetMembers(key);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Deletes the value specified in the key set
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public long SetRemove<T> (string key, params T[] value)
        {
            key = AddSysCustomKey(key);
            RedisValue[] valueList = base.ConvertRedisValue(value);
            return base.redis.SetRemove(key, valueList);
        }

        /// <summary>
        ///Randomly removes a value from the key collection and returns that value
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T SetPop<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = base.redis.SetPop(key);
            return ConvertObj<T>(rValue);
        }


        /// <summary>
        ///Gets the union of several collections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public List<T> SetCombineUnion<T> (params string[] keys)
        {
            return _SetCombine<T>(SetOperation.Union, keys);
        }
        /// <summary>
        ///Gets the intersection of several collections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public List<T> SetCombineIntersect<T> (params string[] keys)
        {
            return _SetCombine<T>(SetOperation.Intersect, keys);
        }
        /// <summary>
        ///Gets the difference set of several sets
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public List<T> SetCombineDifference<T> (params string[] keys)
        {
            return _SetCombine<T>(SetOperation.Difference, keys);
        }

        /// <summary>
        ///Gets the union of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public long SetCombineUnionAndStore(string destination, params string[] keys)
        {
            return _SetCombineAndStore(SetOperation.Union, destination, keys);
        }
        /// <summary>
        ///Gets the intersection of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public long SetCombineIntersectAndStore(string destination, params string[] keys)
        {
            return _SetCombineAndStore(SetOperation.Intersect, destination, keys);
        }
        /// <summary>
        ///Gets the difference set of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public long SetCombineDifferenceAndStore(string destination, params string[] keys)
        {
            return _SetCombineAndStore(SetOperation.Difference, destination, keys);
        }
        #endregion

        #regionAsynchronous methods
        /// <summary>
        ///Add a value to the Key collection
        /// </summary>
        /// <typeparam name="T">The data type</typeparam>
        /// <param name="key">The Key name</param>
        /// <param name="value">value</param>
        /// <returns></returns>
        public async Task<bool> SetAddAsync<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return await base.redis.SetAddAsync(key, jValue);
        }
        /// <summary>
        ///Add multiple values to the Key collection
        /// </summary>
        /// <typeparam name="T">The data type</typeparam>
        /// <param name="key">The Key name</param>
        /// <param name="value">List of values</param>
        /// <returns></returns>
        public async Task<long> SetAddAsync<T> (string key, List<T> value)
        {
            key = AddSysCustomKey(key);
            RedisValue[] valueList = base.ConvertRedisValue(value.ToArray());
            return await base.redis.SetAddAsync(key, valueList);
        }

        /// <summary>
        ///Gets the number of key set values
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<long> SetLengthAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await base.redis.SetLengthAsync(key);
        }

        /// <summary>
        ///Checks whether the Key collection contains the specified value
        /// </summary>
        /// <typeparam name="T">Value types</typeparam>
        /// <param name="key"></param>
        /// <param name="value">You have to determine the value</param>
        /// <returns></returns>
        public async Task<bool> SetContainsAsync<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jValue = ConvertJson(value);
            return await base.redis.SetContainsAsync(key, jValue);
        }

        /// <summary>
        ///Gets a random value from the key collection
        /// </summary>
        /// <typeparam name="T">The data type</typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<T> SetRandomMemberAsync<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = await base.redis.SetRandomMemberAsync(key);
            return ConvertObj<T>(rValue);
        }

        /// <summary>
        ///Gets the collection of all key values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<List<T>> SetMembersAsync<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = await base.redis.SetMembersAsync(key);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Deletes the value specified in the key set
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<long> SetRemoveAsync<T> (string key, params T[] value)
        {
            key = AddSysCustomKey(key);
            RedisValue[] valueList = base.ConvertRedisValue(value);
            return await base.redis.SetRemoveAsync(key, valueList);
        }

        /// <summary>
        ///Randomly removes a value from the key collection and returns that value
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<T> SetPopAsync<T> (string key)
        {
            key = AddSysCustomKey(key);
            var rValue = await base.redis.SetPopAsync(key);
            return ConvertObj<T>(rValue);
        }


        /// <summary>
        ///Gets the union of several collections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public async Task<List<T>> SetCombineUnionAsync<T> (params string[] keys)
        {
            return await _SetCombineAsync<T>(SetOperation.Union, keys);
        }
        /// <summary>
        ///Gets the intersection of several collections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public async Task<List<T>> SetCombineIntersectAsync<T> (params string[] keys)
        {
            return await _SetCombineAsync<T>(SetOperation.Intersect, keys);
        }
        /// <summary>
        ///Gets the difference set of several sets
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public async Task<List<T>> SetCombineDifferenceAsync<T> (params string[] keys)
        {
            return await _SetCombineAsync<T>(SetOperation.Difference, keys);
        }



        /// <summary>
        ///Gets the union of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public async Task<long> SetCombineUnionAndStoreAsync(string destination, params string[] keys)
        {
            return await _SetCombineAndStoreAsync(SetOperation.Union, destination, keys);
        }
        /// <summary>
        ///Gets the intersection of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public async Task<long> SetCombineIntersectAndStoreAsync(string destination, params string[] keys)
        {
            return await _SetCombineAndStoreAsync(SetOperation.Intersect, destination, keys);
        }
        /// <summary>
        ///Gets the difference set of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public async Task<long> SetCombineDifferenceAndStoreAsync(string destination, params string[] keys)
        {
            return await _SetCombineAndStoreAsync(SetOperation.Difference, destination, keys);
        }

        #endregion

        #regionInternal auxiliary method
        /// <summary>
        ///Gets a cross union collection of several collections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="operation">-Leonard: Union, Intersect, Difference<see cref="SetOperation"/></param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        private List<T> _SetCombine<T> (SetOperation operation, params string[] keys)
        {
            RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys);
            var rValue = base.redis.SetCombine(operation, keyList);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Gets a cross union of several collections and saves them in a new Key
        /// </summary>
        /// <param name="operation">-Leonard: Union, Intersect, Difference<see cref="SetOperation"/></param>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        private long _SetCombineAndStore(SetOperation operation, string destination, params string[] keys)
        {
            destination = AddSysCustomKey(destination);
            RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys);
            return base.redis.SetCombineAndStore(operation, destination, keyList);
        }
        /// <summary>
        ///Gets a cross union collection of several collections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="operation">-Leonard: Union, Intersect, Difference<see cref="SetOperation"/></param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        private async Task<List<T> > _SetCombineAsync<T> (SetOperation operation, params string[] keys)
        {
            RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys);
            var rValue = await base.redis.SetCombineAsync(operation, keyList);
            return ConvetList<T>(rValue);
        }
        /// <summary>
        ///Gets a cross union of several collections and saves them in a new Key
        /// </summary>
        /// <param name="operation">-Leonard: Union, Intersect, Difference<see cref="SetOperation"/></param>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        private async Task<long> _SetCombineAndStoreAsync(SetOperation operation, string destination, params string[] keys)
        {
            destination = AddSysCustomKey(destination);
            RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys);
            return await base.redis.SetCombineAndStoreAsync(operation, destination, keyList);
        }

        #endregion

    }
Copy the code
/// <summary>
    ///Sorted Sets add a weight parameter score to the Set elements, so that the elements in the Set can be Sorted according to score
    ///1. Weighted elements, such as a game's user score leaderboard
    ///2. Relatively complex data structures, generally not too many scenarios are used
    /// </summary>
    public class RedisSortedSetService : RedisBase
    {
        #regionThe constructor

        /// <summary>
        ///Initialize Redis' SortedSet ordered data structure operation
        /// </summary>
        /// <param name="dbNum">Database indexes for the operation 0-64(need to be configured in conf file)</param>
        public RedisSortedSetService(int? dbNum = null) :
            base(dbNum){}#endregion

        #regionSynchronized methods

        /// <summary>
        ///Add a value to Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="score">Sort score, null will get the maximum score in the set plus 1</param>
        /// <returns></returns>
        public bool SortedSetAdd<T> (string key, T value.double? score = null)
        {
            key = AddSysCustomKey(key);
            double scoreNum = score ?? _GetScore(key);
            return base.redis.SortedSetAdd(key, ConvertJson<T>(value), scoreNum);
        }

        /// <summary>
        ///Add a collection to Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="score">Sort score, null will get the maximum score in the set plus 1</param>
        /// <returns></returns>
        public long SortedSetAdd<T> (string key, List<T> value.double? score = null)
        {
            key = AddSysCustomKey(key);
            double scoreNum = score ?? _GetScore(key);
            SortedSetEntry[] rValue = value.Select(o => new SortedSetEntry(ConvertJson<T>(o), scoreNum++)).ToArray();
            return base.redis.SortedSetAdd(key, rValue);
        }

        /// <summary>
        ///Gets the number in the collection
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long SortedSetLength(string key)
        {
            key = AddSysCustomKey(key);
            return redis.SortedSetLength(key);
        }

        /// <summary>
        ///Gets the number of collections from the specified start to end values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="startValue">The starting value</param>
        /// <param name="endValue">The end value</param>
        /// <returns></returns>
        public long SortedSetLengthByValue<T> (string key, T startValue, T endValue)
        {
            key = AddSysCustomKey(key);
            var sValue = ConvertJson<T>(startValue);
            var eValue = ConvertJson<T>(endValue);
            return redis.SortedSetLengthByValue(key, sValue, eValue);
        }

        /// <summary>
        ///Gets the sort Score value of the specified Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public double? SortedSetScore<T>(string key, T value)
        {
            key = AddSysCustomKey(key);
            var rValue = ConvertJson<T>(value);
            return redis.SortedSetScore(key, rValue);
        }

        /// <summary>
        ///Gets the minimum Score value for the specified Key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public double SortedSetMinScore(string key)
        {
            key = AddSysCustomKey(key);
            double dValue = 0;
            var rValue = base.redis.SortedSetRangeByRankWithScores(key, 0.0, Order.Ascending).FirstOrDefault(); dValue = rValue ! =null ? rValue.Score : 0;
            return dValue;
        }

        /// <summary>
        ///Gets the maximum Score value of the specified Key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public double SortedSetMaxScore(string key)
        {
            key = AddSysCustomKey(key);
            double dValue = 0;
            var rValue = base.redis.SortedSetRangeByRankWithScores(key, 0.0, Order.Descending).FirstOrDefault(); dValue = rValue ! =null ? rValue.Score : 0;
            return dValue;
        }

        /// <summary>
        ///Deletes the value specified in Key
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public long SortedSetRemove<T> (string key, params T[] value)
        {
            key = AddSysCustomKey(key);
            var rValue = ConvertRedisValue<T>(value);
            return base.redis.SortedSetRemove(key, rValue);
        }

        /// <summary>
        ///Deletes data from the specified start to end values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="startValue">The starting value</param>
        /// <param name="endValue">The end value</param>
        /// <returns></returns>
        public long SortedSetRemoveRangeByValue<T> (string key, T startValue, T endValue)
        {
            key = AddSysCustomKey(key);
            var sValue = ConvertJson<T>(startValue);
            var eValue = ConvertJson<T>(endValue);
            return base.redis.SortedSetRemoveRangeByValue(key, sValue, eValue);
        }

        /// <summary>
        ///Delete stop data starting from start
        /// </summary>
        /// <param name="key"></param>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <returns></returns>
        public long SortedSetRemoveRangeByRank(string key, long start, long stop)
        {
            key = AddSysCustomKey(key);
            return base.redis.SortedSetRemoveRangeByRank(key, start, stop);
        }

        /// <summary>
        ///Delete stop bar data starting from start according to sort Score
        /// </summary>
        /// <param name="key"></param>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <returns></returns>
        public long SortedSetRemoveRangeByScore(string key, double start, double stop)
        {
            key = AddSysCustomKey(key);
            return base.redis.SortedSetRemoveRangeByScore(key, start, stop);
        }

        /// <summary>
        ///Get stop bar data starting from start
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">Starting number</param>
        /// <param name="stop">-1 indicates the end. 0 indicates 1</param>
        /// <param name="desc">Is it sorted in descending order</param>
        /// <returns></returns>
        public List<T> SortedSetRangeByRank<T> (string key, long start = 0.long stop = - 1.bool desc = false)
        {
            key = AddSysCustomKey(key);
            Order orderBy = desc ? Order.Descending : Order.Ascending;
            var rValue = base.redis.SortedSetRangeByRank(key, start, stop, orderBy);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Get stop bar data from start containing Score, return data format: Key= Value, Value = Score
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">Starting number</param>
        /// <param name="stop">-1 indicates the end. 0 indicates 1</param>
        /// <param name="desc">Is it sorted in descending order</param>
        /// <returns></returns>
        public Dictionary<T.double> SortedSetRangeByRankWithScores<T> (string key, long start = 0.long stop = - 1.bool desc = false)
        {
            key = AddSysCustomKey(key);
            Order orderBy = desc ? Order.Descending : Order.Ascending;
            var rValue = base.redis.SortedSetRangeByRankWithScores(key, start, stop, orderBy);
            Dictionary<T, double> dicList = new Dictionary<T, double> ();foreach (var item in rValue)
            {
                dicList.Add(ConvertObj<T>(item.Element), item.Score);
            }
            return dicList;
        }

        /// <summary>
        ///Get stop bar data starting from start according to Score sort
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">Starting number</param>
        /// <param name="stop">-1 indicates the end. 0 indicates 1</param>
        /// <param name="desc">Is it sorted in descending order</param>
        /// <returns></returns>
        public List<T> SortedSetRangeByScore<T> (string key, double start = 0.double stop = - 1.bool desc = false)
        {
            key = AddSysCustomKey(key);
            Order orderBy = desc ? Order.Descending : Order.Ascending;
            var rValue = base.redis.SortedSetRangeByScore(key, start, stop, Exclude.None, orderBy);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Get stop bar data from start including Score according to Score sort, return data format: Key= Value, Value = Score
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">Starting number</param>
        /// <param name="stop">-1 indicates the end. 0 indicates 1</param>
        /// <param name="desc">Is it sorted in descending order</param>
        /// <returns></returns>
        public Dictionary<T.double> SortedSetRangeByScoreWithScores<T> (string key, double start = 0.double stop = - 1.bool desc = false)
        {
            key = AddSysCustomKey(key);
            Order orderBy = desc ? Order.Descending : Order.Ascending;
            var rValue = base.redis.SortedSetRangeByScoreWithScores(key, start, stop, Exclude.None, orderBy);
            Dictionary<T, double> dicList = new Dictionary<T, double> ();foreach (var item in rValue)
            {
                dicList.Add(ConvertObj<T>(item.Element), item.Score);
            }
            return dicList;
        }

        /// <summary>
        ///Gets data from the specified start to end values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="startValue">The starting value</param>
        /// <param name="endValue">The end value</param>
        /// <returns></returns>
        public List<T> SortedSetRangeByValue<T> (string key, T startValue, T endValue)
        {
            key = AddSysCustomKey(key);
            var sValue = ConvertJson<T>(startValue);
            var eValue = ConvertJson<T>(endValue);
            var rValue = base.redis.SortedSetRangeByValue(key, sValue, eValue);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Gets the union of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public long SortedSetCombineUnionAndStore(string destination, params string[] keys)
        {
            return _SortedSetCombineAndStore(SetOperation.Union, destination, keys);
        }

        /// <summary>
        ///Gets the intersection of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public long SortedSetCombineIntersectAndStore(string destination, params string[] keys)
        {
            return _SortedSetCombineAndStore(SetOperation.Intersect, destination, keys);
        }


        // The intersection does not seem to support/ <summary> / Gets the difference set of several sets and saves it in a new Key / </summary> / <param name="destination"> Save the new Key name </param> / <param name="keys"</param> / <returns></returns>//public long SortedSetCombineDifferenceAndStore(string destination, params string[] keys)
        / / {
        // return _SortedSetCombineAndStore(SetOperation.Difference, destination, keys);
        / /}



        /// <summary>
        ///Modify Scores with the specified Key and value subtract Scores from the original value and return final Scores
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="scores"></param>
        /// <returns></returns>
        public double SortedSetDecrement<T> (string key, T value.double scores)
        {
            key = AddSysCustomKey(key);
            var rValue = ConvertJson<T>(value);
            return redis.SortedSetDecrement(key, rValue, scores);
        }

        /// <summary>
        ///Alter Scores increment Scores over the specified Key and value and return final Scores
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="scores"></param>
        /// <returns></returns>
        public double SortedSetIncrement<T> (string key, T value.double scores)
        {
            key = AddSysCustomKey(key);
            var rValue = ConvertJson<T>(value);
            return redis.SortedSetIncrement(key, rValue, scores);
        }



        #endregion

        #regionAsynchronous methods

        /// <summary>
        ///Add a value to Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="score">Sort score, null will get the maximum score in the set plus 1</param>
        /// <returns></returns>
        public async Task<bool> SortedSetAddAsync<T> (string key, T value.double? score = null)
        {
            key = AddSysCustomKey(key);
            double scoreNum = score ?? _GetScore(key);
            return await base.redis.SortedSetAddAsync(key, ConvertJson<T>(value), scoreNum);
        }

        /// <summary>
        ///Add a collection to Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="score">Sort score, null will get the maximum score in the set plus 1</param>
        /// <returns></returns>
        public async Task<long> SortedSetAddAsync<T> (string key, List<T> value.double? score = null)
        {
            key = AddSysCustomKey(key);
            double scoreNum = score ?? _GetScore(key);
            SortedSetEntry[] rValue = value.Select(o => new SortedSetEntry(ConvertJson<T>(o), scoreNum++)).ToArray();
            return await base.redis.SortedSetAddAsync(key, rValue);
        }

        /// <summary>
        ///Gets the number in the collection
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<long> SortedSetLengthAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await redis.SortedSetLengthAsync(key);
        }

        /// <summary>
        ///Gets the number of collections from the specified start to end values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="startValue">The starting value</param>
        /// <param name="endValue">The end value</param>
        /// <returns></returns>
        public async Task<long> SortedSetLengthByValueAsync<T> (string key, T startValue, T endValue)
        {
            key = AddSysCustomKey(key);
            var sValue = ConvertJson<T>(startValue);
            var eValue = ConvertJson<T>(endValue);
            return await redis.SortedSetLengthByValueAsync(key, sValue, eValue);
        }

        /// <summary>
        ///Gets the sort Score value of the specified Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<double? >SortedSetScoreAsync<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            var rValue = ConvertJson<T>(value);
            return await redis.SortedSetScoreAsync(key, rValue);
        }

        /// <summary>
        ///Gets the minimum Score value for the specified Key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<double> SortedSetMinScoreAsync(string key)
        {
            key = AddSysCustomKey(key);
            double dValue = 0;
            var rValue = (await base.redis.SortedSetRangeByRankWithScoresAsync(key, 0.0, Order.Ascending)).FirstOrDefault(); dValue = rValue ! =null ? rValue.Score : 0;
            return dValue;
        }

        /// <summary>
        ///Gets the maximum Score value of the specified Key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<double> SortedSetMaxScoreAsync(string key)
        {
            key = AddSysCustomKey(key);
            double dValue = 0;
            var rValue = (await base.redis.SortedSetRangeByRankWithScoresAsync(key, 0.0, Order.Descending)).FirstOrDefault(); dValue = rValue ! =null ? rValue.Score : 0;
            return dValue;
        }

        /// <summary>
        ///Deletes the value specified in Key
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public async Task<long> SortedSetRemoveAsync<T> (string key, params T[] value)
        {
            key = AddSysCustomKey(key);
            var rValue = ConvertRedisValue<T>(value);
            return await base.redis.SortedSetRemoveAsync(key, rValue);
        }

        /// <summary>
        ///Deletes data from the specified start to end values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="startValue">The starting value</param>
        /// <param name="endValue">The end value</param>
        /// <returns></returns>
        public async Task<long> SortedSetRemoveRangeByValueAsync<T> (string key, T startValue, T endValue)
        {
            key = AddSysCustomKey(key);
            var sValue = ConvertJson<T>(startValue);
            var eValue = ConvertJson<T>(endValue);
            return await base.redis.SortedSetRemoveRangeByValueAsync(key, sValue, eValue);
        }

        /// <summary>
        ///Delete stop data starting from start
        /// </summary>
        /// <param name="key"></param>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <returns></returns>
        public async Task<long> SortedSetRemoveRangeByRankAsync(string key, long start, long stop)
        {
            key = AddSysCustomKey(key);
            return await base.redis.SortedSetRemoveRangeByRankAsync(key, start, stop);
        }

        /// <summary>
        ///Delete stop bar data starting from start according to sort Score
        /// </summary>
        /// <param name="key"></param>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <returns></returns>
        public async Task<long> SortedSetRemoveRangeByScoreAsync(string key, double start, double stop)
        {
            key = AddSysCustomKey(key);
            return await base.redis.SortedSetRemoveRangeByScoreAsync(key, start, stop);
        }

        /// <summary>
        ///Get stop bar data starting from start
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">Starting number</param>
        /// <param name="stop">-1 indicates the end. 0 indicates 1</param>
        /// <param name="desc">Is it sorted in descending order</param>
        /// <returns></returns>
        public async Task<List<T>> SortedSetRangeByRankAsync<T> (string key, long start = 0.long stop = - 1.bool desc = false)
        {
            key = AddSysCustomKey(key);
            Order orderBy = desc ? Order.Descending : Order.Ascending;
            var rValue = await base.redis.SortedSetRangeByRankAsync(key, start, stop, orderBy);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Get stop bar data from start containing Score, return data format: Key= Value, Value = Score
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">Starting number</param>
        /// <param name="stop">-1 indicates the end. 0 indicates 1</param>
        /// <param name="desc">Is it sorted in descending order</param>
        /// <returns></returns>
        public async Task<Dictionary<T.double>> SortedSetRangeByRankWithScoresAsync<T> (string key, long start = 0.long stop = - 1.bool desc = false)
        {
            key = AddSysCustomKey(key);
            Order orderBy = desc ? Order.Descending : Order.Ascending;
            var rValue = await base.redis.SortedSetRangeByRankWithScoresAsync(key, start, stop, orderBy);
            Dictionary<T, double> dicList = new Dictionary<T, double> ();foreach (var item in rValue)
            {
                dicList.Add(ConvertObj<T>(item.Element), item.Score);
            }
            return dicList;
        }

        /// <summary>
        ///Get stop bar data starting from start according to Score sort
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">Starting number</param>
        /// <param name="stop">-1 indicates the end. 0 indicates 1</param>
        /// <param name="desc">Is it sorted in descending order</param>
        /// <returns></returns>
        public async Task<List<T>> SortedSetRangeByScoreAsync<T> (string key, double start = 0.double stop = - 1.bool desc = false)
        {
            key = AddSysCustomKey(key);
            Order orderBy = desc ? Order.Descending : Order.Ascending;
            var rValue = await base.redis.SortedSetRangeByScoreAsync(key, start, stop, Exclude.None, orderBy);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Get stop bar data from start including Score according to Score sort, return data format: Key= Value, Value = Score
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">Starting number</param>
        /// <param name="stop">-1 indicates the end. 0 indicates 1</param>
        /// <param name="desc">Is it sorted in descending order</param>
        /// <returns></returns>
        public async Task<Dictionary<T.double>> SortedSetRangeByScoreWithScoresAsync<T> (string key, double start = 0.double stop = - 1.bool desc = false)
        {
            key = AddSysCustomKey(key);
            Order orderBy = desc ? Order.Descending : Order.Ascending;
            var rValue = await base.redis.SortedSetRangeByScoreWithScoresAsync(key, start, stop, Exclude.None, orderBy);
            Dictionary<T, double> dicList = new Dictionary<T, double> ();foreach (var item in rValue)
            {
                dicList.Add(ConvertObj<T>(item.Element), item.Score);
            }
            return dicList;
        }

        /// <summary>
        ///Gets data from the specified start to end values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="startValue">The starting value</param>
        /// <param name="endValue">The end value</param>
        /// <returns></returns>
        public async Task<List<T>> SortedSetRangeByValueAsync<T> (string key, T startValue, T endValue)
        {
            key = AddSysCustomKey(key);
            var sValue = ConvertJson<T>(startValue);
            var eValue = ConvertJson<T>(endValue);
            var rValue = await base.redis.SortedSetRangeByValueAsync(key, sValue, eValue);
            return ConvetList<T>(rValue);
        }

        /// <summary>
        ///Gets the union of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public async Task<long> SortedSetCombineUnionAndStoreAsync(string destination, params string[] keys)
        {
            return await _SortedSetCombineAndStoreAsync(SetOperation.Union, destination, keys);
        }

        /// <summary>
        ///Gets the intersection of several collections and saves it in a new Key
        /// </summary>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        public async Task<long> SortedSetCombineIntersectAndStoreAsync(string destination, params string[] keys)
        {
            return await_SortedSetCombineAndStoreAsync(SetOperation.Intersect, destination, keys); } / <summary> / Get the difference set of several sets and save it in a new Key / </summary> / <param name="destination"> Save the new Key name </param> / <param name="keys"</param> / <returns></returns>//public async Task<long> SortedSetCombineDifferenceAndStoreAsync(string destination, params string[] keys)
        / / {
        // return await _SortedSetCombineAndStoreAsync(SetOperation.Difference, destination, keys);
        / /}

        /// <summary>
        ///Modify Scores with the specified Key and value subtract Scores from the original value and return final Scores
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="scores"></param>
        /// <returns></returns>
        public async Task<double> SortedSetDecrementAsync<T> (string key, T value.double scores)
        {
            key = AddSysCustomKey(key);
            var rValue = ConvertJson<T>(value);
            return await base.redis.SortedSetDecrementAsync(key, rValue, scores);
        }

        /// <summary>
        ///Alter Scores increment Scores over the specified Key and value and return final Scores
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="scores"></param>
        /// <returns></returns>
        public async Task<double> SortedSetIncrementAsync<T> (string key, T value.double scores)
        {
            key = AddSysCustomKey(key);
            var rValue = ConvertJson<T>(value);
            return await base.redis.SortedSetIncrementAsync(key, rValue, scores);
        }



        #endregion

        #regionInternal auxiliary method
        /// <summary>
        ///Get the maximum Score value in the specified Key,
        /// </summary>
        /// <param name="key">The key name must be prefixed with the key</param>
        /// <returns></returns>
        private double _GetScore(string key)
        {
            double dValue = 0;
            var rValue = base.redis.SortedSetRangeByRankWithScores(key, 0.0, Order.Descending).FirstOrDefault(); dValue = rValue ! =null ? rValue.Score : 0;
            return dValue + 1;
        }

        /// <summary>
        ///Gets a cross union of several collections and saves them in a new Key
        /// </summary>
        /// <param name="operation">-Leonard: Union, Intersect, Difference<see cref="SetOperation"/></param>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        private long _SortedSetCombineAndStore(SetOperation operation, string destination, params string[] keys)
        {
            #regionLooking at the source code, it seems that Difference is not supported
            //RedisCommand command;
            //if (operation ! = SetOperation.Union)
            / / {
            // if (operation ! = SetOperation.Intersect)
            / / {
            // throw new ArgumentOutOfRangeException("operation");
            / /}
            // command = RedisCommand.ZINTERSTORE;
            / /}
            //else
            / / {
            // command = RedisCommand.ZUNIONSTORE;
            / /}
            #endregion

            destination = AddSysCustomKey(destination);
            RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys);
            var rValue = base.redis.SortedSetCombineAndStore(operation, destination, keyList);
            return rValue;

        }

        /// <summary>
        ///Gets a cross union of several collections and saves them in a new Key
        /// </summary>
        /// <param name="operation">-Leonard: Union, Intersect, Difference<see cref="SetOperation"/></param>
        /// <param name="destination">The name of the new Key to save</param>
        /// <param name="keys">The set of keys to operate on</param>
        /// <returns></returns>
        private async Task<long> _SortedSetCombineAndStoreAsync(SetOperation operation, string destination, params string[] keys)
        {
            destination = AddSysCustomKey(destination);
            RedisKey[] keyList = base.ConvertRedisKeysAddSysCustomKey(keys);
            var rValue = await base.redis.SortedSetCombineAndStoreAsync(operation, destination, keyList);
            return rValue;
        }

        #endregion
    }
Copy the code
/// <summary>
    ///Key-value: Value can be serialized data
    /// </summary>
    public class RedisStringService : RedisBase
    {
        #regionThe constructor

        /// <summary>
        ///Initialize the Redis String data structure operation
        /// </summary>
        /// <param name="dbNum">Database indexes for the operation 0-64(need to be configured in conf file)</param>
        public RedisStringService(int? dbNum = null) :
            base(dbNum){}#endregion

        #regionSynchronized methods
        /// <summary>
        ///Add a single key value
        /// </summary>
        /// <param name="key">Redis Key</param>
        /// <param name="value">Save the value of the</param>
        /// <param name="expiry">Expiration time</param>
        /// <returns></returns>
        public bool StringSet(string key, string value, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            return base.redis.StringSet(key, value, expiry);
        }

        /// <summary>
        ///Add multiple keys and values
        /// </summary>
        /// <param name="valueList">The key/value collection</param>
        /// <returns></returns>
        public bool StringSet(Dictionary<string.string> valueList)
        {
            var newkeyValues = valueList.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToArray();
            return base.redis.StringSet(newkeyValues);
        }

        /// <summary>
        ///Save an object
        /// </summary>
        /// <typeparam name="T">Object type</typeparam>
        /// <param name="key">Name of the saved Key</param>
        /// <param name="value">Object entities</param>
        /// <param name="expiry">Expiration time</param>
        /// <returns></returns>
        public bool StringSet<T> (string key, T value, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            string jsonValue = ConvertJson(value);
            return base.redis.StringSet(key, jsonValue, expiry);
        }

        /// <summary>
        ///Appends value to the value of the original key
        /// </summary>
        /// <param name="key">The name of the appended Key</param>
        /// <param name="value">The value of the additional</param>
        /// <returns></returns>
        public long StringAppend(string key, string value)
        {
            key = AddSysCustomKey(key);
            return base.redis.StringAppend(key, value);
        }

        /// <summary>
        ///Gets the value of a single key
        /// </summary>
        /// <param name="key">The name of the Key to read</param>
        /// <returns></returns>
        public string StringGet(string key)
        {
            key = AddSysCustomKey(key);
            return base.redis.StringGet(key);
        }

        /// <summary>
        ///Gets the value of multiple keys
        /// </summary>
        /// <param name="keys">The collection of keys to retrieve values</param>
        /// <returns></returns>
        public List<string> StringGet(params string[] keys)
        {
            var newKeys = ConvertRedisKeysAddSysCustomKey(keys);
            var values = base.redis.StringGet(newKeys);
            return values.Select(o => o.ToString()).ToList();
        }


        /// <summary>
        ///Gets the value of a single key
        /// </summary>
        /// <typeparam name="T">Return data type</typeparam>
        /// <param name="key">The collection of keys to retrieve values</param>
        /// <returns></returns>
        public T StringGet<T> (string key)
        {
            key = AddSysCustomKey(key);
            var values = base.redis.StringGet(key);
            return ConvertObj<T>(values);
        }

        /// <summary>
        ///Gets the value of multiple keys
        /// </summary>
        /// <typeparam name="T">Return data type</typeparam>
        /// <param name="keys">The collection of keys to retrieve values</param>
        /// <returns></returns>
        public List<T> StringGet<T> (params string[] keys)
        {
            var newKeys = ConvertRedisKeysAddSysCustomKey(keys);
            var values = base.redis.StringGet(newKeys);
            return ConvetList<T>(values);
        }

        /// <summary>
        ///Get the old value and assign the new value
        /// </summary>
        /// <param name="key">The Key name</param>
        /// <param name="value">The new value</param>
        /// <returns></returns>
        public string StringGetSet(string key, string value)
        {
            key = AddSysCustomKey(key);
            return base.redis.StringGetSet(key, value);
        }

        /// <summary>
        ///Get the old value and assign the new value
        /// </summary>
        /// <typeparam name="T">The data type</typeparam>
        /// <param name="key">The Key name</param>
        /// <param name="value">The new value</param>
        /// <returns></returns>
        public T StringGetSet<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jsonValue = ConvertJson(value);
            var oValue = base.redis.StringGetSet(key, jsonValue);
            return ConvertObj<T>(oValue);
        }


        /// <summary>
        ///Gets the length of the value
        /// </summary>
        /// <param name="key">The Key name</param>
        /// <returns></returns>
        public long StringGetLength(string key)
        {
            key = AddSysCustomKey(key);
            return base.redis.StringLength(key);
        }

        /// <summary>
        ///Increment val returns the increment value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val">You can have a negative</param>
        /// <returns>The value of the increment</returns>
        public double StringIncrement(string key, double val = 1)
        {
            key = AddSysCustomKey(key);
            return base.redis.StringIncrement(key, val);
        }

        /// <summary>
        ///The numeric decrement val returns the self-decrement value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val">You can have a negative</param>
        /// <returns>The reduced value</returns>
        public double StringDecrement(string key, double val = 1)
        {
            key = AddSysCustomKey(key);
            return base.redis.StringDecrement(key, val);
        }

        #endregion

        #regionAsynchronous methods
        /// <summary>
        ///Asynchronous methods save a single key value
        /// </summary>
        /// <param name="key">Redis Key</param>
        /// <param name="value">Save the value of the</param>
        /// <param name="expiry">Expiration time</param>
        /// <returns></returns>
        public async Task<bool> StringSetAsync(string key, string value, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            return await base.redis.StringSetAsync(key, value, expiry);
        }
        /// <summary>
        ///The asynchronous method adds multiple keys/values
        /// </summary>
        /// <param name="valueList">The key/value collection</param>
        /// <returns></returns>
        public async Task<bool> StringSetAsync(Dictionary<string.string> valueList)
        {
            var newkeyValues = valueList.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToArray();
            return await base.redis.StringSetAsync(newkeyValues);
        }

        /// <summary>
        ///Asynchronous methods hold an object
        /// </summary>
        /// <typeparam name="T">Object type</typeparam>
        /// <param name="key">Name of the saved Key</param>
        /// <param name="obj">Object entities</param>
        /// <param name="expiry">Expiration time</param>
        /// <returns></returns>
        public async Task<bool> StringSetAsync<T> (string key, T obj, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            string jsonValue = ConvertJson(obj);
            return await base.redis.StringSetAsync(key, jsonValue, expiry);
        }

        /// <summary>
        ///The asynchronous method appends a value to the value of the original key
        /// </summary>
        /// <param name="key">The name of the appended Key</param>
        /// <param name="value">The value of the additional</param>
        /// <returns></returns>
        public async Task<long> StringAppendAsync(string key, string value)
        {
            key = AddSysCustomKey(key);
            return await base.redis.StringAppendAsync(key, value);
        }

        /// <summary>
        ///The asynchronous method gets the value of a single key
        /// </summary>
        /// <param name="key">The name of the Key to read</param>
        /// <returns></returns>
        public async Task<string> StringGetAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await base.redis.StringGetAsync(key);
        }

        /// <summary>
        ///The asynchronous method gets the value of multiple keys
        /// </summary>
        /// <param name="keys">The collection of keys to retrieve values</param>
        /// <returns></returns>
        public async Task<List<string>> StringGetAsync(params string[] keys)
        {
            var newKeys = ConvertRedisKeysAddSysCustomKey(keys);
            var values = await base.redis.StringGetAsync(newKeys);
            return values.Select(o => o.ToString()).ToList();
        }


        /// <summary>
        ///The asynchronous method gets the value of a single key
        /// </summary>
        /// <typeparam name="T">Return data type</typeparam>
        /// <param name="key">The collection of keys to retrieve values</param>
        /// <returns></returns>
        public async Task<T> StringGetAsync<T> (string key)
        {
            key = AddSysCustomKey(key);
            var values = await base.redis.StringGetAsync(key);
            return ConvertObj<T>(values);
        }

        /// <summary>
        ///The asynchronous method gets the value of multiple keys
        /// </summary>
        /// <typeparam name="T">Return data type</typeparam>
        /// <param name="keys">The collection of keys to retrieve values</param>
        /// <returns></returns>
        public async Task<List<T>> StringGetAsync<T> (params string[] keys)
        {
            var newKeys = ConvertRedisKeysAddSysCustomKey(keys);
            var values = await base.redis.StringGetAsync(newKeys);
            return ConvetList<T>(values);
        }

        /// <summary>
        ///The asynchronous method takes the old value and assigns the new value
        /// </summary>
        /// <param name="key">The Key name</param>
        /// <param name="value">The new value</param>
        /// <returns></returns>
        public async Task<string> StringGetSetAsync(string key, string value)
        {
            key = AddSysCustomKey(key);
            return await base.redis.StringGetSetAsync(key, value);
        }

        /// <summary>
        ///The asynchronous method takes the old value and assigns the new value
        /// </summary>
        /// <typeparam name="T">The data type</typeparam>
        /// <param name="key">The Key name</param>
        /// <param name="value">The new value</param>
        /// <returns></returns>
        public async Task<T> StringGetSetAsync<T> (string key, T value)
        {
            key = AddSysCustomKey(key);
            string jsonValue = ConvertJson(value);
            var oValue = await base.redis.StringGetSetAsync(key, jsonValue);
            return ConvertObj<T>(oValue);
        }


        /// <summary>
        ///The asynchronous method gets the length of the value
        /// </summary>
        /// <param name="key">The Key name</param>
        /// <returns></returns>
        public async Task<long> StringGetLengthAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await base.redis.StringLengthAsync(key);
        }

        /// <summary>
        ///The asynchronous method increments val numerically and returns the incremented value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val">You can have a negative</param>
        /// <returns>The value of the increment</returns>
        public async Task<double> StringIncrementAsync(string key, double val = 1)
        {
            key = AddSysCustomKey(key);
            return await base.redis.StringIncrementAsync(key, val);
        }

        /// <summary>
        ///The asynchronous method decrement val, which returns a self-decrement value
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val">You can have a negative</param>
        /// <returns>The reduced value</returns>
        public async Task<double> StringDecrementAsync(string key, double val = 1)
        {
            key = AddSysCustomKey(key);
            return await base.redis.StringDecrementAsync(key, val);
        }

        #endregion
    }
Copy the code