[C#] Redisのデータベースを接続して使い方


Devlopment note / C#    作成日付 : 2022/02/15 18:46:09   修正日付 : 2022/02/16 16:06:46

こんにちは。明月です。


この投稿はC#でRedisのデータベースを接続して使い方に関する説明です。


RedisデータベースはRDB種類ではなく、NoSQL種類のKey-Valueタイプのデータベースです。簡単に共有メモリのデータベースです。

以前の投稿でLinux環境にインストール及び使い方に関して説明したことがあります。

リング - [CentOS] Redisデータベースをインストールする方法とコマンドを使い方


そのRedisデータベースをC#で使ってみましょう。

まず、C#で使うためにはNugetを利用してStackExchange.Redisライブラリをインストールしましょう。



ライブラリがインストールされたらRedisデータベースに値を格納して取得しましょう。

using System;
using StackExchange.Redis;

namespace ConsoleApp1
{
  class Program
  {
    // 実行関数
    static void Main(string[] args)
    {
      // redis接続する。
      ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
      {
        EndPoints = { "192.168.1.200:6379" }
      });
      // 基本データベース取得
      var db = redis.GetDatabase();
      // ping pong確認
      var pong = db.Ping();
      // コンソール出力
      Console.WriteLine(pong);

      // testキーで「hello world」の値を格納する。満了時間は10分。
      db.StringSet("test", "hello world", TimeSpan.FromMinutes(10));
      // testキーでデータを取得する。
      string data = db.StringGet("test");
      // コンソール出力
      Console.WriteLine(data);

      // 任意のキーを押してください
      Console.WriteLine("Press Any key...");
      Console.ReadLine();
    }
  }
}



上のソースでtestのキーでhello worldを格納しました。そして10分後では自動にkey-valueが消えます。

そしてtestキーで取得すると入力したデータがコンソールに出よくします。


関連な関数に関してはAPIドキュメントを参照してください。

リンク - https://stackexchange.github.io/StackExchange.Redis/


上には単純にkeyでデータの値を格納して取得する基本的な処理です。

そうすると実践でプログラムを作成する時によく使われるコードを作成して見ましょう。

using System;
using System.IO;
using StackExchange.Redis;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace ConsoleApp1
{
  class Program
  {
    // シリアルタイプ
    [Serializable]
    // 例クラス
    class Node
    {
      // メンバー変数
      private string data;
      // コンストラクタ
      public Node(string data)
      {
        // メンバー変数設定
        this.data = data;
      }
      // 出力関数
      public void Print()
      {
        // コントロール出力
        Console.WriteLine(this.data);
      }
    }
    // Nodeクラスをシリアル化してbinaryに変換してStringタイプに変換
    static String ConvertToStringFromClass(Node node)
    {
      // シリアルクラス
      var formatter = new BinaryFormatter();
      // クラスをシリアル化して格納するデータ
      byte[] data;
      // メモリストリーム
      using (MemoryStream stream = new MemoryStream())
      {
        // クラスをシリアル化してstreamに変換
        formatter.Serialize(stream, node);
        // ストリームをbyte[]データに変換
        data = stream.GetBuffer();
      }
      // 値の変形がないようにASCIIコードでStringタイプに変換
      return Encoding.ASCII.GetString(data);
    }
    // 実行関数
    static void Main(string[] args)
    {
      // redis接続する。
      ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
      {
        EndPoints = { "192.168.1.200:6379" }
      });
      // 基本データベース取得
      var db = redis.GetDatabase();

      // インスタンスを生成
      var node = new Node("Test");
      // Nodeインスタンスをstringタイプに変換
      var data = ConvertToStringFromClass(node);
      // Redisデータベースにtestキーで格納(満了時間10分)
      db.StringSet("test", data, TimeSpan.FromMinutes(10));

      // 任意のキーを押してください
      Console.WriteLine("Press Any key...");
      Console.ReadLine();
    }
  }
}



上のソースでNodeクラスのインスタンスをシリアル化で利用してbyteに変換して、またStringタイプに変換してRedisデータベースに入力しました。

そうするとこのことで別のプログラムで取得できます。

using System;
using System.IO;
using StackExchange.Redis;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace ConsoleApp1
{
  class Program
  {
    // シリアルタイプ
    [Serializable]
    // 例クラス
    class Node
    {
      // メンバー変数
      private string data;
      // コンストラクタ
      public Node(string data)
      {
        // メンバー変数設定
        this.data = data;
      }
      // 出力関数
      public void Print()
      {
        // コントロール出力
        Console.WriteLine(this.data);
      }
    }
    // Stringタイプでbyteに変換してシリアル化を通ってインスタンスに変換
    static Node ConvertToClassFromString(String val)
    {
      // Stringを通ってbyteに変換
      var binary = Encoding.ASCII.GetBytes(val);
      // シリアルクラス
      var formatter = new BinaryFormatter();
      // メモリストリーム
      using (MemoryStream stream = new MemoryStream(binary))
      {
        // streamをシリアル化してインスタンスに変換
        return (Node)formatter.Deserialize(stream);
      }
    }
    // 実行関数
    static void Main(string[] args)
    {
      // redis接続する。
      ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
      {
        EndPoints = { "192.168.1.200:6379" }
      });
      // 基本データベース取得
      var db = redis.GetDatabase();

      // testキーでデータを取得する。
      var data = db.StringGet("test");
      // stringタイプをNodeインスタンスに変換
      var node = ConvertToClassFromString(data);
      // NodeクラスのPrint関数を呼び出す。
      node.Print();

      // 任意のキーを押してください
      Console.WriteLine("Press Any key...");
      Console.ReadLine();
    }
  }
}


