Detailed Stackexchange.redis general encapsulation class sharing _c# tutorial

Source: Internet
Author: User
Tags publish subscribe redis serialization static class


Two days ago, my friend asked me if I have used Stackexchange.redis, asked me to have a package class, because before the use of Servicestack.redis, due to the Servicestack.redis V4 version is the charge version, So now there are companies that are using Stackexchange.redis to abandon Servicestack.redis. In fact, personally feel that two drivers are good, just because Servicestack.redis charges lead to many companies are based on the V3 version of the use, others said V3 version has a lot of bugs, no maintenance and upgrades, but at least for now I do not find bugs.



However, Servicestack.redis compared with Stackexchange.redis, aside from the charges, confirm more advantages than Stackexchange.redis. Stackexchange.redis documents, not to mention the domestic documents, even github the corresponding introductory documents are very one-sided, I really think that Stackexchange.redis the author at least to improve the following documents, many are to see the source code examples. The use of Stackexchange.redis on the internet is much less than Servicestack.redis, not to say that no one to use, but I checked, most of them are based on string type of data used in the encapsulation class, for the List,sortedset,hash encapsulation operations are very Less, the basic is to write a little, the West write a little, it is difficult to find complete. After reference to some articles and source code, here to provide a class of their own encapsulation, the basic provision for various types of use of encapsulation, provided to everyone to learn to use, if there is no bad, we can communicate with each other.



Connectionmultiplexer Package



The first is the encapsulation of the Connectionmultiplexer, the Connectionmultiplexer object is the Stackexchange.redis most central object. Instances of this class need to be shared and reused by the entire application domain, so there is no need to create an instance of the object in every operation, typically by using a single example to create and store the object, as explained on the official web site.


