您的位置:首页 > 游戏 > 手游 > C#操作redis(StackExchange.Redis)

C#操作redis(StackExchange.Redis)

2024/11/19 0:25:29 来源:https://blog.csdn.net/zhang8593/article/details/141590070  浏览:    关键词:C#操作redis(StackExchange.Redis)

C#操作redis
入门步骤:
安装redis–安装可视化软件RedisDesktopManager–C#操作redis
前两步软件的安装教程很多,这里不赘述。

一、类库的选择
在C#中使用Redis,一般有两种方式:

1、ServiceStack.Redis,据说是Redis官方推荐使用的驱动类库,但是是收费的。
2、StackExchange.Redis,可能性能要比ServiceStack.Redis差点,但是是免费的。

经过多方调研,我选用StackExchange.Redis来实现Redis操作,可找到的资料也更多。

二、添加StackExchange.Redis引用
想要在C#中使用Redis,首先得要有个Redis支持的C#版的驱动。

通过网络下载或nuget安装,得到Redis相关的dll,添加到项目中引用。这里介绍下通过NuGet方式添加

第一步:在项目中右键,选择管理NuGet管理包

第二步:搜索StackExchange.Redis添加,我这里已经添加过了所以没有添加按钮
注意.net framework的版本要相适应

通过这两步,会在项目中自动添加StackExchange.Redis引用
有需要的可以自行添加Newtonsoft.Json引用
补充完整后引用如图

三、利用StackExchange.Redis对数据库进行增删查改
论坛里有不少教程,都是给出RedisHelper类,可自己调用这样的用法,如下面几篇文章
https://blog.csdn.net/u011301348/article/details/105215016
https://blog.csdn.net/wanlong360599336/article/details/46771477
https://blog.csdn.net/weixin_30892037/article/details/98005759
https://blog.csdn.net/yangwohenmai1/article/details/93536539

对我而言,更想学数据库连接,写入,增删查改的具体方法,下面的原文连接很友好。
https://blog.csdn.net/kingshown_WZ/article/details/89603057

我这里在原文程序的基础上扩展功能,对redis各种数据类型的操作做了完整补充。程序结构在上图中可以看到。

1、新建控制台程序
同上步操作添加Nuget包

2、添加UserInfoDto.cs用户实体

public class UserInfoDto
    {
        public int Id { get; set; }
        public string StaffId { get; set; }
        public string StaffName { get; set; }
        public string Password { get; set; }
        public System.DateTime LastLoginTime { get; set; } 
    }

3、添加Redis数据库辅助操作类RedisHelper.cs
注意:private static readonly ConfigurationOptions ConfigurationOptions = ConfigurationOptions.Parse(“127.0.0.1:6379,password=123456”);
设置连接数据库的IP、端口号和密码,若没有设置密码可去掉后半句。

class RedisHelper
    {
        private static readonly ConfigurationOptions ConfigurationOptions = ConfigurationOptions.Parse("127.0.0.1:6379,password=123456");
        private static readonly object Locker = new object();
        private static ConnectionMultiplexer _redisConn;
 
        /// <summary>
        /// 单例获取
        /// </summary>
        public static ConnectionMultiplexer RedisConn
        {
            get
            {
                if (_redisConn == null)
                {
                    // 锁定某一代码块,让同一时间只有一个线程访问该代码块
                    lock (Locker)
                    {
                        if (_redisConn == null || !_redisConn.IsConnected)
                        {
                            _redisConn = ConnectionMultiplexer.Connect(ConfigurationOptions);
                        }
                    }
                }
                return _redisConn;
            }
        }
    }

4、 添加Redis数据库业务实现类RedisDemo.cs
这部分程序是操作数据库的主要部分
下面有对string、Hash、List、Set、SortedSet五种类型的基本操作
备注是自己加的,也比较详细,有什么问题欢迎大家指出

