【后端】.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();
    }
}

案例如下

相关推荐
秋秋棠2 小时前
MyBatis动态SQL实战:告别硬编码,拥抱智能SQL生成
java·数据库·sql·mybatis
清酒伴风(面试准备中......)2 小时前
Shardingsphere 在项目中的使用全流程
java·数据库·mysql·性能优化
Mr_Xuhhh5 小时前
窗口(6)-QMessageBox
c语言·开发语言·数据库·c++·qt
贰拾wan7 小时前
Redis的持久化-RDB
java·数据库·redis·缓存
KellenKellenHao8 小时前
Redis数据库基础与持久化部署
数据库·redis·缓存·持久化
秋秋棠10 小时前
MyBatis动态SQL全解析:五大核心标签实战指南
数据库·sql·mybatis
西京刀客10 小时前
软删除设计:为什么使用 deleted_at = ‘1970-01-01 00:00:00‘ 表示未删除?
数据库·1970-01-01·软删除·deleted_at
wjpwjpwjp083111 小时前
[MySQL基础3] 数据控制语言DCL和MySQL中的常用函数
数据库·笔记·后端·学习·mysql