首页 > 解决方案 > Asp.Net Core:我应该在缓存服务上使用 AddScoped 还是 AddSingleton

问题描述

在一个 asp.net 核心应用程序中,我有一个依赖注入缓存服务,它本质上是一个围绕内置 MemoryCache 的包装器。

这是被缓存的示例类,它包含一些 Web 应用程序始终使用的枚举列表:

public class GetEnums
{
    public List<MyEnum1> Ones { get; set; }
    public List<MyEnum2> Twos { get; set; }
}

这是我的缓存服务类的示例方法调用,它只是检索 GetEnums 类:

public class CacheService: ICacheService
{
    private IMemoryCache MemoryCache {get;set;}
    public CacheService(IMemoryCache memoryCache)
    {
        MemoryCache = memoryCache;
    }
    public GetEnums GetEnums()
    {
        if (MemoryCache.TryGetValue("GetEnums", out GetEnums getEnums))
            return getEnums;

        getEnums = MyRepository.GetEnums();
        MemoryCache.Set(CacheKeys.GetEnums, getEnums, _enumMemoryCacheEntryOptions);

        return getEnums;
    }
}

在我的 ConfigureServices 方法中,我想让这个类成为一个依赖注入的服务。我应该使用 AddScoped 还是 AddSingleton?也就是说,我应该这样做吗?

services.AddScoped(<ICacheService,CacheService>);

或这个?

services.AddSingleton(<ICacheService,CacheService>);

我有两个问题。

一,如果我选择 AddScoped:我的猜测是,由于我的缓存服务类只是 MemoryCache 的包装器,唯一的区别是用于为每个 Web 请求(AddScoped)创建缓存服务对象与一个实例的轻微开销对于应用程序(AddSingleton)。我猜如果我使用 AddScoped,.Net 运行时不会创建单独的 MemoryCache 实例。

二,如果我选择 AddSingleton,我是否需要在我的缓存服务的每个方法内围绕“MemoryCache.Set”调用添加“锁定”语句,如下所示:

    private readonly object _cachelock = new ();
    public GetEnums GetEnums()
    {
        if (MemoryCache.TryGetValue(CacheKeys.GetEnums, out GetEnums getEnums))
            return getEnums;

        lock(_cachelock)
        {
            if (MemoryCache.TryGetValue(CacheKeys.GetEnums, out getEnums))
                return getEnums;

            getEnums = MyRepository.GetEnums();
            MemoryCache.Set(CacheKeys.GetEnums, getEnums, _enumMemoryCacheEntryOptions);
        }

        return getEnums;
    }

标签: c#asp.net-corecaching

解决方案


当您注册内存缓存时,services.AddMemoryCache()它被添加为单例,因此将您的服务也注册为单例似乎是合乎逻辑的。

源代码

MemoryCache 也是线程安全的,因此没有理由添加锁。如果对给定键多次调用 Set(),它将简单地更新现有值。

内存缓存文档


推荐阅读