class RedisDemo
    {
        //键值对
        public static void StringTest()
        {
            // Using:定义了一个范围,等范围结束以后进行资源的释放,结束后调用Dispose()
            using (ConnectionMultiplexer conn = RedisHelper.RedisConn)
            {
                //测试0,文件夹下入数据
                string key0 = "StringTest:";
 
                //默认为db0
                //括号内可填写1-15,如var db2 = conn.GetDatabase(2);
                var db = conn.GetDatabase(); //在Redis中获得与数据库的交互式连接
 
                db.StringSet(key0+"num", "138");
                db.StringSet(key0 + "time", DateTime.Now.ToString());
                var num = db.StringGet("StringTest:num");
                Console.WriteLine(num);
 
                //测试1,写入数据,读取数据
                string key = "StringTest";
                if (db.KeyExists(key))
                    db.KeyDelete(key);
 
                db.StringSet(key, "1008611");
                var value = db.StringGet(key);
                Console.WriteLine(value);
 
                //测试2,获取当前时间
                string key2 = "StringTest2";
 
                //如果key已经存在并且是字符串,则此命令将值附加在字符串的末尾
                //如果key不存在,则会创建它并将其设置为空字符串,类似于SET
                //if (db.KeyExists(key2))
                //     db.KeyDelete(key2);
                //db.StringAppend(key2, DateTime.Now.ToString());
 
                db.StringSet(key2, DateTime.Now.ToString());
                Console.WriteLine(db.StringGet(key2));
 
                //测试3,控制台写入
                string value3 = Console.ReadLine();
                Console.WriteLine("value3=" + value3);
                string key3 = "StringTest3";
                db.StringSet(key3, value3);
                Console.WriteLine(db.StringGet(key3));
 
                // 测试4,批量读写数据
                // KeyValuePair<RedisKey, RedisValue>[] values
                //以KeyValuePair数组形式批量写入
                var keyvp1 = new KeyValuePair<RedisKey, RedisValue>("name1", "Jhon");
                var keyvp2 = new KeyValuePair<RedisKey, RedisValue>("name2", "Lilei");
                var keyvp3 = new KeyValuePair<RedisKey, RedisValue>("name3", "Jim");
                KeyValuePair<RedisKey, RedisValue>[] values = { keyvp1, keyvp2, keyvp3 };
                db.StringSet(values);
 
                //批量读取key的值
                RedisKey[] rkarray = { "name1", "name2", "name3" };
                RedisValue[] rvarray = db.StringGet(rkarray);
                foreach (var item in rvarray)
                {
                    Console.WriteLine(item);
                }
 
                //测试5,将对象以Json格式存入string中
                db.StringSet("myfirstname", "Li");
                string str = db.StringGet("myfirstname");
                db.StringSet("mylastname", "Shuxian", TimeSpan.FromSeconds(20));//设置时间,20s后过期。
                str = db.StringGet("mylastname");
 
                //创建对象
                UserInfoDto User1 = new UserInfoDto()
                {
                    Id = 97,
                    LastLoginTime = DateTime.Now,
                    Password ="xxxxxx",
                    StaffId = "xxxxxx",
                    StaffName = "xxx"
                };
                
                string user1_Json = JsonConvert.SerializeObject(User1);//序列化,对象转化为Json格式
                db.StringSet("stringtest_Json", user1_Json);
 
                string user1_JsonResult = db.StringGet("stringtest_Json");//读取Json格式的key
                Console.WriteLine(user1_JsonResult);
 
                User1 = JsonConvert.DeserializeObject<UserInfoDto>(user1_JsonResult);//反序列化
                Console.WriteLine(User1);
            }
        }
 
        //Hash类型
        //string类型的域和值的映射表
        //常用来存储对象信息
        public static void HashTest()
        {
            // C# 泛型集合 List<数据类型>
            List<UserInfoDto> list = new List<UserInfoDto>();
            for (int i = 0; i < 11; ++i)
            {
                list.Add(new UserInfoDto()
                {
                    Id = i,
                    LastLoginTime = DateTime.Now,
                    Password = "password_" + i.ToString(),
                    StaffId = "StaffId_" + i.ToString(),
                    StaffName = "StaffName_" + i.ToString()
                });
            }
 
            using (ConnectionMultiplexer conn = RedisHelper.RedisConn)
            {
                //测试1:对象序列化为JSON字符串写入
                string key = "HashSetTest";
                var db = conn.GetDatabase();
                if (db.KeyExists(key))
                    db.KeyDelete(key);
 
                //string listKey = IdentityMap.CreateKey<UserInfoDto>();
                HashEntry[] items = new HashEntry[list.Count];
 
                for (int i = 1; i < list.Count; i++)
                {
                    // 将指定的对象序列化为JSON字符串。
                    string json = JsonConvert.SerializeObject(list[i]);
                    db.HashSet(key, list[i].Id, json);
 
                    Console.WriteLine(db.HashGet(key, list[i].Id));
                    Console.WriteLine(db.HashGet(key, "StaffId"));
 
                    db.HashDelete(key, "password");//无效
                }
 
                //测试2:将对象以plain text格式希尔
                string key2 = "HashSetTest2";
                //if (db.KeyExists(key2))
                //    db.KeyDelete(key2);
                //为哈希表的每一个域设值
                //bool HashSet(RedisKey key, RedisValue hashField, RedisValue value)
                for (int i = 1; i < 5; i++)
                {
                    key2 = "HashSetTest" + list[i].Id.ToString();
                    if (db.KeyExists(key2))
                        db.KeyDelete(key2);
 
                    db.HashSet(key2, "ID", list[i].Id);
                    db.HashSet(key2, "password", list[i].Password);
                    db.HashSet(key2, "StaffId", list[i].StaffId);
                    db.HashSet(key2, "StaffName", list[i].StaffName);
                    db.HashSet(key2, "LastLoginTime", DateTime.Now.ToString());
 
                    Console.WriteLine(db.HashGet(key2, list[i].Id));
 
                    //删除key中的域
                    db.HashDelete(key2, "password");
                }
 
                //测试3:删除key中的域
                string key3 = "HashDeletTest";
                db.HashSet(key3, "ID", 123456111111111111);
                db.HashSet(key3, "password", "xxxxxx");
                db.HashSet(key3, "StaffId", "xxxxxxxxxx");
                db.HashDelete(key3, "password");
 
            }
            Console.ReadLine();
        }
 
        //列表数据类型
        //列表按照插入顺序排序,可将一个元素插入列表的头部和尾部
        public static void ListTest()
        {
            using (ConnectionMultiplexer conn = RedisHelper.RedisConn)
            {
                string key = "ListTest";
                var db = conn.GetDatabase();
                if (db.KeyExists(key))
                    db.KeyDelete(key);
 
                for (int i = 0; i < 10; i++)
                {
                    // 将指定的值插入存储在key的列表的开头 ,相当于栈
                    // 如果键不存在,则在执行推入操作之前将其创建为空列表
                    db.ListLeftPush(key, "left_" + i.ToString());
                    db.ListRightPush(key, "right_" + i.ToString());
                }
                Console.WriteLine("写入完成");
                var length = db.ListLength("list"); //读出list的长度
                Console.WriteLine(length);
 
                var str = db.ListLeftPop(key); //从顶部拿出数据
                Console.WriteLine(str);
                str = db.ListRightPop(key); //从底部拿出数据
                Console.WriteLine(str);
 
                //返回存储在键列表中指定的元素。
                //偏移量start和stop是从零开始的索引,0是列表的第一个元素(列表的头),1是下一个元素,依此类推。
                //这些偏移也可以是负数,表示从列表。用于示例,-1是列表的最后一个元素,-2是倒数第二个元素,依此类推。
                //注意,如果您有一个从0到100的数字列表,LRANGE list 0 10将返回11个元素,也就是说,包含最右边的项。
                var list = db.ListRange(key, 0, 4);
                foreach (var item in list)
                {
                    Console.WriteLine(item);
                }
 
                str = db.ListRemove(key, "left_2"); //删除list中的单个数值
                Console.WriteLine(str);
 
                str = db.ListInsertAfter(key, list[3], "After"); //在某一位置后插入数据
                Console.WriteLine(str);
                str = db.ListInsertBefore(key, list[3], "Before"); //在某一位置前插入数据
                Console.WriteLine(str);
 
                //删除list中的数据
                while (db.ListLength(key) != 0)
                {
                    //从redis数据库弹出List里的数据
                    //var str = db.ListRightPop(key);
                    //Console.WriteLine(str);
                }
            }
        }
 
        //Set是String类型的无序集合
        public static void SetTest()
        {
            List<UserInfoDto> list = new List<UserInfoDto>();
            DateTime dt = DateTime.Now;
            for (int i = 1; i < 4; i++)
            {
                list.Add(new UserInfoDto()
                {
                    Id = i,
                    LastLoginTime = dt,
                    Password = "password" + i.ToString(),
                    StaffId = "StaffId_" + i.ToString(),
                    StaffName = "StaffName_" + i.ToString()
                });
            }
 
            using (ConnectionMultiplexer conn = RedisHelper.RedisConn)
            {
                //测试1
                string key = "SetTest:";
                var db = conn.GetDatabase();
                db.KeyDelete(key);
                //string listKey = IdentityMap.CreateKey<UserInfoDto>();
                HashEntry[] items = new HashEntry[list.Count];
                for (int i = 0; i < list.Count; i++)
                {
                    string json = JsonConvert.SerializeObject(list[i]);
                    db.KeyDelete(key + list[i].Id.ToString());
 
                    // 以Json格式存储
                    db.SetAdd(key + list[i].Id.ToString(), json);
 
                    //以string格式存储
 
                    db.SetAdd(key + list[i].Id.ToString() + ":Id", list[i].Id);
                    db.SetAdd(key + list[i].Id.ToString() + ":password", list[i].Password);
                    db.SetAdd(key + list[i].Id.ToString() + ":StaffId", list[i].StaffId);
                    db.SetAdd(key + list[i].Id.ToString() + ":StaffName", list[i].StaffName);
                    db.SetAdd(key + list[i].Id.ToString() + ":LastLoginTime", DateTime.Now.ToString());
 
                    //SSCAN命令用于对集合进行增量迭代。
                    //注意:要通过游标恢复迭代,请将原始的可枚举或枚举数转换为IScanningCursor。
                    var result = db.SetScan(key, "*password99*").FirstOrDefault();
                    Console.WriteLine(result);
                }
                Console.WriteLine("Complete test1!");
 
 
                //测试2,set命令
                //冒号后可在目录下创建文件夹
                string key2 = "citys:";
                db.KeyDelete(key2);
                RedisValue[] citys1 = { "北京", "上海", "广州" };
                db.SetAdd(key2 + "1", citys1);
                RedisValue[] citys2 = { "成都", "重庆", "西安" };
                db.SetAdd(key2 + "2", citys2);
                RedisValue[] citys3 = { "太原", "大连", "徐州" };
                db.SetAdd(key2 + "3", citys3);
                db.SetMove("citys:2", "citys:1", "成都");
                db.SetRemove("citys:3", "大连");
            }
        }
 
        //有序集合
        //每个集合元素都有一个对应的double类型的分数
        public static void SortedSet()
        {
            List<UserInfoDto> list = new List<UserInfoDto>();
            for (int i = 1; i < 5; i++)
            {
                list.Add(new UserInfoDto()
                {
                    Id = i,
                    LastLoginTime = DateTime.Now,
                    Password = "password" + i.ToString(),
                    StaffId = "StaffId_" + i.ToString(),
                    StaffName = "StaffName_" + i.ToString()
                });
            }
 
            using (ConnectionMultiplexer conn = RedisHelper.RedisConn)
            {
                //测试2
                var db = conn.GetDatabase();
                string key = "SortedSetTest:";
                db.KeyDelete("SortedSetTest");
 
                foreach (var item in list)
                {
                    string json = JsonConvert.SerializeObject(item);
                    db.KeyDelete(key + item.Id.ToString());
                    db.KeyDelete("SortedSetTest" + item.Id.ToString() + ":name");
                    db.KeyDelete("SortedSetTest" + item.Id.ToString() + ":StaffId");
                    //db.SetAdd(key + list[i].Id.ToString(), json);
                    db.SortedSetAdd(key + item.Id.ToString() + ":name", item.StaffName, item.Id);
                    db.SortedSetAdd(key + item.Id.ToString() + ":StaffId", item.StaffName, item.Id);
                }
 
                Console.WriteLine("写入完成");
                Console.WriteLine("读取两条记录");
 
                var result = db.SortedSetRangeByRank(key, 1, 3);
                for (int i = 0; i < result.Length; i++)
                {
                    Console.WriteLine(result[i]);
                }
 
                var result2 = db.SortedSetRangeByRankWithScores(key, 0, -1, Order.Descending);
 
                var result3 = db.SortedSetScan(key, "*99*", 10).ToList();
                for (int i = 0; i < result3.Count; i++)
                {
                    Console.WriteLine(result3[i]);
                }
                Console.ReadLine();
 
                //测试1
                string key0 = "SortedSetTest0";
                var db2 = conn.GetDatabase(2);
                var rep = db2.SortedSetAdd(key0, "北京", 6521);
                Console.WriteLine(rep);
 
                var city1 = new SortedSetEntry("北京", 4451);
                var city2 = new SortedSetEntry("上海", 3400);
                var city3 = new SortedSetEntry("广州", 3459);
 
                var city4 = new SortedSetEntry("成都", 3300);
                var city5 = new SortedSetEntry("太原", 2459);
                SortedSetEntry[] citys = { city1, city2, city3, city4, city5 };
                var rep2 = db2.SortedSetAdd(key0, citys);
                Console.WriteLine(rep2);
 
                var res = db2.SortedSetRangeByRank(key0, 1, 3);
                for (int i = 0; i < res.Length; i++)
                {
                    Console.WriteLine(res[i]);
                }
            }
        }
    }

