dotnet核心中的内存缓存

时间:2017-01-06 12:20:19

标签: caching .net-core memorycache

我正在尝试编写一个类来处理.net核心类库中的内存缓存。如果我不使用核心,那么我可以写

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; 

4 个答案:

答案 0 :(得分:29)

构造函数是:

using Microsoft.Extensions.Caching.Memory;

。 。

MemoryCache myCache = new MemoryCache(new MemoryCacheOptions());

答案 1 :(得分:1)

我的答案集中在“在.Net内核中找不到System.Runtime.Cache”,因为我遇到了同样的问题。对于在特定OP的情况下使用IMemoryCache,可接受的答案很好。


有两种完全不同的缓存实现/解决方案:

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文档的摘要。您可以在此处找到扩展信息。

答案 2 :(得分:0)

如果您使用Asp.net核心,则无需自定义SingleTon进行缓存,因为Asp.net核心是您的Cache类支持的DI。

要使用 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);
        }
    }
}

有关更多详细信息,您可以阅读文章implement in-memory in asp.net core

答案 3 :(得分:0)

  • 通过构造函数注入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();