1.项目框架(项目为Asp.Net Core3.1 WebApi项目,采用仓储模式)
2.配置文件配置(appsettings.json)
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "Redis": { "Default": { "Connection": "127.0.0.1:6379", "InstanceName": "local", "DefaultDb": 0 } }, "ConnectionStrings": { "redisTestDb": "Data Source=.;Initial Catalog=MyDatabase; User Id=sa;Password=pass02!" }, "AllowedHosts": "*" }
3.Redis.Common类库代码
首先nuget添加StackExchange.Redis
(1) RedisOption.cs代码
此类主要是Redis配置相关的
using System; using System.Collections.Generic; using System.Text; namespace Redis.Common { public class RedisOption { public string Connection { get; set; } public string InstanceName { get; set; } public int DefaultDb { get; set; } } }
(2)RedisHelper.cs
此类就是操作redis的,
using StackExchange.Redis; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Text; namespace Redis.Common { public class RedisHelper { private readonly RedisOption _option; private readonly ConcurrentDictionary<string, ConnectionMultiplexer> _connections; public RedisHelper(RedisOption option) { _option = option; _connections = new ConcurrentDictionary<string, ConnectionMultiplexer>(); } private ConnectionMultiplexer GetConnection() { return _connections.GetOrAdd(_option.InstanceName, p => ConnectionMultiplexer.Connect(_option.Connection)); } public IDatabase GetDatabase() { return GetConnection().GetDatabase(_option.DefaultDb); } /// <summary> /// 设置key的过期时间 /// </summary> /// <param name="key"></param> /// <param name="time"></param> /// <returns></returns> public bool Expire(string key, TimeSpan time) { try { GetDatabase().KeyExpire(key, time); return true; } catch (Exception e) { Console.WriteLine(e); return false; } } public TimeSpan GetExpire(string key) { try { // ReSharper disable once PossibleInvalidOperationException TimeSpan time = GetDatabase().KeyTimeToLive(key).Value; return time; } catch (Exception e) { Console.WriteLine(e); throw; } } /// <summary> /// 写入缓存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public bool Set(string key, RedisValue value) { bool result = false; try { result = GetDatabase().StringSet(key, value); } catch (Exception e) { Console.WriteLine(e); throw; } return result; } /// <summary> /// 写入缓存并设置过期时间 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expireTime"></param> /// <returns></returns> public bool Set(string key, string value, TimeSpan expireTime) { Console.WriteLine($"过期时间:{expireTime}"); bool result = false; try { result = GetDatabase().StringSet(key, value); GetDatabase().KeyExpire(key, expireTime); } catch (Exception e) { Console.WriteLine(e); throw; } return result; } public RedisValue Get(string key) { var value = key == null ? (RedisValue)"" : GetDatabase().StringGet(key); return value; } /// <summary> /// 递增 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long Incr(string key, long value) { return GetDatabase().StringIncrement(key, value); } public long Incr(string key) { return GetDatabase().StringIncrement(key); } /// <summary> /// 递减 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long Decr(string key, long value) { return GetDatabase().StringIncrement(key, value); } public long Decr(string key) { return GetDatabase().StringDecrement(key); } public RedisValue Hget(string key, string item) { return GetDatabase().HashGet(key, item); } /// <summary> /// 加锁,如果锁定成功,就去执行方法 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expire"></param> /// <returns></returns> public bool TryGetLock(string key, string value, TimeSpan expire) { return GetDatabase().LockTake(key, value, expire); } /// <summary> /// 解锁 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public bool LockRelease(string key, string value) { return GetDatabase().LockRelease(key, value); } public bool Remove(string key) { return GetDatabase().KeyDelete(key); } } }
4.Redis.Entities类库代码
User.cs
namespace Redis.Entities { public class User { public int UserId { get; set; } public string Name { get; set; } public string Phone { get; set; } public string Sex { get; set; } public string UserType { get; set; } } }
5.Redis.IRepository类库代码
首先添加Redis.Entities项目依赖
(1) IRepositoryBase.cs
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; namespace Redis.IRepository { public interface IRepositoryBase<T> { IQueryable<T> FindAll(); IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression); void Create(T entity); void Update(T entity); void Delete(T entity); } }
(2)IUserRepository.cs
using Redis.Entities; using System; using System.Collections.Generic; using System.Text; namespace Redis.IRepository { public interface IUserRepository : IRepositoryBase<User> { User GetUserById(int id); } }
(3) IRepositoryWrapper.cs
using System; using System.Collections.Generic; using System.Text; namespace Redis.IRepository { public interface IRepositoryWrapper { IUserRepository User { get; } } }
6.Redis.Repository类库项目
nuget包添加:Microsoft.EntityFrameworkCore,Microsoft.EntityFrameworkCore.SqlServer
项目引用:Redis.Entities,Redis.IRepository
(1) RedisDbContext.cs
using Microsoft.EntityFrameworkCore; using Redis.Entities; using System; using System.Collections.Generic; using System.Text; namespace Redis.Repository { public class RedisDbContext : DbContext { public RedisDbContext(DbContextOptions<RedisDbContext> options) : base(options) { } public DbSet<User> Users { get; set; } } }
(2) RepositoryBase.cs
using Microsoft.EntityFrameworkCore; using Redis.IRepository; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; namespace Redis.Repository { public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class { protected RedisDbContext RedisDbContext { get; set; } protected RepositoryBase(RedisDbContext repositoryContext) { RedisDbContext = repositoryContext; } public IQueryable<T> FindAll() { return RedisDbContext.Set<T>().AsNoTracking(); } public IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression) { return RedisDbContext.Set<T>().Where(expression); } public void Create(T entity) { RedisDbContext.Set<T>().Add(entity); } public void Update(T entity) { RedisDbContext.Set<T>().Update(entity); } public void Delete(T entity) { RedisDbContext.Set<T>().Remove(entity); } } }
(3) RepositoryWrapper.cs
using Redis.IRepository; using System; using System.Collections.Generic; using System.Text; namespace Redis.Repository { public class RepositoryWrapper : IRepositoryWrapper { private readonly RedisDbContext _redisDbContext; private IUserRepository _user; public IUserRepository User { get { return _user ??= new UserRepository(_redisDbContext); } } public RepositoryWrapper(RedisDbContext redisDbContext) { _redisDbContext = redisDbContext; } } }
(4)UserRepository.cs
using Redis.Entities; using Redis.IRepository; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Redis.Repository { public class UserRepository : RepositoryBase<User>, IUserRepository { public UserRepository(RedisDbContext repositoryContext) : base(repositoryContext) { } public User GetUserById(int id) { return FindByCondition(user => user.UserId == id) .FirstOrDefault(); } } }
7. Redis.IService类库项目
IUserService.cs代码
using Redis.Entities; using System; namespace Redis.IService { public interface IUserService { User GetUserByUserId(int id); } }
8.Redis.Service类库项目
UserService.cs代码
using Newtonsoft.Json; using Redis.Common; using Redis.Entities; using Redis.IRepository; using Redis.IService; using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; namespace Redis.Service { public class UserService : IUserService { private readonly IRepositoryWrapper _repository; private readonly RedisHelper _redis; public UserService(IRepositoryWrapper repository, RedisHelper redis) { _repository = repository; _redis = redis; } public User GetUserByUserId(int id) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); string key = "user:" + id; string result = _redis.Get(key); User users = new User(); if (!string.IsNullOrWhiteSpace(result)) { users = JsonConvert.DeserializeObject<User>(result); Console.WriteLine("缓存查询"); } else { users = _repository.User.GetUserById(id); _redis.Set("user:" + id, JsonConvert.SerializeObject(users)); Console.WriteLine("接口查询"); } stopwatch.Stop(); TimeSpan timeSpan = stopwatch.Elapsed; Console.WriteLine($"用时:{timeSpan.TotalMilliseconds} 毫秒"); return users; } } }
9.Redis.WebApi项目代码
(1) ServiceExtensions.cs
using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Redis.Common; using Redis.IRepository; using Redis.Repository; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Redis.WebApi.Extensions { public static class ServiceExtensions { public static void ConfigureCors(this IServiceCollection services) { services.AddCors(options => { options.AddPolicy("AnyPolicy", builder => builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader()); }); } public static void ConfigureSqlServerContext(this IServiceCollection services, IConfiguration config) { var connectionString = config.GetConnectionString("redisTestDb"); services.AddDbContext<RedisDbContext>( builder => builder.UseSqlServer(connectionString)); } public static void ConfigureRedisContext(this IServiceCollection services, IConfiguration config) { var section = config.GetSection("Redis:Default"); services.AddSingleton(new RedisHelper(section.Get<RedisOption>())); } public static void ConfigureRepositoryWrapper(this IServiceCollection services) { services.AddScoped<IRepositoryWrapper, RepositoryWrapper>(); } } }
(2)DateTimeConverter.cs
using System; using System.Text.Json; using System.Text.Json.Serialization; namespace Redis.WebApi.Extensions { public class DateTimeConverter : JsonConverter<DateTime> { public string DateTimeFormat { get; set; } = "yyyy-MM-dd HH:mm:ss"; public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => DateTime.Parse(reader.GetString()); public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) => writer.WriteStringValue(value.ToString(this.DateTimeFormat)); } }
(3) Startup.cs
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using Redis.IService; using Redis.Service; using Redis.WebApi.Extensions; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Redis.WebApi { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Redis.WebApi", Version = "v1" }); }); services.AddScoped<IUserService, UserService>(); services.ConfigureCors(); services.ConfigureRedisContext(Configuration); services.ConfigureSqlServerContext(Configuration); services.ConfigureRepositoryWrapper(); services.AddMvc().AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = null; options.JsonSerializerOptions.Converters.Add(new DateTimeConverter()); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Redis.WebApi v1")); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }
(4) UserController.cs
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Redis.Common; using Redis.Entities; using Redis.IService; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Redis.WebApi.Controllers { [Route("api/[controller]")] [ApiController] public class UserController : ControllerBase { private readonly IUserService _userService; private readonly RedisHelper _redis; public UserController(IUserService userService, RedisHelper redis) { _userService = userService; _redis = redis; } [HttpGet("GetUserByUserId")] public IActionResult GetUserByUserId(int id) { User account = _userService.GetUserByUserId(id); return Ok(account); } [HttpGet] public IActionResult Test() { _redis.Set("hello", "Hobe"); string value = _redis.Get("hello"); return Ok(value); } } }
10 创建sql表及数据的语句
CREATE TABLE [dbo].[Users]( [UserId] [int] IDENTITY(1,1) NOT NULL, [Name] [varchar](50) NOT NULL, [Phone] [varchar](20) NULL, [Sex] [varchar](10) NULL, [UserType] [varchar](20) NULL, PRIMARY KEY CLUSTERED ( [UserId] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] GO SET IDENTITY_INSERT [dbo].[Users] ON INSERT [dbo].[Users] ([UserId], [Name], [Phone], [Sex], [UserType]) VALUES (1, N'张三', N'13964812931', N'男', N'1') INSERT [dbo].[Users] ([UserId], [Name], [Phone], [Sex], [UserType]) VALUES (2, N'李四', N'13611091826', N'女', N'2') SET IDENTITY_INSERT [dbo].[Users] OFF
11.运行测试
使用postman测试