/// <summary>
 /// ConnectionMultiplexer object management helper class
 /// </ summary>
 public static class RedisConnectionHelp
 {
  // System custom Key prefix
  public static readonly string SysCustomKey = ConfigurationManager.AppSettings ["redisKey"] ?? "";

  //"127.0.0.1:6379,allowadmin=true
  private static readonly string RedisConnectionString = ConfigurationManager.ConnectionStrings ["RedisExchangeHosts"]. ConnectionString;

  private static readonly object Locker = new object ();
  private static ConnectionMultiplexer _instance;
  private static readonly ConcurrentDictionary <string, ConnectionMultiplexer> ConnectionCache = new ConcurrentDictionary <string, ConnectionMultiplexer> ();

  /// <summary>
  /// Singleton acquisition
  /// </ summary>
  public static ConnectionMultiplexer Instance
  {
   get
   {
    if (_instance == null)
    {
     lock (Locker)
     {
      if (_instance == null ||! _instance.IsConnected)
      {
       _instance = GetManager ();
      }
     }
    }
    return _instance;
   }
  }

  /// <summary>
  /// cache acquisition
  /// </ summary>
  /// <param name = "connectionString"> </ param>
  /// <returns> </ returns>
  public static ConnectionMultiplexer GetConnectionMultiplexer (string connectionString)
  {
   if (! ConnectionCache.ContainsKey (connectionString))
   {
    ConnectionCache [connectionString] = GetManager (connectionString);
   }
   return ConnectionCache [connectionString];
  }

  private static ConnectionMultiplexer GetManager (string connectionString = null)
  {
   connectionString = connectionString ?? RedisConnectionString;
   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;
  }

  #region events

  /// <summary>
  /// When configuration changes
  /// </ summary>
  /// <param name = "sender"> </ param>
  /// <param name = "e"> </ param>
  private static void MuxerConfigurationChanged (object sender, EndPointEventArgs e)
  {
   Console.WriteLine ("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)
  {
   Console.WriteLine ("ErrorMessage:" + e.Message);
  }

  /// <summary>
  /// error before re-establishing the connection
  /// </ summary>
  /// <param name = "sender"> </ param>
  /// <param name = "e"> </ param>
  private static void MuxerConnectionRestored (object sender, ConnectionFailedEventArgs e)
  {
   Console.WriteLine ("ConnectionRestored:" + e.EndPoint);
  }

  /// <summary>
  /// connection failed, you will not receive this notification if the reconnection is successful
  /// </ summary>
  /// <param name = "sender"> </ param>
  /// <param name = "e"> </ param>
  private static void MuxerConnectionFailed (object sender, ConnectionFailedEventArgs e)
  {
   Console.WriteLine ("Reconnect: Endpoint failed:" + e.EndPoint + "," + e.FailureType + (e.Exception == null? "": ("," + E.Exception.Message)));
  }

  /// <summary>
  /// change cluster
  /// </ summary>
  /// <param name = "sender"> </ param>
  /// <param name = "e"> </ param>
  private static void MuxerHashSlotMoved (object sender, HashSlotMovedEventArgs e)
  {
   Console.WriteLine ("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)
  {
   Console.WriteLine ("InternalError: Message" + e.Exception.Message);
  }

  #endregion events
 }


 


redishelper Generic action class seal


public class RedisHelper
 {
  private int DbNum {get;}
  private readonly ConnectionMultiplexer _conn;
  public string CustomKey;

  #region Constructor

  public RedisHelper (int dbNum = 0)
    : this (dbNum, null)
  {
  }

  public RedisHelper (int dbNum, string readWriteHosts)
  {
   DbNum = dbNum;
   _conn =
    string.IsNullOrWhiteSpace (readWriteHosts)?
    RedisConnectionHelp.Instance:
    RedisConnectionHelp.GetConnectionMultiplexer (readWriteHosts);
  }

#region helper methods

  private string AddSysCustomKey (string oldKey)
  {
   var prefixKey = CustomKey ?? RedisConnectionHelp.SysCustomKey;
   return prefixKey + oldKey;
  }

  private T Do <T> (Func <IDatabase, T> func)
  {
   var database = _conn.GetDatabase (DbNum);
   return func (database);
  }

  private string ConvertJson <T> (T value)
  {
   string result = value is string? value.ToString (): JsonConvert.SerializeObject (value);
   return result;
  }

  private T ConvertObj <T> (RedisValue value)
  {
   return JsonConvert.DeserializeObject <T> (value);
  }

  private 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;
  }

  private RedisKey [] ConvertRedisKeys (List <string> redisKeys)
  {
   return redisKeys.Select (redisKey => (RedisKey) redisKey) .ToArray ();
  }

  #endregion helper methods

  #endregion Constructor
}


Where Customkey is used to represent the system prefix, the Addsyscustomkey method adds a prefix to each key, recommending that you prefix the name of the Redis key and use: to split the prefix, This is easier to distinguish when viewing using visual tools, such as my prefix is demo:test: (usually the system name: Business Name:), and then you look at the time you will find neat, good distinguish a lot






string-Type Encapsulation


#region String

  #region synchronization method

  /// <summary>
  /// save a single key value
  /// </ summary>
  /// <param name = "key"> Redis Key </ param>
  /// <param name = "value"> the saved value </ param>
  /// <param name = "expiry"> Expiration time </ param>
  /// <returns> </ returns>
  public bool StringSet (string key, string value, TimeSpan? expiry = default (TimeSpan?))
  {
   key = AddSysCustomKey (key);
   return Do (db => db.StringSet (key, value, expiry));
  }

  /// <summary>
  /// save multiple key values
  /// </ summary>
  /// <param name = "keyValues"> key-value pairs </ param>
  /// <returns> </ returns>
  public bool StringSet (List <KeyValuePair <RedisKey, RedisValue >> keyValues)
  {
   List <KeyValuePair <RedisKey, RedisValue >> newkeyValues =
    keyValues.Select (p => new KeyValuePair <RedisKey, RedisValue> (AddSysCustomKey (p.Key), p.Value)). ToList ();
   return Do (db => db.StringSet (newkeyValues.ToArray ()));
  }

  /// <summary>
  /// save an object
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <param name = "obj"> </ param>
  /// <param name = "expiry"> </ param>
  /// <returns> </ returns>
  public bool StringSet <T> (string key, T obj, TimeSpan? expiry = default (TimeSpan?))
  {
   key = AddSysCustomKey (key);
   string json = ConvertJson (obj);
   return Do (db => db.StringSet (key, json, expiry));
  }

  /// <summary>
  /// get the value of a single key
  /// </ summary>
  /// <param name = "key"> Redis Key </ param>
  /// <returns> </ returns>
  public string StringGet (string key)
  {
   key = AddSysCustomKey (key);
   return Do (db => db.StringGet (key));
  }

  /// <summary>
  /// get multiple keys
  /// </ summary>
  /// <param name = "listKey"> Redis Key collection </ param>
  /// <returns> </ returns>
  public RedisValue [] StringGet (List <string> listKey)
  {
   List <string> newKeys = listKey.Select (AddSysCustomKey) .ToList ();
   return Do (db => db.StringGet (ConvertRedisKeys (newKeys)));
  }

  /// <summary>
  /// get a key object
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public T StringGet <T> (string key)
  {
   key = AddSysCustomKey (key);
   return Do (db => ConvertObj <T> (db.StringGet (key)));
  }

  /// <summary>
  /// increase the number by val
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "val"> can be negative </ param>
  /// <returns> the value after growth </ returns>
  public double StringIncrement (string key, double val = 1)
  {
   key = AddSysCustomKey (key);
   return Do (db => db.StringIncrement (key, val));
  }

  /// <summary>
  /// Decrease val for numbers
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "val"> can be negative </ param>
  /// <returns> decreased value </ returns>
  public double StringDecrement (string key, double val = 1)
  {
   key = AddSysCustomKey (key);
   return Do (db => db.StringDecrement (key, val));
  }

  #endregion synchronization method

  #region asynchronous methods

  /// <summary>
  /// save a single key value
  /// </ summary>
  /// <param name = "key"> Redis Key </ param>
  /// <param name = "value"> the saved value </ 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 Do (db => db.StringSetAsync (key, value, expiry));
  }

  /// <summary>
  /// save multiple key values
  /// </ summary>
  /// <param name = "keyValues"> key-value pairs </ param>
  /// <returns> </ returns>
  public async Task <bool> StringSetAsync (List <KeyValuePair <RedisKey, RedisValue >> keyValues)
  {
   List <KeyValuePair <RedisKey, RedisValue >> newkeyValues =
    keyValues.Select (p => new KeyValuePair <RedisKey, RedisValue> (AddSysCustomKey (p.Key), p.Value)). ToList ();
   return await Do (db => db.StringSetAsync (newkeyValues.ToArray ()));
  }

  /// <summary>
  /// save an object
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <param name = "obj"> </ param>
  /// <param name = "expiry"> </ param>
  /// <returns> </ returns>
  public async Task <bool> StringSetAsync <T> (string key, T obj, TimeSpan? expiry = default (TimeSpan?))
  {
   key = AddSysCustomKey (key);
   string json = ConvertJson (obj);
   return await Do (db => db.StringSetAsync (key, json, expiry));
  }

  /// <summary>
  /// get the value of a single key
  /// </ summary>
  /// <param name = "key"> Redis Key </ param>
  /// <returns> </ returns>
  public async Task <string> StringGetAsync (string key)
  {
   key = AddSysCustomKey (key);
   return await Do (db => db.StringGetAsync (key));
  }

  /// <summary>
  /// get multiple keys
  /// </ summary>
  /// <param name = "listKey"> Redis Key collection </ param>
  /// <returns> </ returns>
  public async Task <RedisValue []> StringGetAsync (List <string> listKey)
  {
   List <string> newKeys = listKey.Select (AddSysCustomKey) .ToList ();
   return await Do (db => db.StringGetAsync (ConvertRedisKeys (newKeys)));
  }

  /// <summary>
  /// get a key object
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public async Task <T> StringGetAsync <T> (string key)
  {
   key = AddSysCustomKey (key);
   string result = await Do (db => db.StringGetAsync (key));
   return ConvertObj <T> (result);
  }

  /// <s
ummary>
   /// increase the number by val
   /// </ summary>
   /// <param name = "key"> </ param>
   /// <param name = "val"> can be negative </ param>
   /// <returns> the value after growth </ returns>
   public async Task <double> StringIncrementAsync (string key, double val = 1)
   {
    key = AddSysCustomKey (key);
    return await Do (db => db.StringIncrementAsync (key, val));
   }

   /// <summary>
   /// Decrease val for numbers
   /// </ summary>
   /// <param name = "key"> </ param>
   /// <param name = "val"> can be negative </ param>
   /// <returns> decreased value </ returns>
   public async Task <double> StringDecrementAsync (string key, double val = 1)
   {
    key = AddSysCustomKey (key);
    return await Do (db => db.StringDecrementAsync (key, val));
   }

   #endregion Asynchronous methods

   #endregion String


In this case, the storage of objects in Stackexchange.redis is a method of not being serialized and deserialized, so in Convertjson and convertobj I use JsonConvert to operate, If you need to change to other serialization and serialization, it is better to directly modify these two aspects, in addition, Stackexchange.redis relative to Servicestack.redis provides an asynchronous method, so here also encapsulates the asynchronous and synchronous methods.



Encapsulation of the list type


#region List

  #region synchronization method

  /// <summary>
  /// remove the value of the internal List of the specified ListId
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  public void ListRemove <T> (string key, T value)
  {
   key = AddSysCustomKey (key);
   Do (db => db.ListRemove (key, ConvertJson (value)));
  }

  /// <summary>
  /// get the List of the specified key
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public List <T> ListRange <T> (string key)
  {
   key = AddSysCustomKey (key);
   return Do (redis =>
   {
    var values = redis.ListRange (key);
    return ConvetList <T> (values);
   });
  }

  /// <summary>
  /// join the team
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  public void ListRightPush <T> (string key, T value)
  {
   key = AddSysCustomKey (key);
   Do (db => db.ListRightPush (key, ConvertJson (value)));
  }

  /// <summary>
  /// get out of the team
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public T ListRightPop <T> (string key)
  {
   key = AddSysCustomKey (key);
   return Do (db =>
    {
     var value = db.ListRightPop (key);
     return ConvertObj <T> (value);
    });
  }

  /// <summary>
  /// push the stack
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  public void ListLeftPush <T> (string key, T value)
  {
   key = AddSysCustomKey (key);
   Do (db => db.ListLeftPush (key, ConvertJson (value)));
  }

  /// <summary>
  /// pop out of the stack
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public T ListLeftPop <T> (string key)
  {
   key = AddSysCustomKey (key);
   return Do (db =>
   {
    var value = db.ListLeftPop (key);
    return ConvertObj <T> (value);
   });
  }

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

  #endregion synchronization method

  #region asynchronous methods

  /// <summary>
  /// remove the value of the internal List of the specified ListId
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  public async Task <long> ListRemoveAsync <T> (string key, T value)
  {
   key = AddSysCustomKey (key);
   return await Do (db => db.ListRemoveAsync (key, ConvertJson (value)));
  }

  /// <summary>
  /// get the List of the specified key
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public async Task <List <T >> ListRangeAsync <T> (string key)
  {
   key = AddSysCustomKey (key);
   var values = await Do (redis => redis.ListRangeAsync (key));
   return ConvetList <T> (values);
  }

  /// <summary>
  /// join the team
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  public async Task <long> ListRightPushAsync <T> (string key, T value)
  {
   key = AddSysCustomKey (key);
   return await Do (db => db.ListRightPushAsync (key, ConvertJson (value)));
  }

  /// <summary>
  /// get out of the team
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public async Task <T> ListRightPopAsync <T> (string key)
  {
   key = AddSysCustomKey (key);
   var value = await Do (db => db.ListRightPopAsync (key));
   return ConvertObj <T> (value);
  }

  /// <summary>
  /// push the stack
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  public async Task <long> ListLeftPushAsync <T> (string key, T value)
  {
   key = AddSysCustomKey (key);
   return await Do (db => db.ListLeftPushAsync (key, ConvertJson (value)));
  }

  /// <summary>
  /// pop out of the stack
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public async Task <T> ListLeftPopAsync <T> (string key)
  {
   key = AddSysCustomKey (key);
   var value = await Do (db => db.ListLeftPopAsync (key));
   return ConvertObj <T> (value);
  }

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

  #endregion Asynchronous methods

  #endregion List


 


Hash-type encapsulation



#region Hash

  #region synchronization method

  /// <summary>
  /// determine whether some 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 Do (db => db.HashExists (key, dataKey));
  }

  /// <summary>
  /// store data in 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);
   return Do (db =>
   {
    string json = ConvertJson (t);
    return db.HashSet (key, dataKey, json);
   });
  }

  /// <summary>
  /// remove 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 Do (db => db.HashDelete (key, dataKey));
  }

  /// <summary>
  /// remove multiple values in the hash
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "dataKeys"> </ param>
  /// <returns> </ returns>
  public long HashDelete (string key, List <RedisValue> dataKeys)
  {
   key = AddSysCustomKey (key);
   // List <RedisValue> dataKeys1 = new List <RedisValue> () {"1", "2"};
   return Do (db => db.HashDelete (key, dataKeys.ToArray ()));
  }

  /// <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);
   return Do (db =>
   {
    string value = db.HashGet (key, dataKey);
    return ConvertObj <T> (value);
   });
  }

  /// <summary>
  /// increase the number by val
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "dataKey"> </ param>
  /// <param name = "val"> can be negative </ param>
  /// <returns> the value after growth </ returns>
  public double HashIncrement (string key, string dataKey, double val = 1)
  {
   key = AddSysCustomKey (key);
   return Do (db => db.HashIncrement (key, dataKey, val));
  }

  /// <summary>
  /// Decrease val for numbers
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "dataKey"> </ param>
  /// <param name = "val"> can be negative </ param>
  /// <returns> decreased value </ returns>
  public double HashDecrement (string key, string dataKey, double val = 1)
  {
   key = AddSysCustomKey (key);
   return Do (db => db.HashDecrement (key, dataKey, val));
  }

  /// <summary>
  /// Get all Redis keys for hashkey
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public List <T> HashKeys <T> (string key)
  {
   key = AddSysCustomKey (key);
   return Do (db =>
   {
    RedisValue [] values = db.HashKeys (key);
    return ConvetList <T> (values);
   });
  }

  #endregion synchronization method

  #region asynchronous methods

  /// <summary>
  /// determine whether some 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 Do (db => db.HashExistsAsync (key, dataKey));
  }

  /// <summary>
  /// store data in hash table
  /// </ 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);
   return await Do (db =>
   {
    string json = ConvertJson (t);
    return db.HashSetAsync (key, dataKey, json);
   });
  }

  /// <summary>
  /// remove 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 Do (db => db.HashDeleteAsync (key, dataKey));
  }

  /// <summary>
  /// remove multiple values in the hash
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "dataKeys"> </ param>
  /// <returns> </ returns>
  public async Task <long> HashDeleteAsync (string key, List <RedisValue> dataKeys)
  {
   key = AddSysCustomKey (key);
   // List <RedisValue> dataKeys1 = new List <RedisValue> () {"1", "2"};
   return await Do (db => db.HashDeleteAsync (key, dataKeys.ToArray ()));
  }

  /// <summary>
  /// 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> HashGeAsync <T> (string key, string dataKey)
  {
   key = AddSysCustomKey (key);
   string value = await Do (db => db.HashGetAsync (key, dataKey));
   return ConvertObj <T> (value);
  }

  /// <summary>
  /// increase the number by val
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "dataKey"> </ param>
  /// <param name = "val"> can be negative </ param>
  /// <returns> the value after growth </ returns>
  public async Task <double> HashIncrement Async (string key, string dataKey, double val = 1)
   {
    key = AddSysCustomKey (key);
    return await Do (db => db.HashIncrementAsync (key, dataKey, val));
   }

   /// <summary>
   /// Decrease val for numbers
   /// </ summary>
   /// <param name = "key"> </ param>
   /// <param name = "dataKey"> </ param>
   /// <param name = "val"> can be negative </ param>
   /// <returns> decreased value </ returns>
   public async Task <double> HashDecrementAsync (string key, string dataKey, double val = 1)
   {
    key = AddSysCustomKey (key);
    return await Do (db => db.HashDecrementAsync (key, dataKey, val));
   }

   /// <summary>
   /// Get all Redis keys for hashkey
   /// </ summary>
   /// <typeparam name = "T"> </ typeparam>
   /// <param name = "key"> </ param>
   /// <returns> </ returns>
   public async Task <List <T >> HashKeysAsync <T> (string key)
   {
    key = AddSysCustomKey (key);
    RedisValue [] values = await Do (db => db.HashKeysAsync (key));
    return ConvetList <T> (values);
   }

   #endregion Asynchronous methods

   #endregion Hash
 



