• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >ASP.NET > 详解Asp.net Core 使用Redis存储Session

详解Asp.net Core 使用Redis存储Session

作者:韩天伟 字体:[增加 减小] 来源:互联网 时间:2017-05-11

韩天伟通过本文主要向大家介绍了pro asp.net core mvc,asp core h5,asp core area,redis asp.net,asp redis等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

Asp.net Core 改变了之前的封闭,现在开源且开放,下面我们来用Redis存储Session来做一个简单的测试,或者叫做中间件(middleware)。

对于Session来说褒贬不一,很多人直接说不要用,也有很多人在用,这个也没有绝对的这义,个人认为只要不影什么且又可以方便实现的东西是可以用的,现在不对可不可用做表态,我们只关心实现。

类库引用

这个相对于之前的.net是方便了不少,需要在project.json中的dependencies节点中添加如下内容:

  "StackExchange.Redis": "1.1.604-alpha",
  "Microsoft.AspNetCore.Session": "1.1.0-alpha1-21694"
</div>

Redis实现

这里并非我实现,而是借用不知道为什么之前还有这个类库,而现在NUGET止没有了,为了不影响日后升级我的命名空间也用 Microsoft.Extensions.Caching.Redis

可以看到微软这里有四个类,其实我们只需要三个,第四个拿过来反而会出错:

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using StackExchange.Redis;

namespace Microsoft.Extensions.Caching.Redis
{
  public class RedisCache : IDistributedCache, IDisposable
  {
    // KEYS[1] = = key
    // ARGV[1] = absolute-expiration - ticks as long (-1 for none)
    // ARGV[2] = sliding-expiration - ticks as long (-1 for none)
    // ARGV[3] = relative-expiration (long, in seconds, -1 for none) - Min(absolute-expiration - Now, sliding-expiration)
    // ARGV[4] = data - byte[]
    // this order should not change LUA script depends on it
    private const string SetScript = (@"
        redis.call('HMSET', KEYS[1], 'absexp', ARGV[1], 'sldexp', ARGV[2], 'data', ARGV[4])
        if ARGV[3] ~= '-1' then
         redis.call('EXPIRE', KEYS[1], ARGV[3])
        end
        return 1");
    private const string AbsoluteExpirationKey = "absexp";
    private const string SlidingExpirationKey = "sldexp";
    private const string DataKey = "data";
    private const long NotPresent = -1;

    private ConnectionMultiplexer _connection;
    private IDatabase _cache;

    private readonly RedisCacheOptions _options;
    private readonly string _instance;

    public RedisCache(IOptions<RedisCacheOptions> optionsAccessor)
    {
      if (optionsAccessor == null)
      {
        throw new ArgumentNullException(nameof(optionsAccessor));
      }

      _options = optionsAccessor.Value;

      // This allows partitioning a single backend cache for use with multiple apps/services.
      _instance = _options.InstanceName ?? string.Empty;
    }

    public byte[] Get(string key)
    {
      if (key == null)
      {
        throw new ArgumentNullException(nameof(key));
      }

      return GetAndRefresh(key, getData: true);
    }

    public async Task<byte[]> GetAsync(string key)
    {
      if (key == null)
      {
        throw new ArgumentNullException(nameof(key));
      }

      return await GetAndRefreshAsync(key, getData: true);
    }

    public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
    {
      if (key == null)
      {
        throw new ArgumentNullException(nameof(key));
      }

      if (value == null)
      {
        throw new ArgumentNullException(nameof(value));
      }

      if (options == null)
      {
        throw new ArgumentNullException(nameof(options));
      }

      Connect();

      var creationTime = DateTimeOffset.UtcNow;

      var absoluteExpiration = GetAbsoluteExpiration(creationTime, options);

      var result = _cache.ScriptEvaluate(SetScript, new RedisKey[] { _instance + key },
        new RedisValue[]
        {
            absoluteExpiration?.Ticks ?? NotPresent,
            options.SlidingExpiration?.Ticks ?? NotPresent,
            GetExpirationInSeconds(creationTime, absoluteExpiration, options) ?? NotPresent,
            value
        });
    }

    public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options)
    {
      if (key == null)
      {
        throw new ArgumentNullException(nameof(key));
      }

      if (value == null)
      {
        throw new ArgumentNullException(nameof(value));
      }

      if (options == null)
      {
        throw new ArgumentNullException(nameof(options));
      }

      await ConnectAsync();

      var creationTime = DateTimeOffset.UtcNow;

      var absoluteExpiration = GetAbsoluteExpiration(creationTime, options);

      await _cache.ScriptEvaluateAsync(SetScript, new RedisKey[] { _instance + key },
        new RedisValue[]
        {
            absoluteExpiration?.Ticks ?? NotPresent,
            options.SlidingExpiration?.Ticks ?? NotPresent,
            GetExpirationInSeconds(creationTime, absoluteExpiration, options) ?? NotPresent,
            value
        });
    }

