1

我的应用程序具有以下实体(产品和模型之间具有多对多关系):

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 个项目。

我一直在绞尽脑汁试图想出一种更好的方法来做到这一点,但到目前为止我还没有想法。不幸的是,现阶段无法修改我的模型和数据库。

我会很感激帮助。谢谢

4

1 回答 1

0

解决问题的关键是了解实体和查询缓存的工作方式。

实体缓存本质上存储实体的 POID 及其属性值。

当您想要获取/初始化一个实例时,NH 将首先检查缓存以查看值是否存在,以避免数据库查询。

另一方面,查询缓存将查询存储为键(为了简化,假设它是命令文本和参数值),以及实体 ID 列表作为值(假设您的结果是实体列表,而不是投影)

当 NH 执行一个可缓存的查询时,它会查看结果是否被缓存。如果是,它将从这些 id 加载代理。然后,当您使用它们时,它会从实体缓存或数据库中一一初始化它们。

集合缓存类似。

通常,为这些实体加载获得许多二级缓存命中是一件好事。当然,除非您使用位于单独机器中的分布式缓存,在这种情况下,这几乎与从数据库中获取它们一样糟糕。

如果是这种情况,我建议您跳过缓存查询。

于 2013-05-30T13:23:51.677 回答