Redis学习-.AspNet Core项目实际应用

Posted on 2022-01-18 23:07  樱木007  阅读(130)  评论(0编辑  收藏  举报

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测试

 

 

 

Copyright © 2024 樱木007
Powered by .NET 8.0 on Kubernetes