別のプログラムで生成したNodeインスタンスをredisデータベースに格納して、また、別のプログラムで取得してインスタンスに変換して使うことを確認しました。

この意味はシリアル化を通ってクラス形式で様々なプログラムで値を共有できるという意味です。C#のシリアル化なので、別の言語プログラムでは使うことは出来ずに、同じ言語のC#だけで使うことが可能です。


別の言語で使うためにはJsonタイプで変換して使うなら言語が違くても値を共有することが可能ですね。

using System;
using StackExchange.Redis;
using Newtonsoft.Json;

namespace ConsoleApp1
{
  class Program
  {
    // 例クラス
    class Node
    {
      // メンバー変数
      public string Data { get; set; }
      // コンストラクタ
      public Node(string data)
      {
        // メンバー変数設定
        this.Data = data;
      }
      // 出力関数
      public void Print()
      {
        // コンソール出力
        Console.WriteLine(this.Data);
      }
    }
    // 実行関数
    static void Main(string[] args)
    {
      // redis接続する。
      ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
      {
        EndPoints = { "192.168.1.200:6379" }
      });
      // 基本データベース取得
      var db = redis.GetDatabase();

      // インスタンス生成
      var node = new Node("Test");
      // インスタンスをJsonタイプで変換
      var data = JsonConvert.SerializeObject(node);
      // Redisデータベースにtest1キーで格納(満了時間10分)
      db.StringSet("test1", data, TimeSpan.FromMinutes(10));

      // 任意のキーを押してください
      Console.WriteLine("Press Any key...");
      Console.ReadLine();
    }
  }
}



上のシリアル化を通ってStringに変換してRedisデータベースに格納することと似てますが、今回はシリアル化ではなくJson構造タイプに変換して入力しました。

using System;
using StackExchange.Redis;
using Newtonsoft.Json;

namespace ConsoleApp1
{
  class Program
  {
    // 例クラス
    class Node
    {
      // メンバー変数
      public string Data { get; set; }
      // コンストラクタ
      public Node(string data)
      {
        // メンバー変数設定
        this.Data = data;
      }
      // 出力関数
      public void Print()
      {
        // コンソール出力
        Console.WriteLine(this.Data);
      }
    }
    // 実行関数
    static void Main(string[] args)
    {
      // redis接続する。
      ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
      {
        EndPoints = { "192.168.1.200:6379" }
      });
      // 基本データベース取得
      var db = redis.GetDatabase();

      // test1キーでデータを取得する。
      var data = db.StringGet("test1");
      // JsonタイプのStringタイプをインスタンスに変換
      var node = JsonConvert.DeserializeObject<Node>(data);
      // NodeクラスのPrint関数を呼び出す。
      node.Print();

      // 任意のキーを押してください
      Console.WriteLine("Press Any key...");
      Console.ReadLine();
    }
  }
}


Redisデータベースでtest1のkey値でJsonタイプのString値を取得した後、Nodeインスタンスで変換しました。

結果はPrint関数を呼び出すと上で入力したTestの値がコンソール出力します。


次はRedisで使えるListとMap、SortedSetのデータタイプです。

using System;
using StackExchange.Redis;

namespace ConsoleApp1
{
  class Program
  {
    // 実行関数
    static void Main(string[] args)
    {
      // redis接続する。
      ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
      {
        EndPoints = { "192.168.1.200:6379" }
      });
      // 基本データベース取得
      var db = redis.GetDatabase();

      // Listタイプの右からPush
      db.ListRightPush("list", "1");
      // Listタイプの左からPush
      db.ListLeftPush("list", "2");
      // 2,1
      db.ListSetByIndex("list", 1, "3");
      // 2,3
      // Listタイプの左から出力
      Console.WriteLine(db.ListLeftPop("list"));
      Console.WriteLine(db.ListLeftPop("list"));

      // 改行
      Console.WriteLine();
      // Hashタイプのkey-value値を入力
      db.HashSet("map", "a", "1");
      db.HashSet("map", "b", "2");
      db.HashSet("map", "c", "3");
      // {{"a","1"},{"b","2"},{"c","3"}}

      // mapのbキーで出力
      Console.WriteLine(db.HashGet("map", "b"));

      // 改行
      Console.WriteLine();
      // SortedSetタイプの値を入力
      db.SortedSetAdd("SortedSet", "aaa", 1);
      db.SortedSetAdd("SortedSet", "bbb", 0);

      // 入力順番でsort
      foreach(var sort in db.SortedSetScan("SortedSet"))
      {
        // コンソール出力
        Console.WriteLine(sort);
      }
      // 改行
      Console.WriteLine();
      // Score順番でsort
      foreach (var sort in db.SortedSetRangeByRank("SortedSet"))
      {
        // コンソール出力
        Console.WriteLine(sort);
      }
      // 改行
      Console.WriteLine();
      // aaaのSocre
      Console.WriteLine(db.SortedSetScore("SortedSet", "aaa"));

      // 任意のキーを押してください
      Console.WriteLine("Press Any key...");
      Console.ReadLine();
    }
  }
}


上はRedisでlistとmap、SortedSetで使えるタイプです。


実は私はよく使わないタイプです。

Redisプログラムのアルゴリズムが悪く思わないですが、Redisデータベースの性能に関するボトルネックやアルゴリズムの性能がC#の基本ListやDictionaryよりもっと良いと思わないので、可能ならデータをそのままに取得してプログラム内で処理することをよく使います。

私がまだ、Redisの経験が多くないので正確に分かりないですね。


ここまでC#でRedisのデータベースを接続して使い方に関する説明でした。


ご不明なところや間違いところがあればコメントしてください。

最新投稿