    public void Refresh(string key)
    {
      if (key == null)
      {
        throw new ArgumentNullException(nameof(key));
      }

      GetAndRefresh(key, getData: false);
    }

    public async Task RefreshAsync(string key)
    {
      if (key == null)
      {
        throw new ArgumentNullException(nameof(key));
      }

      await GetAndRefreshAsync(key, getData: false);
    }

    private void Connect()
    {
      if (_connection == null)
      {
        _connection = ConnectionMultiplexer.Connect(_options.Configuration);
        _cache = _connection.GetDatabase();
      }
    }

    private async Task ConnectAsync()
    {
      if (_connection == null)
      {
        _connection = await ConnectionMultiplexer.ConnectAsync(_options.Configuration);
        _cache = _connection.GetDatabase();
      }
    }

    private byte[] GetAndRefresh(string key, bool getData)
    {
      if (key == null)
      {
        throw new ArgumentNullException(nameof(key));
      }

      Connect();

      // This also resets the LRU status as desired.
      // TODO: Can this be done in one operation on the server side? Probably, the trick would just be the DateTimeOffset math.
      RedisValue[] results;
      if (getData)
      {
        results = _cache.HashMemberGet(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey, DataKey);
      }
      else
      {
        results = _cache.HashMemberGet(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey);
      }

      // TODO: Error handling
      if (results.Length >= 2)
      {
        // Note we always get back two results, even if they are all null.
        // These operations will no-op in the null scenario.
        DateTimeOffset? absExpr;
        TimeSpan? sldExpr;
        MapMetadata(results, out absExpr, out sldExpr);
        Refresh(key, absExpr, sldExpr);
      }

      if (results.Length >= 3 && results[2].HasValue)
      {
        return results[2];
      }

      return null;
    }

    private async Task<byte[]> GetAndRefreshAsync(string key, bool getData)
    {
      if (key == null)
      {
        throw new ArgumentNullException(nameof(key));
      }

      await ConnectAsync();

      // This also resets the LRU status as desired.
      // TODO: Can this be done in one operation on the server side? Probably, the trick would just be the DateTimeOffset math.
      RedisValue[] results;
      if (getData)
      {
        results = await _cache.HashMemberGetAsync(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey, DataKey);
      }
      else
      {
        results = await _cache.HashMemberGetAsync(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey);
      }

      // TODO: Error handling
      if (results.Length >= 2)
      {
        // Note we always get



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • ASP.NET Core发送邮件的方法
  • 在ASP.NET Core 中发送邮件的实现方法(必看篇)
  • Asp.net core WebApi 使用Swagger生成帮助页实例
  • ASP.NET core Web中使用appsettings.json配置文件的方法
  • ASP.NET Core部署前期准备 使用Hyper-V安装Ubuntu Server 16.10
  • ASP.NET Core应用中与第三方IoC/DI框架的整合
  • ASP.NET Core程序发布到Linux生产环境详解
  • 详解ASP.NET Core 网站发布到Linux服务器
  • ASP.NET Core全面扫盲贴
  • 基于ASP.NET Core数据保护生成验证token示例

相关文章

  • 2018-08-20ADO调用分页查询存储过程的实例讲解
  • 2018-08-20WPF图形解锁控件ScreenUnLock使用详解
  • 2017-05-11asp.net使用母版页中使用ajax脚本取数据
  • 2017-05-11ASP.NET怎么操作DataTable实例应用
  • 2017-05-11ASP.NET MVC4入门教程(二):添加一个控制器
  • 2017-05-11Asp.Net用OWC操作Excel的实例代码
  • 2017-05-11asp.net中资源文件的使用
  • 2017-05-11.NET MVC中ViewData,ViewBag和TempData的区别浅析
  • 2017-05-11基于SignalR的消息推送与二维码扫描登录实现代码
  • 2017-05-11详解在ASP.NET Core下使用SignalR技术

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • asp.net简单生成验证码的方法
    • 创建完全可编辑的 DataGrid
    • ASP.NET Eval 求值运算的一些用法
    • .NET中的枚举用法浅析
    • 解读ASP.NET 5 & MVC6系列教程(8):Session与Caching
    • asp.net 数据绑定 使用eval 时候报 字符文本中的字符太多 问题的解决方法
    • asp.net 操作excel的实现代码
    • MVC后台创建Json(List)前台接受并循环读取实例
    • DropDownList 下拉框选择改变促发事件和防全局刷新(推荐)
    • ASP.NET设计网络硬盘之下载或在线查看实现代码

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有