dotnet 核心中的内存缓存
Memory Cache in dotnet core
我正在尝试编写一个 class 来处理 .net 核心 class 库中的内存缓存。如果我不使用核心那么我可以写
using System.Runtime.Caching;
using System.Collections.Concurrent;
namespace n{
public class MyCache
{
readonly MemoryCache _cache;
readonly Func<CacheItemPolicy> _cachePolicy;
static readonly ConcurrentDictionary<string, object> _theLock = new ConcurrentDictionary<string, object>();
public MyCache(){
_cache = MemoryCache.Default;
_cachePolicy = () => new CacheItemPolicy
{
SlidingExpiration = TimeSpan.FromMinutes(15),
RemovedCallback = x =>
{
object o;
_theLock.TryRemove(x.CacheItem.Key, out o);
}
};
}
public void Save(string idstring, object value){
lock (_locks.GetOrAdd(idstring, _ => new object()))
{
_cache.Add(idstring, value, _cachePolicy.Invoke());
}
....
}
}
}
在 .Net 核心中我找不到 System.Runtime.Cache。在阅读了 .net 核心 In Memory Cache 之后,我添加了参考 Microsoft.Extensions.Caching.Memory (1.1.0) 并尝试了
using System.Collections.Concurrent;
using Microsoft.Extensions.Caching.Memory;
namespace n
{
public class MyCache
{
readonly MemoryCache _cache;
readonly Func<CacheItemPolicy> _cachePolicy;
static readonly ConcurrentDictionary<string, object> _theLock = new ConcurrentDictionary<string, object>();
public MyCache(IMemoryCache memoryCache){
_cache = memoryCache;// ?? **MemoryCache**;
}
public void Save(string idstring, object value){
lock (_locks.GetOrAdd(idstring, _ => new object()))
{
_cache.Set(idstring, value,
new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes(15))
.RegisterPostEvictionCallback(
(key, value, reason, substate) =>
{
object o;
_locks.TryRemove(key.ToString(), out o);
}
));
}
....
}
}
}
希望保存方法中的代码没问题,尽管目前我的大部分 mycache 测试都失败了。任何人都可以指出什么是错的吗?
主要问题是关于构造函数我应该怎么做才能设置缓存 MemoryCache.Default
_cache = memoryCache ?? MemoryCache.Default;
构造函数是:
using Microsoft.Extensions.Caching.Memory;
。
.
.
MemoryCache myCache = new MemoryCache(new MemoryCacheOptions());
我的回答集中在“在 .Net 核心中我找不到 System.Runtime.Cache”,因为我 运行 遇到了同样的问题。对于在特定 OP 场景中使用 IMemoryCache
,接受的答案很好。
有两个完全不同缓存implementations/solutions:
1 - System.Runtime.Caching/MemoryCache
2 - Microsoft.Extensions.Caching.Memory/IMemoryCache
System.Runtime.Caching/MemoryCache:
这与过去 ASP.Net MVC 的 HttpRuntime.Cache
几乎相同。 您可以在 ASP.Net CORE 上使用它而无需任何依赖项注入。这是如何使用它:
// First install 'System.Runtime.Caching' (NuGet package)
// Add a using
using System.Runtime.Caching;
// To get a value
var myString = MemoryCache.Default["itemCacheKey"];
// To store a value
MemoryCache.Default["itemCacheKey"] = myString;
Microsoft.Extensions.Caching.Memory
这与依赖注入紧密结合。这是一种实现方式:
// In asp.net core's Startup add this:
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
}
在控制器上使用它:
// Add a using
using Microsoft.Extensions.Caching.Memory;
// In your controller's constructor, you add the dependency on the 'IMemoryCache'
public class HomeController : Controller
{
private IMemoryCache _cache;
public HomeController(IMemoryCache memoryCache)
{
_cache = memoryCache;
}
public void Test()
{
// To get a value
string myString = null;
if (_cache.TryGetValue("itemCacheKey", out myString))
{ /* key/value found - myString has the key cache's value*/ }
// To store a value
_cache.Set("itemCacheKey", myString);
}
}
正如@WillC 所指出的,这个答案实际上是 Cache in-memory in ASP.NET Core 文档的摘要。您可以在那里找到扩展信息。
如果您使用 Asp.net 核心,则无需为缓存自定义 SingleTon,因为 Asp.net 核心支持缓存 class.
要使用IMemoryCache
将数据设置到服务器的内存中,您可以按照以下步骤操作:
public void Add<T>(T o, string key)
{
if (IsEnableCache)
{
T cacheEntry;
// Look for cache key.
if (!_cache.TryGetValue(key, out cacheEntry))
{
// Key not in cache, so get data.
cacheEntry = o;
// Set cache options.
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromSeconds(7200));
// Save data in cache.
_cache.Set(key, cacheEntry, cacheEntryOptions);
}
}
}
- 通过构造函数注入 MemoryCache(从 nugget 获取引用
Microsoft.Extensions.Caching.Memory)
private readonly IMemoryCache memoryCache;
- 代码实现
private IList<Employee> GetListFromCache()
{
const string Key = "employee";
IList<Employee> cacheValue = null;
if (!this.memoryCache.TryGetValue(Key, out cacheValue))
{
//// Key not in cache, so get data.
cacheValue = this.context.Employee.AsNoTracking().Include(x =>
x.Id).ToList();
//// Set cache options.
var cacheEntryOptions = new MemoryCacheEntryOptions()
//// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromDays(1));
//// Save data in cache.
this.memoryCache.Set(Key, cacheValue, cacheEntryOptions);
}
return cacheValue;
}
在 Startup.cs
中的 ConfigureServices 下注册 AddMemoryCache
services.AddMemoryCache();
- 为单元测试模拟 IMemoryCache
/// <summary>Gets the memory cache.</summary>
/// <returns> Memory cache object.</returns>
public IMemoryCache GetMemoryCache()
{
var services = new ServiceCollection();
services.AddMemoryCache();
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetService<IMemoryCache>();
}
//Inject memory cache in constructor for unit test
this.memoryCache = text.GetMemoryCache();
我正在尝试编写一个 class 来处理 .net 核心 class 库中的内存缓存。如果我不使用核心那么我可以写
using System.Runtime.Caching;
using System.Collections.Concurrent;
namespace n{
public class MyCache
{
readonly MemoryCache _cache;
readonly Func<CacheItemPolicy> _cachePolicy;
static readonly ConcurrentDictionary<string, object> _theLock = new ConcurrentDictionary<string, object>();
public MyCache(){
_cache = MemoryCache.Default;
_cachePolicy = () => new CacheItemPolicy
{
SlidingExpiration = TimeSpan.FromMinutes(15),
RemovedCallback = x =>
{
object o;
_theLock.TryRemove(x.CacheItem.Key, out o);
}
};
}
public void Save(string idstring, object value){
lock (_locks.GetOrAdd(idstring, _ => new object()))
{
_cache.Add(idstring, value, _cachePolicy.Invoke());
}
....
}
}
}
在 .Net 核心中我找不到 System.Runtime.Cache。在阅读了 .net 核心 In Memory Cache 之后,我添加了参考 Microsoft.Extensions.Caching.Memory (1.1.0) 并尝试了
using System.Collections.Concurrent;
using Microsoft.Extensions.Caching.Memory;
namespace n
{
public class MyCache
{
readonly MemoryCache _cache;
readonly Func<CacheItemPolicy> _cachePolicy;
static readonly ConcurrentDictionary<string, object> _theLock = new ConcurrentDictionary<string, object>();
public MyCache(IMemoryCache memoryCache){
_cache = memoryCache;// ?? **MemoryCache**;
}
public void Save(string idstring, object value){
lock (_locks.GetOrAdd(idstring, _ => new object()))
{
_cache.Set(idstring, value,
new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes(15))
.RegisterPostEvictionCallback(
(key, value, reason, substate) =>
{
object o;
_locks.TryRemove(key.ToString(), out o);
}
));
}
....
}
}
}
希望保存方法中的代码没问题,尽管目前我的大部分 mycache 测试都失败了。任何人都可以指出什么是错的吗? 主要问题是关于构造函数我应该怎么做才能设置缓存 MemoryCache.Default
_cache = memoryCache ?? MemoryCache.Default;
构造函数是:
using Microsoft.Extensions.Caching.Memory;
。 . .
MemoryCache myCache = new MemoryCache(new MemoryCacheOptions());
我的回答集中在“在 .Net 核心中我找不到 System.Runtime.Cache”,因为我 运行 遇到了同样的问题。对于在特定 OP 场景中使用 IMemoryCache
,接受的答案很好。
有两个完全不同缓存implementations/solutions:
1 - System.Runtime.Caching/MemoryCache
2 - Microsoft.Extensions.Caching.Memory/IMemoryCache
System.Runtime.Caching/MemoryCache:
这与过去 ASP.Net MVC 的 HttpRuntime.Cache
几乎相同。 您可以在 ASP.Net CORE 上使用它而无需任何依赖项注入。这是如何使用它:
// First install 'System.Runtime.Caching' (NuGet package)
// Add a using
using System.Runtime.Caching;
// To get a value
var myString = MemoryCache.Default["itemCacheKey"];
// To store a value
MemoryCache.Default["itemCacheKey"] = myString;
Microsoft.Extensions.Caching.Memory
这与依赖注入紧密结合。这是一种实现方式:
// In asp.net core's Startup add this:
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
}
在控制器上使用它:
// Add a using
using Microsoft.Extensions.Caching.Memory;
// In your controller's constructor, you add the dependency on the 'IMemoryCache'
public class HomeController : Controller
{
private IMemoryCache _cache;
public HomeController(IMemoryCache memoryCache)
{
_cache = memoryCache;
}
public void Test()
{
// To get a value
string myString = null;
if (_cache.TryGetValue("itemCacheKey", out myString))
{ /* key/value found - myString has the key cache's value*/ }
// To store a value
_cache.Set("itemCacheKey", myString);
}
}
正如@WillC 所指出的,这个答案实际上是 Cache in-memory in ASP.NET Core 文档的摘要。您可以在那里找到扩展信息。
如果您使用 Asp.net 核心,则无需为缓存自定义 SingleTon,因为 Asp.net 核心支持缓存 class.
要使用IMemoryCache
将数据设置到服务器的内存中,您可以按照以下步骤操作:
public void Add<T>(T o, string key)
{
if (IsEnableCache)
{
T cacheEntry;
// Look for cache key.
if (!_cache.TryGetValue(key, out cacheEntry))
{
// Key not in cache, so get data.
cacheEntry = o;
// Set cache options.
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromSeconds(7200));
// Save data in cache.
_cache.Set(key, cacheEntry, cacheEntryOptions);
}
}
}
- 通过构造函数注入 MemoryCache(从 nugget 获取引用 Microsoft.Extensions.Caching.Memory)
private readonly IMemoryCache memoryCache;
- 代码实现
private IList<Employee> GetListFromCache()
{
const string Key = "employee";
IList<Employee> cacheValue = null;
if (!this.memoryCache.TryGetValue(Key, out cacheValue))
{
//// Key not in cache, so get data.
cacheValue = this.context.Employee.AsNoTracking().Include(x =>
x.Id).ToList();
//// Set cache options.
var cacheEntryOptions = new MemoryCacheEntryOptions()
//// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromDays(1));
//// Save data in cache.
this.memoryCache.Set(Key, cacheValue, cacheEntryOptions);
}
return cacheValue;
}
在 Startup.cs
中的 ConfigureServices 下注册 AddMemoryCache services.AddMemoryCache();
- 为单元测试模拟 IMemoryCache
/// <summary>Gets the memory cache.</summary>
/// <returns> Memory cache object.</returns>
public IMemoryCache GetMemoryCache()
{
var services = new ServiceCollection();
services.AddMemoryCache();
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetService<IMemoryCache>();
}
//Inject memory cache in constructor for unit test
this.memoryCache = text.GetMemoryCache();