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

时间:2019-01-24 15:30:48

标签: c# .net caching asp.net-core redis

我有一个ASP.NET核心应用程序,并且尝试使用Redis缓存-但是我收到一条错误消息,说无法访问已处置的对象,因此我必须未正确设置我的缓存类。我已经将Cache服务类放入我自己的Nuget存储库中,以便其他应用程序可以将它与其他应用程序中的appsettings.json传递不同的Db号码

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

services.AddTransient<ICacheService, CacheService>();

然后按如下方式在我的应用程序中使用缓存服务:

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

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

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核心启动类中调用AddRedisCacheHandler方法,如下所示:

services.AddRedisCacheHandler(Configuration);

编辑

它的用法是我点击了一个API控制器来获取参考数据。 API控制器调用服务层,然后服务层将检查数据是否在缓存中,然后从那里进行检索,将从数据库中获取数据并将其在缓存中设置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

1 个答案:

答案 0 :(得分:1)

您在这里自杀。从字面上看,这没有必要。 ASP.NET Core具有对分布式缓存的内置支持,包括使用Redis作为提供程序。在您的import tkinter as tk from tkinter import ttk root=tk.Tk() root.geometry("+50+50") var=tk.IntVar() var.set(0) current_state=tk.StringVar() text=[' Checkbutton: Off ', ' Checkbutton: On ', ' CB to Third State '] def label_update(): current_state.set(text[var.get()]) cb=ttk.Checkbutton(root, variable=var, text='Test Box', command=label_update) cb.grid() seq=[1,2] def tick(): """ Sets var (tk.IntVar) to 0, 1, 2 in sequence for each tick """ try: var.set(seq[var.get()]) if var.get()>1: cb.state(['alternate']) # alternate on except IndexError: cb.state(['!alternate']) # alternate off var.set(0) # reset count label_update() ttk.Button(root, text=" Click to cycle through states ", command=tick).grid() ttk.Label(root, textvariable=current_state).grid() label_update() root.title("Checkbutton Issue") root.mainloop() 中,只需执行以下操作:

Startup.cs

然后,当您需要利用缓存时,只需注入services.AddDistributedRedisCache(options => { options.Configuration = "localhost"; options.InstanceName = "SampleInstance"; }); 。如果您想要一种独立的方法来自动序列化/反序列化缓存中的值,则可以简单地添加一些扩展方法:

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注入其中,然后在其中进行工作即可。