访问内存缓存是否创建副本

本文关键字:创建 副本 是否 缓存 内存 访问 | 更新日期: 2023-09-27 18:33:42

我有一个这样的缓存服务:

public interface ICacheService {
    T Get<T>(string cacheID, Func<T> getItemCallback, int cacheMinutes = 5) where T : class;
}
public class MemoryCacheService : ICacheService {
    public T Get<T>(string cacheId, Func<T> getItemCallback, int cacheMinutes = 5) where T : class {
        T item = MemoryCache.Default.Get(cacheId) as T;
        if (item == null) {
            item = getItemCallback();
            MemoryCache.Default.Add(cacheId, item,
                new CacheItemPolicy {AbsoluteExpiration = DateTime.Now.AddMinutes(cacheMinutes)});
        }
        return item;
    }
}

并像这样检索:

var result = _cache.Get("mylist", () => _database.Fetch<MyList>().AsQueryable(), 600);

该列表很大,并且经常在每次击键键入的预先下拉列表中访问。 并且查询条件也是动态的,例如

if (this) result = result.Where(x=> this ...)
if (that) result = result.Where(x=> that ...)
finally result.ToList() 

想知道,每次我从缓存访问列表时,系统是否在开始构建 linq 查询之前创建数据的副本? 如果是这样,就像每次击键复制一样,效率不高。 还是因为它正在检索 AsQueryable 并构建 linq 而延迟了查询?

还有更好的选择吗? 谢谢

访问内存缓存是否创建副本

不,MemoryCache 不会创建副本。您基本上在缓存中存储对某个对象实例的引用,这就是您在访问缓存中的项目时得到的。

我没有正式的文档链接,但在实践中发现了"困难的方法",我只使用我返回的引用(不复制它)不小心修改了缓存的对象。

此外,研究参考源 (http://referencesource.microsoft.com) 表明不会发生自动复制。

根据您的应用程序和需求,您可能希望确保缓存的类型在设计上实际上是不可变的。

在不迷失在 MemoryCache 的细节中,你可以用基本的 .NET 设计原则来推理这一点。 只有值类型易于复制。 除了 [可序列化] 和非常破碎的 ICloneable 之外,没有复制引用类型的通用机制。 这不是将对象放入内存缓存的要求。 所以没有。

缓存对象非常非常简单。 一个简单的列表<>就可以完成这项工作。 您从 MemoryCache 获得的附加值是有效缓存的另一个基本功能。 退休政策。 没有策略的缓存是内存泄漏。