【后端】.NET Core API框架搭建(7) --配置使用Redis

目录

1.添加包

[2. 连接配置](#2. 连接配置)

2.1.连接字符串

2.2.连接对象

3.仓储配置

3.1.仓储实现

3.2.仓储接口

4.获取配置和注册

4.1.添加配置获取方法

4.2.注册

5.简单使用案例

5.1.实现

5.2.接口

5.3.控制器


在 .NET Core 应用程序中使用 Redis 有许多显著的好处,Redis 是一种高性能的键值存储系统,通常被用作数据库、缓存和消息代理。增强的性能表现以及更高的灵活性和可靠性,适用于从简单的缓存方案到复杂的分布式应用架构。

1.添加包

添加 StackExchange.Redis 和 Microsoft.Extensions.Caching.StackExchangeRedis 包。

2. 连接配置

2.1.连接字符串

dbsettings.json文件添加 Redis连接配置

cs 复制代码
 //Redis配置
 "RedisSettings": {
   "RedisConnStr": "ip地址:端口,password=密码,abortConnect=false"
 },

2.2.连接对象

cs 复制代码
namespace Frame3_DataRepository.RedisRepository
{
    public class RedisOptions
    {
        /// <summary>
        /// 连接地址
        /// </summary>
        public string RedisConnStr { get; set; }
    }
}

案例如下

3.仓储配置

3.1.仓储实现

为 Redis 添加仓储方便使用。

cs 复制代码
using Frame6_LibraryUtility;
using StackExchange.Redis;
using System.Text.Json;

namespace Frame3_DataRepository.RedisRepository
{
    public class RedisRepository : BaseServiceSingleton, IRedisRepository
    {
        private readonly IConnectionMultiplexer _redis;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="redis"></param>
        public RedisRepository(IConnectionMultiplexer redis)
        {
            _redis = redis;
        }

        /// <summary>
        /// 设置键值对
        /// </summary>
        public async Task<bool> SetAsync<T>(string key, T value, int dbNumber = 1, TimeSpan? expiry = null)
        {
            var database = _redis.GetDatabase(dbNumber);
            var json = JsonSerializer.Serialize(value);
            return await database.StringSetAsync(key, json, expiry);
        }

        /// <summary>
        /// 获取值
        /// </summary>
        public async Task<T> GetAsync<T>(string key, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            var json = await database.StringGetAsync(key);
            return json.IsNullOrEmpty ? default : JsonSerializer.Deserialize<T>(json);
        }

        /// <summary>
        /// 删除键
        /// </summary>
        public async Task<bool> RemoveAsync(string key, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            return await database.KeyDeleteAsync(key);
        }

        /// <summary>
        /// 检查键是否存在
        /// </summary>
        public async Task<bool> ExistsAsync(string key, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            return await database.KeyExistsAsync(key);
        }

        /// <summary>
        /// 更新键值
        /// </summary>
        public async Task<bool> UpdateAsync<T>(string key, T value, int dbNumber = 1, TimeSpan? expiry = null)
        {
            if (!await ExistsAsync(key, dbNumber))
                return false;

            return await SetAsync(key, value, dbNumber, expiry);
        }

        /// <summary>
        /// 搜索匹配的键
        /// </summary>
        public async Task<IEnumerable<string>> SearchKeysAsync(string pattern, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            var endpoints = _redis.GetEndPoints();
            var server = _redis.GetServer(endpoints.First());
            var keys = server.Keys(pattern: $"*{pattern}*");
            return keys.Select(k => k.ToString());
        }

        /// <summary>
        /// 按模式删除键
        /// </summary>
        public async Task<long> RemoveByPatternAsync(string pattern, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            var keys = await SearchKeysAsync(pattern, dbNumber);
            if (!keys.Any())
                return 0;

            return await database.KeyDeleteAsync(keys.Select(k => (RedisKey)k).ToArray());
        }

        /// <summary>
        /// 设置哈希字段值
        /// </summary>
        public async Task<bool> SetHashAsync<T>(string hashKey, string field, T value, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            var json = JsonSerializer.Serialize(value);
            return await database.HashSetAsync(hashKey, field, json);
        }

        /// <summary>
        /// 获取哈希字段值
        /// </summary>
        public async Task<T> GetHashAsync<T>(string hashKey, string field, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            var json = await database.HashGetAsync(hashKey, field);
            return json.IsNullOrEmpty ? default : JsonSerializer.Deserialize<T>(json);
        }

        /// <summary>
        /// 删除哈希字段
        /// </summary>
        public async Task<bool> RemoveHashAsync(string hashKey, string field, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            return await database.HashDeleteAsync(hashKey, field);
        }

        /// <summary>
        /// 获取所有哈希字段
        /// </summary>
        public async Task<Dictionary<string, T>> GetAllHashAsync<T>(string hashKey, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            var entries = await database.HashGetAllAsync(hashKey);
            return entries.ToDictionary(
                x => x.Name.ToString(),
                x => JsonSerializer.Deserialize<T>(x.Value)
            );
        }

        /// <summary>
        /// 获取所有哈希字段 -- List返回
        /// </summary>
        public async Task<List<T>> GetAllListHashAsync<T>(string hashKey, int dbNumber = 1)
        {
            var database = _redis.GetDatabase(dbNumber);
            var entries = await database.HashGetAllAsync(hashKey);
            var list = new List<T>();
            foreach (var item in entries)
            {
                list.Add(JsonSerializer.Deserialize<T>(item.Value));
            }
            return list;
        }
    }
}

案例如下

3.2.仓储接口

cs 复制代码
namespace Frame3_DataRepository.RedisRepository
{
    public interface IRedisRepository
    {
        /// <summary>
        /// 设置键值对
        /// </summary>
        Task<bool> SetAsync<T>(string key, T value, int dbNumber, TimeSpan? expiry = null);

        /// <summary>
        /// 获取值
        /// </summary>
        Task<T> GetAsync<T>(string key, int dbNumber);

        /// <summary>
        /// 删除键
        /// </summary>
        Task<bool> RemoveAsync(string key, int dbNumber);

        /// <summary>
        /// 检查键是否存在
        /// </summary>
        Task<bool> ExistsAsync(string key, int dbNumber);

        /// <summary>
        /// 更新键值
        /// </summary>
        Task<bool> UpdateAsync<T>(string key, T value, int dbNumber, TimeSpan? expiry = null);

        /// <summary>
        /// 搜索匹配的键
        /// </summary>
        Task<IEnumerable<string>> SearchKeysAsync(string pattern, int dbNumber);

        /// <summary>
        /// 按模式删除键
        /// </summary>
        Task<long> RemoveByPatternAsync(string pattern, int dbNumber);

        /// <summary>
        /// 设置哈希字段值
        /// </summary>
        Task<bool> SetHashAsync<T>(string hashKey, string field, T value, int dbNumber);

        /// <summary>
        /// 获取哈希字段值
        /// </summary>
        Task<T> GetHashAsync<T>(string hashKey, string field, int dbNumber);

        /// <summary>
        /// 删除哈希字段
        /// </summary>
        Task<bool> RemoveHashAsync(string hashKey, string field, int dbNumber);

        /// <summary>
        /// 获取所有哈希字段
        /// </summary>
        Task<Dictionary<string, T>> GetAllHashAsync<T>(string hashKey, int dbNumber);

        /// <summary>
        /// 获取所有哈希字段 -- List返回
        /// </summary>
        Task<List<T>> GetAllListHashAsync<T>(string hashKey, int dbNumber);
    }
}

案例如下

4.获取配置和注册

获取连接字符串、注册Redis实例和仓储

4.1.添加配置获取方法

cs 复制代码
using Microsoft.Extensions.Configuration;
 
namespace Frame4_LibraryCore.BaseConfig
{
    /// <summary>
    /// 全局配置
    /// </summary>
    public static class Config
    {
        /// <summary>
        /// 从指定的 JSON 配置文件中读取配置,并反序列化为指定类型
        /// </summary>
        /// <typeparam name="T">目标配置类型(如 RedisSettings、DatabaseSettings 等)</typeparam>
        /// <param name="fileName">JSON 配置文件名(如 "appsettings.json")</param>
        /// <param name="sessions">配置节点名称(如 "RedisSettings")</param>
        /// <returns>返回绑定后的强类型配置对象</returns>
        public static T GetSetting<T>(string fileName, string sessions)
        {
            //创建 ConfigurationBuilder 实例,用于构建配置
            var builder = new ConfigurationBuilder()
                //设置配置文件的基础路径为当前程序运行目录
                .SetBasePath(Directory.GetCurrentDirectory())
                //添加 JSON 文件作为配置源:
                //- fileName: 指定要加载的 JSON 文件
                //- optional: false 表示文件必须存在,否则抛出异常
                //- reloadOnChange: true 表示文件修改时自动重新加载
                .AddJsonFile(fileName, optional: false, reloadOnChange: true);
 
            //构建配置对象(IConfigurationRoot)
            IConfigurationRoot config = builder.Build();
 
            //获取指定配置节点(sessions),并将其反序列化为类型 T
            var conn = config.GetSection(sessions).Get<T>();
 
            //返回反序列化后的配置对象
            return conn;
        }
    }
}

案例如下

4.2.注册

添加注册方法方便程序注册

cs 复制代码
using Frame4_LibraryCore.BaseConfig;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;

namespace Frame3_DataRepository.RedisRepository
{
    /// <summary>
    /// Redis扩展方法静态类,用于配置Redis相关服务
    /// </summary>
    public static class RedisExtension
    {
        /// <summary>
        /// 扩展方法:向IServiceCollection添加Redis仓储相关服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <returns>配置后的服务集合</returns>
        public static IServiceCollection AddRedisRepository(this IServiceCollection services)
        {
            // 从配置文件"dbsettings.json"的"RedisSettings"节点读取Redis配置
            var redisConn = Config.GetSetting<RedisOptions>("dbsettings.json", "RedisSettings");

            // 添加StackExchange.Redis缓存服务(基于IDistributedCache接口)
            services.AddStackExchangeRedisCache(options =>
            {
                // 配置Redis连接字符串(从redisConn对象获取)
                options.Configuration = redisConn.RedisConnStr;

                // 设置实例名称前缀(用于区分不同应用的缓存键)
                // 例如:设置"MyApp_"前缀后,实际缓存键会变成"MyApp_UserCache"
                options.InstanceName = "MyApp_"; // 所有缓存键自动添加此前缀
            });

            // 直接注册ConnectionMultiplexer为单例服务(Redis连接复用)
            // ConnectionMultiplexer是线程安全的,适合单例模式
            services.AddSingleton<IConnectionMultiplexer>(_ =>
                ConnectionMultiplexer.Connect(redisConn.RedisConnStr));

            // 注册Redis仓储实现(IRedisRepository接口对应RedisRepository实现类)
            // 使用单例模式注册,因为RedisRepository内部使用线程安全的ConnectionMultiplexer
            services.AddSingleton<IRedisRepository, RedisRepository>();

            // 返回配置好的服务集合以支持链式调用
            return services;
        }
    }
}

案例如下

新增好注册方法后即可在 Program 或 Startup 中注册。

cs 复制代码
  //注册Redis服务
  builder.Services.AddRedisRepository();

案例如下

5.简单使用案例

下面是 实现、接口和控制器的使用案例

5.1.实现

cs 复制代码
using Frame1_Service.IService.Product;
using Frame2_DataModel.MongoEntity.Product;
using Frame3_DataRepository.RedisRepository;
using Frame6_LibraryUtility;

namespace Frame1_Service.Service.Product
{
    public class RedisSvr : BaseService, IRedisSvr
    {
        /// <summary>
        /// RedisKey
        /// </summary>
        private const string ProductsKey = "products";
        /// <summary>
        /// Redis缓存
        /// </summary>
        private readonly IRedisRepository _redisRepository;
        /// <summary>
        /// redis数据库编号
        /// </summary>
        private int dBNumber = 1;

        public RedisSvr(IRedisRepository redisRepository)
        {
            _redisRepository = redisRepository;
        }

        /// <summary>
        /// 添加数据-键值对   30后自动删除,可用于分布式锁
        /// </summary>
        /// <returns></returns>
        public async Task<string> CacheCatalogItemsAsync()
        {
            var Gid = Guid.NewGuid().ToString();

            // 设置缓存,过期时间30秒
            var Ref = await _redisRepository.SetAsync(ProductsKey, Gid, dBNumber, TimeSpan.FromSeconds(30));

            if (!Ref)
            {
                return null;
            }
            return Gid;
        }

        /// <summary>
        /// 查询数据 获取键值对
        /// </summary>
        /// <returns></returns>
        public async Task<string> GetRedisByIdAsync()
        {
            //redis测试查询set
            var list = await _redisRepository.GetAsync<string>(ProductsKey, dBNumber);

            return list;
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> IndertAsync(ProductEntity model)
        {
            var iRet = false;
            iRet = await _redisRepository.SetHashAsync(ProductsKey, model.Id, model, 2);

            return iRet;
        }

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public async Task<ProductEntity> GetRedisAsync(string key)
        {
            //redis测试查询set
            var list = await _redisRepository.GetHashAsync<ProductEntity>(ProductsKey, key, 2);

            return list;
        }

        /// <summary>
        /// 查询所有数据
        /// </summary>
        /// <returns></returns>
        public async Task<dynamic> GetAllRedisAsync()
        {
            //redis测试查询set
            var list = await _redisRepository.GetAllHashAsync<ProductEntity>(ProductsKey, 2);

            return list;
        }

        /// <summary>
        /// 查询所有数据集合显示
        /// </summary>
        /// <returns></returns>
        public async Task<dynamic> GetAllListRedisAsync()
        {
            //redis测试查询set
            var list = await _redisRepository.GetAllListHashAsync<ProductEntity>(ProductsKey, 2);

            return list;
        }

        /// <summary>
        /// 添加集合数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> IndertGatherAsync(List<ProductEntity> model)
        {
            var iRet = false;
            iRet = await _redisRepository.SetHashAsync(ProductsKey, Guid.NewGuid().ToString(), model, 3);

            return iRet;
        }

        /// <summary>
        /// 查询所有集合数据
        /// </summary>
        /// <returns></returns>
        public async Task<dynamic> GetGatherAllRedisAsync()
        {
            //redis测试查询set
            var list = await _redisRepository.GetAllHashAsync<List<ProductEntity>>(ProductsKey, 3);

            return list;
        }

    }
}

案例如下

5.2.接口

cs 复制代码
using Frame2_DataModel.MongoEntity.Product;

namespace Frame1_Service.IService.Product
{
    public interface IRedisSvr
    {
        Task<string> CacheCatalogItemsAsync();

        /// <summary>
        /// 查询数据 获取键值对
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<string> GetRedisByIdAsync();

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<bool> IndertAsync(ProductEntity model);

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<ProductEntity> GetRedisAsync(string key);

        /// <summary>
        /// 查询所有数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<dynamic> GetAllRedisAsync();

        /// <summary>
        /// 查询所有数据集合显示
        /// </summary>
        /// <returns></returns>
        Task<dynamic> GetAllListRedisAsync();

        /// <summary>
        /// 添加集合数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<bool> IndertGatherAsync(List<ProductEntity> model);

        /// <summary>
        /// 查询所有集合数据
        /// </summary>
        /// <returns></returns>
        Task<dynamic> GetGatherAllRedisAsync();
    }
}

案例如下

5.3.控制器

cs 复制代码
using Frame1_Service.IService.Product;
using Frame2_DataModel.MongoEntity.Product;
using Frame3_DataRepository.RedisRepository;
using Frame4_LibraryCore.BaseConfig;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.Mvc;

namespace DemoAPI.Controllers
{
    /// <summary>
    /// Redis测试控制器
    /// </summary>
    //[Authorize]// 保护整个控制器
    [Route("api/[controller]/[action]")]//标记路由地址规格
    [ApiController] // 标记该类为 API 控制器,启用一些默认的行为,如模型绑定、输入验证等
    [ApiExplorerSettings(GroupName = nameof(ApiVersionInfo.V1))]//设置控制器的API版本
    public class RedisTestController : BaseController
    {
        private readonly IRedisSvr _iRedisSvr;

        /// <summary>
        /// 注入
        /// </summary>
        /// <param name="iRedisSvr"></param>
        public RedisTestController(IRedisSvr iRedisSvr)
        {
            _iRedisSvr = iRedisSvr;
        }

        /// <summary>
        /// 添加数据-键值对   30后自动删除,可用于分布式锁
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<string> CacheCatalogItemsAsync() => await _iRedisSvr.CacheCatalogItemsAsync();

        /// <summary>
        /// 查询数据 获取键值对
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<string> GetRedisByIdAsync() => await _iRedisSvr.GetRedisByIdAsync();

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<bool> IndertAsync(ProductEntity model) => await _iRedisSvr.IndertAsync(model);

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ProductEntity> GetRedisAsync(string key) => await _iRedisSvr.GetRedisAsync(key);

        /// <summary>
        /// 查询所有数据
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<dynamic> GetAllRedisAsync() => await _iRedisSvr.GetAllRedisAsync();

        /// <summary>
        /// 查询所有数据集合显示
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<dynamic> GetAllListRedisAsync() => await _iRedisSvr.GetAllListRedisAsync();

        /// <summary>
        /// 添加集合数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<bool> IndertGatherAsync(List<ProductEntity> model) => await _iRedisSvr.IndertGatherAsync(model);

        /// <summary>
        /// 查询所有集合数据
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<dynamic> GetGatherAllRedisAsync() => await _iRedisSvr.GetGatherAllRedisAsync();
    }
}

案例如下

相关推荐
末央&17 小时前
【天机论坛】项目环境搭建和数据库设计
java·数据库
徒 花17 小时前
数据库知识复习07
数据库·作业
素玥17 小时前
实训5 python连接mysql数据库
数据库·python·mysql
jnrjian18 小时前
text index 查看index column index定义 index 刷新频率 index视图
数据库·oracle
瀚高PG实验室18 小时前
审计策略修改
网络·数据库·瀚高数据库
言慢行善18 小时前
sqlserver模糊查询问题
java·数据库·sqlserver
韶博雅18 小时前
emcc24ai
开发语言·数据库·python
有想法的py工程师19 小时前
PostgreSQL 分区表排序优化:Append Sort 优化为 Merge Append
大数据·数据库·postgresql
迷枫71219 小时前
达梦数据库的体系架构
数据库·oracle·架构
夜晚打字声19 小时前
9(九)Jmeter如何连接数据库
数据库·jmeter·oracle