【问题标题】:Create global caching in class library at .net core 2.0在 .net core 2.0 的类库中创建全局缓存
【发布时间】:2018-10-25 02:39:47
【问题描述】:

我有 .net core 2.0 Web Api 项目。我有 10 个 Web Api 和一个类库项目。我想缓存一些数据。所以我在类库中创建CacheHelper.cs。我在 web api 项目中注入Startup.cs。我想在 webapi 项目启动并到达我的控制器中的任何位置时调用 SetCommonCacheItems。但是当我调用 GetCities 函数时,返回 null。有什么问题?

CacheHelper.cs(在类库项目中)

public class CacheHelper : ICacheHelper
{
    private readonly IUnitOfWork unitOfWork;

    MemoryCache cache = new MemoryCache(new MemoryCacheOptions());
    public CacheHelper(IUnitOfWork unitOfWork)
    {
        this.unitOfWork = unitOfWork;
    }

    public void SetCommonCacheItems()
    {
        var cities= unitOfWork.CityRepo.GetAll();
        cache.Set("city", cities);
    }

    public string GetCities()
    {
        string obj;
        cache.TryGetValue<string>("city", out obj);

        return obj;
    }
}

Startup.cs(在 Web API 项目中)

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
        services.AddScoped<IUnitOfWork, UnitOfWork>();
        services.AddScoped<IJwtHelper, JwtHelper>();
        services.AddScoped<IAuditHelper, AuditHelper>();
        services.AddMemoryCache();
        services.AddScoped<ICacheHelper, CacheHelper>();
        services.AddMvc();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    }

【问题讨论】:

  • 请停止使用 .NET Core 2.0。它具有无法修复的已知安全问题。例如,CVE-2018-8292:.NET Core 信息泄露漏洞。我建议尽快升级到 2.1。
  • 感谢您的回复。我已经在使用 2.1。我只是为了提问而写的。

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


【解决方案1】:

这是因为您将缓存用作“范围”服务,这意味着对于每个请求,框架都会创建一个新的缓存对象,而您在应用启动时设置的缓存对象将会丢失。

试试这个:

services.AddSingleton<ICacheHelper, CacheHelper>();

重要提示:这会破坏你的工作单元,因为它在你的缓存中也是一个单例。

我建议不要在缓存中使用工作单元,而只需将存储库中的结果作为参数传递给 SetCommonCacheItems()。

编辑:或者您可以使用built-in memory cache。在这种情况下,您不必将缓存助手用作单例。

【讨论】:

  • 我试过单例。但在那种情况下,我不能调用 SetCommonCacheItems。您认为MemoryCache cache = new MemoryCache(new MemoryCacheOptions()); 行是错误的吗? @PeterCsajtai
  • 为什么不能调用SetCommonCacheItems?如果您的 cachehelper 是单例,则实例化您自己的内存缓存的那一行应该可以工作,如果它仍然是作用域,它将为每个新请求一次又一次地实例化。另一种方法是用框架提供的注入 IMemoryCache 依赖项替换该行。
  • 我编辑了CacheHelper.cs,使用了像CacheHelper: public CacheHelper(IMemoryCache cache, IUnitOfWork unitOfWork) {}这样的添加依赖关系,我像services.TryAdd(ServiceDescriptor.Singleton&lt;IMemoryCache, MemoryCache&gt;());那样转换了startup.cs它现在可以工作了。我可以得到我的缓存值。但是现在唯一的问题是对于每个请求,运行 CacheHelper。但我只想要项目开始时,然后每 8 小时一次。我怎样才能做到这一点? @PéterCsajtai
  • 运行 CacheHelper 是什么意思?将存储库中的项目加载到缓存中?您可以通过托管服务使用定时后台任务来实现类似的目标,查看thisthis 了解更多信息
  • 是的。我的意思是就像你说的将项目从存储库加载到缓存。我认为内存缓存具有在每个周期(例如 8 小时)刷新其数据的选项。我会尝试你建议的链接。非常感谢。
【解决方案2】:

services.AddMemoryCache();注册MemoryCache这样services.TryAdd(ServiceDescriptor.Singleton&lt;IMemoryCache, MemoryCache&gt;());,表示缓存在单例范围内,请求完成后不会被释放。

但是在CacheHelper 中,你已经通过构造函数创建了MemoryCache,并且,一旦请求完成后CacheHelper 被释放,你的缓存就会丢失。

要更改此行为,您有 2 个选项:

  • 将“IMemoryCache”依赖添加到CacheHelperpublic CacheHelper(IMemoryCache cache, IUnitOfWork unitOfWork) {}
  • CacheHelper 设为单例:services.AddScoped&lt;ICacheHelper, CacheHelper&gt;();

【讨论】:

  • 感谢@AxeUser。我编辑了我的代码,如 services.TryAdd(ServiceDescriptor.Singleton&lt;IMemoryCache, MemoryCache&gt;()); 。它奏效了。但是对于每个请求,它都会发送到CacheHelper。但我只想要项目开始时,然后每 8 小时一次。我怎样才能做到这一点?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-21
  • 2018-05-14
相关资源
最近更新 更多