Asp.Net 核心:我应该在缓存服务上使用 AddScoped 还是 AddSingleton
Asp.Net Core: should I use AddScoped or AddSingleton on a cache service
在一个 asp.net 核心应用程序中,我有一个依赖注入的缓存服务,它本质上是内置 MemoryCache 的包装器。
这是被缓存的示例 class,它包含 Web 应用程序始终使用的一些枚举的列表:
public class GetEnums
{
public List<MyEnum1> Ones { get; set; }
public List<MyEnum2> Twos { get; set; }
}
这是对我的缓存服务 class 的示例方法调用,它只是检索 GetEnums class:
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 方法中,我想让这个 class 成为一个依赖注入的服务。我应该使用 AddScoped 还是 AddSingleton?也就是说,我应该这样做吗?
services.AddScoped(<ICacheService,CacheService>);
还是这个?
services.AddSingleton(<ICacheService,CacheService>);
我有两个问题。
第一,如果我选择 AddScoped:我的猜测是因为我的缓存服务 class 只是 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;
}
当您使用 services.AddMemoryCache()
注册内存缓存时,它被添加为单例,因此将您的服务也注册为单例似乎合乎逻辑。
MemoryCache 也是线程安全的,所以应该没有理由加锁。如果对给定键多次调用 Set(),它只会更新现有值。
在一个 asp.net 核心应用程序中,我有一个依赖注入的缓存服务,它本质上是内置 MemoryCache 的包装器。
这是被缓存的示例 class,它包含 Web 应用程序始终使用的一些枚举的列表:
public class GetEnums
{
public List<MyEnum1> Ones { get; set; }
public List<MyEnum2> Twos { get; set; }
}
这是对我的缓存服务 class 的示例方法调用,它只是检索 GetEnums class:
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 方法中,我想让这个 class 成为一个依赖注入的服务。我应该使用 AddScoped 还是 AddSingleton?也就是说,我应该这样做吗?
services.AddScoped(<ICacheService,CacheService>);
还是这个?
services.AddSingleton(<ICacheService,CacheService>);
我有两个问题。
第一,如果我选择 AddScoped:我的猜测是因为我的缓存服务 class 只是 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;
}
当您使用 services.AddMemoryCache()
注册内存缓存时,它被添加为单例,因此将您的服务也注册为单例似乎合乎逻辑。
MemoryCache 也是线程安全的,所以应该没有理由加锁。如果对给定键多次调用 Set(),它只会更新现有值。