我的应用程序具有以下实体(产品和型号之间存在多对多关系):
public class TopProduct {
public virtual int Id { get; set; }
public virtual Product Product { get; set; }
public virtual int Order { get; set; }
}
public class Product {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Model> Models { get; set; }
}
public class Model {
public virtual string ModelNumber { get; set; }
public virtual IList<Product> Products { get; set; }
}
注意:产品可能有1000个型号。
我需要显示TopProducts列表和前5个模型(按字母顺序排列)。
例如说我有以下查询:
var topProducts = session.Query<TopProduct>()
.Cacheable()
.Fetch(tp => tp.Product).ThenFetchMany(p => p.Models)
.OrderBy(tp => tp.Order)
.ToList();
如果我现在说:
foreach (var topProduct in topProducts) {
var models = topProduct.Product.Models.Take(5).ToList();
...
}
执行速度非常慢,因为它从每个模型的二级缓存中检索项目。由于产品可能有1000个模型,因此第二次执行时需要从缓存中检索1000个项目。
我一直绞尽脑汁试图想出一个更好的方法来做到这一点,但到目前为止,我已经没有想法了。不幸的是,我的模型和数据库在此阶段无法修改。
我很感激帮助。感谢
答案 0 :(得分:0)
问题的关键是了解实体和查询缓存的工作原理。
实体缓存存储,实质上是实体的POID及其属性值。
当您想要获取/初始化实例时,NH将首先检查缓存以查看值是否存在,以避免数据库查询。
另一方面,查询缓存将查询存储为键(为了简化,假设它是命令文本和参数值),并将实体ID列表作为值(这假设您的结果是实体列表,而不是投影)
当NH执行可缓存的查询时,它将查看结果是否被缓存。如果是,它将从这些ID加载代理。然后,当您使用它们时,它将逐个初始化它们,可以是实体缓存,也可以是数据库。
集合缓存类似。
通常,为这些实体加载获取许多二级缓存命中是一件好事。当然,除非您使用位于单独计算机中的分布式缓存,否则这几乎与从数据库中获取它们一样糟糕。
如果是这种情况,我建议您跳过缓存查询。