sortedset type encapsulation


#region SortedSet Ordered Set

  #region synchronization method

  /// <summary>
  /// Add to
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  /// <param name = "score"> </ param>
  public bool SortedSetAdd <T> (string key, T value, double score)
  {
   key = AddSysCustomKey (key);
   return Do (redis => redis.SortedSetAdd (key, ConvertJson <T> (value), score));
  }

  /// <summary>
  /// delete
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  public bool SortedSetRemove <T> (string key, T value)
  {
   key = AddSysCustomKey (key);
   return Do (redis => redis.SortedSetRemove (key, ConvertJson (value)));
  }

  /// <summary>
  /// get all
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public List <T> SortedSetRangeByRank <T> (string key)
  {
   key = AddSysCustomKey (key);
   return Do (redis =>
   {
    var values = redis.SortedSetRangeByRank (key);
    return ConvetList <T> (values);
   });
  }

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

  #endregion synchronization method

  #region asynchronous methods

  /// <summary>
  /// Add to
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  /// <param name = "score"> </ param>
  public async Task <bool> SortedSetAddAsync <T> (string key, T value, double score)
  {
   key = AddSysCustomKey (key);
   return await Do (redis => redis.SortedSetAddAsync (key, ConvertJson <T> (value), score));
  }

  /// <summary>
  /// delete
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <param name = "value"> </ param>
  public async Task <bool> SortedSetRemoveAsync <T> (string key, T value)
  {
   key = AddSysCustomKey (key);
   return await Do (redis => redis.SortedSetRemoveAsync (key, ConvertJson (value)));
  }

  /// <summary>
  /// get all
  /// </ summary>
  /// <param name = "key"> </ param>
  /// <returns> </ returns>
  public async Task <List <T >> SortedSetRangeByRankAsync <T> (string key)
  {
   key = AddSysCustomKey (key);
   var values = await Do (redis => redis.SortedSetRangeByRankAsync (key));
   return ConvetList <T> (values);
  }

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

  #endregion Asynchronous methods

  #endregion SortedSet Ordered Set


