我正在尝试使用 Microsoft.Extensions.Caching.Memory 命名空间将应用程序缓存添加到 Net 8 控制台应用程序。我已经完成了一半,但已经达到了一个地步,当缓存运行时,我不知道如何管理缓存,其中包含 1,000 多个项目。在我的 GenericHostBuilder 类中,我设置了以下缓存选项:
private static void BuildMemoryCacheOptions(MemoryCacheOptions _MemoryCacheOptions)
{
_MemoryCacheOptions = new MemoryCacheOptions();
_MemoryCacheOptions.Clock = new Microsoft.Extensions.Internal.SystemClock();
_MemoryCacheOptions.SizeLimit = 1024 * 1024;
_MemoryCacheOptions.TrackLinkedCacheEntries = false;
_MemoryCacheOptions.ExpirationScanFrequency = new TimeSpan(0, 2, 0);
_MemoryCacheOptions.CompactionPercentage = 0.15;
_MemoryCacheOptions.TrackStatistics = true;
}
GenericHostBuilder 将其实现为服务。
_HostApplicationBuilder.Services.AddMemoryCache(BuildMemoryCacheOptions);
然后,我在构造函数调用期间将其作为全局作用域变量添加到我的类中,并作为作用域服务提供者上的单例:
private _MemoryCache = _ServiceProvider.GetRequiredService<MemoryCache>();
然后我可以在方法中使用它来将缓存项目添加到应用程序缓存,并将往返保存到数据库,如下所示:
public Domain? AddAnyLengthName(ref TopLevelDomain _TLD, string _DomainName, bool _IsValidName)
{
Domain? _Domain = _Domain = null;
MyDBContext _DbContext = _ServiceProvider.GetRequiredService<MyDBContext>();
string _RootDomainName = DomainDTO.ConvertToRootDomainName(_DomainName);
_Domain = new Domain(_RootDomainName, _TLD);
_Domain.IsValidDomainName = _IsValidName;
_DbContext.Domains.Add(_Domain);
_DbContext.SaveChanges();
Domain _CachedDomain = _MemoryCache.Set(_Domain.DomainName, _Domain);
ICacheEntry _CacheEntry = _MemoryCache.CreateEntry(_CachedDomain);
_CacheEntry.SlidingExpiration = new TimeSpan(0, 3, 0);
return _Domain;
}
所有这些都非常有效,并且性能提升非常显着。但是,最终缓存会被填满,性能开始受到影响。当 MemoryCache 组件从服务容器中出来时,它的类型已更改为 IMemoryCache 类型,这就是我遇到问题的地方,因为此接口默认情况下包含在 MemoryCache 类中的几个缺少的属性和方法,并且我'尚未找到解决此问题的解决方案。
IMemoryCache 有一个方法 GetCurrentStatistics() 和一个属性 Count。 Count 返回缓存中的项目数,但当我尝试使用 GetCurrentStatistics() 时,它始终为 null,并且没有其他属性或方法允许我迭代缓存中的项目。 所以,目前我还没有办法管理缓存内容。
另一方面,如果不将 MemoryCache 实现为服务,而是直接在类中实现它,然后将其作为参数传递,我就可以访问这些额外的方法和属性,让我管理缓存内容,例如作为 Clear() 来清除缓存中的所有项目,或允许我迭代缓存内容的枚举器,而无需提前知道缓存项目的每个键是什么。
我的问题是:
我什至尝试将 MemoryCache 添加到我的 DbContextOptions 中,如下所示:
_DbContextOptionsBuilder.UseMemoryCache(new MemoryCache(GetMemoryCacheOptions()));
但是当我去检索它时,我无法使用 ServiceProvider.GetRequiredService() 来获取它,所以也许还有另一种方法可以做到这一点,但我还没有看到任何文档。
这是我第一次使用这个组件,所以我确信还有其他方法可以达到我想要的效果,我只是还没有找到与 ASP 以外的任何内容相关的 MS 网页或博客。 NET 实现,这是一个控制台应用程序,没有 Web 部件。
预先感谢您的想法和建议。
在花了几天时间尝试解决该组件的 MS Learn 文档与您在实际位和运行时行为中看到的内容之间的脱节之后,我通读了处理该组件的团队成员之间交换的对话。
据我所知,问题不在 MemroyCache 的基本代码中,而是更深入,深入到 Net Framework 本身,我正在运行 Net8。不幸的是,没有给出关于该主题的具体细节,使得 MemoryCache 在某种程度上成为一个黑匣子。在问题严重的地方,我们决定封锁一些属性和方法,使它们不可用或返回 null 或零。
我确信有比我更聪明的开发人员,他们可以解决这些问题并仍然使其适用于他们的特定情况,但这需要我无法承诺的时间和精力。
我的选择是:
我选择了选项2
尽管如此,对于像宣传的那样工作的 MemoryCache 部分,我的应用程序的性能改进是巨大的,将处理时间从几分钟缩短到几秒钟。因此,对于任何处理大量数据和长处理时间的应用程序来说,MemoryCache 的核心目标仍然是坚实且具有挑战性的。希望 MS 能够尽快解决核心问题。