5、 Program.cs类
主程序,对上面各部分的功能进行测试

class Program
    {
        static void Main(string[] args)
        {
            //字符串            
            RedisDemo.StringTest();
 
            //Hash
            //RedisDemo.HashTest();
 
            //List
            //RedisDemo.ListTest();
            //Console.ReadKey();
 
            //Set
            //RedisDemo.SetTest();
 
            //SortedSet
            //RedisDemo.SortedSet();
        }        
    }

这部分就不一一展示测试结果了

其他功能测试
添加定时器,定时往redis数据库中写入数据,并在控制台显示

static int i = 1;
        static void Main2(string[] args)
        {
            ConnectionMultiplexer conn = RedisHelper.RedisConn;
            string key = "Data Storage";
            var db = conn.GetDatabase(3);
            if (db.KeyExists(key))
                db.KeyDelete(key);
 
            System.Timers.Timer aTimer = new System.Timers.Timer();
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            // Set the Interval to 5 seconds.
            aTimer.Interval = 2000;
            aTimer.Enabled = true;
 
            Console.WriteLine("Press /'q/' to quit the sample.");
            while (Console.Read() == 'q')
            {
                Console.WriteLine("结束!");
            }
 
            void OnTimedEvent(object source, ElapsedEventArgs e)
            {
                Console.WriteLine("Hello World!");
                db.ListLeftPush(key, "left_" + i.ToString());
                i++;
                var str = db.ListGetByIndex(key, 0); //从顶部拿出数据
                Console.WriteLine(str);
            }
        }

