我有一个应用程序,它与ASP.NET实体6框架一起编写在ASP.NET MVC5框架的顶部。
通常,缓存关系确实没有帮助。但是,我有一个案例,相关数据永远不会改变,但父母会这样做。我正在寻找一种缓存关系的方法,所以每次加载页面时我都不必进行硬读取。
我有以下两个类
public class Item
{
public string Id { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public decimal Rate { get; set; }
...
...
public virtual ICollection<ItemRecord> Records { get; set; }
}
public class ItemRecord
{
public string Id { get; set; }
public string Title { get; set; }
public decimal Description { get; set; }
public decimal Amount { get; set; }
[ForeignKey("Item")]
public int ItemId { get; set; }
...
...
public virtual ItemRecord Item { get; set; }
}
在控制器中的Index
操作中,我可以使用以下linq语句获取数据。
public ActionResult Index(int? id)
{
if(id.HasValue)
{
var items = Context.Items.Where(item => item.CategoryId == id.Value)
.Include(x => x.Records)
.ToList();
}
....
}
由于Item
模型一直在变化,我不想缓存它。但是,我希望缓存Records
关系中的所有数据,因为它永远不会更改,而且它是大数据集。
问题
如何在上面的示例中缓存Records
关系?
我尝试使用OutputCache
属性来缓存这样的关系
public class Item
{
public string Id { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public decimal Rate { get; set; }
...
...
[OutputCache(Duration = 3600, VaryByParam = "CategoryId", Location = OutputCacheLocation.Server)]
public virtual ICollection<ItemRecord> Records { get; set; }
}
你可以告诉它不起作用,这是我得到的错误
属性&#39; OutputCache&#39;对此声明类型无效。它是 仅适用于&#39;类,方法&#39;声明。
显然OutputCache
用于缓存类而不是实体关系。
答案 0 :(得分:1)
不,OutputCache
用于缓存操作的响应。它实际上缓存了整个响应,因此动作本身不必运行。它不适合您只想缓存特定数据的情况。
为此,您需要像MemoryCache
或像Redis这样的NoSQL解决方案。 MemoryCache
通常更容易使用,但有一些重要的限制:
顾名思义,缓存是在内存中,因此只有在保留内存时才能存活。也就是说,重新启动服务器,或者只是让AppPool停止,作为正常回收,显式关闭或崩溃的一部分,将擦除您缓存的所有内容。它也将受到正常内存优化的影响。例如,如果操作系统需要为另一个进程回收内存,那么缓存将是首先要牺牲的事情之一。
它是流程限制的,如果你正在使用多个进程(web园),缓存将是每个进程唯一的,这可能意味着在内存中多次包含相同的数据,每个进程一次。
如果你想要一个更稳定的缓存,你需要使用类似Redis的东西,它也是一个内存系统,由文件系统支持,也可以分发。这意味着您可以在完全不同的服务器或甚至多个不同的服务器上运行它以实现故障转移冗余。这将更难实现,因为您必须实际设置Redis并配置与它的连接,但我特别推荐Redis,因为Microsoft已经做了很多工作以确保它在Windows上都能很好地运行以及ASP.NET应用程序之类的东西。 Redis实际上是Azure Cache背后的支持,因此他们的动机是使其无缝化并保持更新等。