Key Management


#region key

  /// <summary>
  /// delete a single key
  /// </ summary>
  /// <param name = "key"> redis key </ param>
  /// <returns> whether the deletion was successful </ returns>
  public bool KeyDelete (string key)
  {
   key = AddSysCustomKey (key);
   return Do (db => db.KeyDelete (key));
  }

  /// <summary>
  /// delete multiple keys
  /// </ summary>
  /// <param name = "keys"> rediskey </ param>
  /// <returns> Number of successful deletions </ returns>
  public long KeyDelete (List <string> keys)
  {
   List <string> newKeys = keys.Select (AddSysCustomKey) .ToList ();
   return Do (db => db.KeyDelete (ConvertRedisKeys (newKeys)));
  }

  /// <summary>
  /// determine whether the key is stored
  /// </ summary>
  /// <param name = "key"> redis key </ param>
  /// <returns> </ returns>
  public bool KeyExists (string key)
  {
   key = AddSysCustomKey (key);
   return Do (db => db.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);
   return Do (db => db.KeyRename (key, newKey));
  }

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

  #endregion key 


Publish and subscribe


#region Publish Subscription

  /// <summary>
  /// Redis Publish Subscribe Subscribe
  /// </ summary>
  /// <param name = "subChannel"> </ param>
  /// <param name = "handler"> </ param>
  public void Subscribe (string subChannel, Action <RedisChannel, RedisValue> handler = null)
  {
   ISubscriber sub = _conn.GetSubscriber ();
   sub.Subscribe (subChannel, (channel, message) =>
   {
    if (handler == null)
    {
     Console.WriteLine (subChannel + "Subscribe to receive message:" + message);
    }
    else
    {
     handler (channel, message);
    }
   });
  }

  /// <summary>
  /// Redis Publish Subscribe Publish
  /// </ summary>
  /// <typeparam name = "T"> </ typeparam>
  /// <param name = "channel"> </ param>
  /// <param name = "msg"> </ param>
  /// <returns> </ returns>
  public long Publish <T> (string channel, T msg)
  {
   ISubscriber sub = _conn.GetSubscriber ();
   return sub.Publish (channel, ConvertJson (msg));
  }

  /// <summary>
  /// Redis Publish Subscription Cancel Subscription
  /// </ summary>
  /// <param name = "channel"> </ param>
  public void Unsubscribe (string channel)
  {
   ISubscriber sub = _conn.GetSubscriber ();
   sub.Unsubscribe (channel);
  }

  /// <summary>
  /// Redis publish subscription Cancel all subscriptions
  /// </ summary>
  public void UnsubscribeAll ()
  {
   ISubscriber sub = _conn.GetSubscriber ();
   sub.UnsubscribeAll ();
  }

  #endregion Publish Subscription 


Other


#region other public

  ITransaction createtransaction ()
  {return
   getdatabase (). CreateTransaction ();
  }

  Public Idatabase getdatabase ()
  {return
   _conn. Getdatabase (Dbnum);
  }

  Public Iserver Getserver (string hostandport)
  {return
   _conn. Getserver (Hostandport);
  }

  <summary>
  ///setting prefix
  ///</summary>
  ///<param name= "Customkey" ></param> Public
  void Setsyscustomkey (string customkey)
  {
   Customkey = Customkey;
  }

  #endregion Other


The above is the basic operation of Stackexchange.redis general packaging, provided to everyone to learn the reference, if there is no wrong to write, also hope to be able to communicate together.



Problem:



Does Stackexchange.redis not provide Redis distributed lock operation? Servicestack.redis provides a Acquirelock method to operate, Stackexchange.redis source only found the Locktake method, and did not find other methods, if someone used, but also hope to provide under.



Finally, attach Source address: Demo



The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.