控制台输出

可视化中查看数据库的写入

四、注意
1、程序运行前启动redis服务器
打开可视化工具,若redis设置了密码,要输入密码才可打开数据库。

2、选择数据写入的数据库
redis默认16个数据库,如何选择将数据写入哪个数据库呢?

var db = conn.GetDatabase(); //在Redis中获得与数据库的交互式连接
该语句连接数据库,括号为空默认写入db0
var db = conn.GetDatabase(3);即可将数据写入db3数据库

3、在数据库内添加文件夹存储
开始时将key全部写入db0中,数据存储凌乱,后来找到了添加文件夹的方法

具体操作:key值后加冒号
string key = "SetTest:";
                var db = conn.GetDatabase();
                db.KeyDelete(key);
                //string listKey = IdentityMap.CreateKey<UserInfoDto>();
                HashEntry[] items = new HashEntry[list.Count];
                for (int i = 0; i < list.Count; i++)
                {
                    string json = JsonConvert.SerializeObject(list[i]);
                    db.KeyDelete(key + list[i].Id.ToString());
 
                    // 以Json格式存储
                    db.SetAdd(key + list[i].Id.ToString(), json);
 
                    //以string格式存储
 
                    db.SetAdd(key + list[i].Id.ToString() + ":Id", list[i].Id);
                    db.SetAdd(key + list[i].Id.ToString() + ":password", list[i].Password);
                    db.SetAdd(key + list[i].Id.ToString() + ":StaffId", list[i].StaffId);
                    db.SetAdd(key + list[i].Id.ToString() + ":StaffName", list[i].StaffName);
                    db.SetAdd(key + list[i].Id.ToString() + ":LastLoginTime", DateTime.Now.ToString());

对应的文件夹添加情况如图

string key = “SetTest:”; 该key值加了冒号,成为文件夹
子文件夹也是,通过加冒号添加文件夹。
下文中也有添加文件夹的说明,大家可多方面参考学习
https://blog.csdn.net/a6864657/article/details/103863349

五、Redis高级功能
redis还有事件、消息队列、同步异步等高级功能,找了找其他参考,有以下几篇文章可参考,本人未进行试验。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/zhiqingcn/article/details/137996641

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com