草庐IT

c# - Redis 缓存无法访问已处置的对象

coder 2023-07-19 原文

我有一个 ASP.NET 核心应用程序,我正在尝试使用 Redis 缓存 - 但是我收到一条错误消息,指出无法访问已处置的对象,所以我一定没有正确设置我的缓存类。我已将缓存服务类提取到我自己的 Nuget 存储库中,以便其他应用程序可以使用它,在其他应用程序中传递与 appsettings.json 不同的 Db 编号

我正在使用内置的 .NET Core DI 来注册缓存服务,如下所示:

services.AddTransient<ICacheService, CacheService>();

然后在我的应用程序中使用缓存服务:

var dataFromCache = _cacheService.TryGetCachedObject<List<MyObject>>(cacheKey);

我的缓存服务在 nuget pacakge 中的实现如下:

public class CacheService : ICacheService, IDisposable

{
    public virtual T TryGetCachedObject<T>(string cacheKey)

    {

        if (RedisCacheHandler.Cache.KeyExists(cacheKey))

        {

            return JsonConvert.DeserializeObject<T>(RedisCacheHandler.Cache.StringGet(cacheKey));

        }

        return default(T);

    }
    //other metjhods omitted for brevity

我在行 if (RedisCacheHandler.Cache.KeyExists(cacheKey))

中收到无法访问已处置对象异常

我的 redis 缓存处理程序类在下面(如果我一直在尝试但没有成功,则注释掉的行。

public static class RedisCacheHandler

{

    private static Lazy<ConnectionMultiplexer> _lazyConnection;

    private static ConnectionMultiplexer Connection => _lazyConnection.Value;

    //private static CacheSettings _cacheSettings;



    public static IDatabase Cache { get; set; }



    //public static IDatabase Cache => Connection.GetDatabase(Convert.ToInt32(_cacheSettings.DbNumber));



    //private static readonly Lazy<ConnectionMultiplexer> LazyConnection

    //    = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(_cacheSettings.Connection));



    //public static ConnectionMultiplexer Connection => LazyConnection.Value;





    public static void AddRedisCacheHandler(this IServiceCollection services, IConfiguration configuration)

    {

        var cacheSettings = new CacheSettings();

        configuration.Bind("CacheSettings", cacheSettings);



        //_cacheSettings = cacheSettings;



        _lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(cacheSettings.Connection));



        Cache = Connection.GetDatabase(Convert.ToInt32(cacheSettings.DbNumber));

    }

}

我在 ConfigureServices 方法中调用 asp.net core 启动类中的 AddRedisCacheHandler 方法,如下所示:

services.AddRedisCacheHandler(Configuration);

编辑

这个的用法是我点击一个 API Controller 去获取引用数据。 API Controller 调用服务层,然后检查数据是否在缓存中并从那里检索,否则将从数据库中获取数据并将其设置在缓存中 24 小时

    private readonly IMyService _myService

    public MyController(IMyService myService)
    {
        _myService = myService;
    }

    [Route("SomeReferenceData")]
    public IEnumerable<SomeDto> GetReferenceData()
    {
        var data = _myService.GetRefData();
         //do stuff and return
    }

在服务层然后代码是:

public class MyService : IMyService
{
    private readonly ICacheService _cacheService;
    private readonly CacheSettings _cacheSettings;    

    public MyService(CacheSettings cacheSettings, ICacheService cacheService)
    {
        _cacheSettings = cacheSettings;
        _cacheService = cacheService;
    }

    public virtual IEnumerable<MyObject> GetRefData()
    {

        string cacheKey = CachingConstants.CacheKey;

        var data = _cacheService.TryGetCachedObject<List<MyObject>>(cacheKey);

        if (data != null)
        {
            return data;
        }

        //go get data from db

        _cacheService.SetCachedObject<IEnumerable<MyObject>>(cacheKey, countries, Convert.ToInt32(_cacheSettings.DurationLongMinutes));

        return data;
    }

从启动开始,我调用下面的代码来注册所有依赖项,包括缓存服务:

services.RegisterServiceDependencies();

public static class ServiceConfig
{
    public static void RegisterServiceDependencies(this IServiceCollection services)
    {
        services.AddTransient<ICacheService, CacheService>();
        //lots of other services

最佳答案

你在这里自杀。从字面上看,这些都不是必需的。 ASP.NET Core 内置了对分布式缓存的支持,包括使用 Redis 作为提供者。在您的 Startup.cs 中:

services.AddDistributedRedisCache(options =>
{
    options.Configuration = "localhost";
    options.InstanceName = "SampleInstance";
});

然后,当您需要使用缓存时,只需注入(inject)IDistributedCache。如果你想要一种自包含的方式来自动序列化/反序列化缓存中的值,你可以简单地添加一些扩展方法:

public static class IDistributedCacheExtensions
{
    public static async Task<T> GetAsync<T>(this IDistributedCache cache, string key) =>
        JsonConvert.DeserializeObject<T>(await cache.GetStringAsync(key));

    public static Task Set<T>(this IDistributedCache cache, string key, T value) =>
        cache.SetStringAsync(key, JsonConvert.SerializeObject(value));
}

如果您坚持要为此创建一个单独的 CacheService 类,那么只需将 IDistributedCache 注入(inject)其中,然后在那里完成您的工作即可。

关于c# - Redis 缓存无法访问已处置的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54350146/

有关c# - Redis 缓存无法访问已处置的对象的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  5. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  6. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  7. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  8. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  9. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  10. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

随机推荐