2012-02-23 43 views
0

我有这个模型如何使用nhibernate加载父级后加载子集合?

Product 
- int Id 
- string Name 
- List<ProductChannelAffectation> Affectations 

ProductChannelAffectation 
- Channel Channel 
- Product Product 
- double Price 

所以我想匹配的一些情况和他们在2个查询(没有N + 1分的问题)做作的10第一个产品,如果可能在1个一趟DB。

所以我读了这个答案

https://stackoverflow.com/a/7035649/277067 或这一个 https://stackoverflow.com/a/5285739/277067

但这里有2问题:

  • 条件被复制“其中(x => X。 Id == ID)“,在2个查询中,没关系,但条件很简单,但如果条件复杂(涉及其他表格,文本搜索...)

  • 没有“最高”条件。

延迟加载导致N + 1问题。

我尝试这样

var products = _nhSession.QueryOver<Product>() 
    .Where(...) 
    .Take(10) 
    .List() 
    .ToList(); 
var idsproduct = products.Select(p => p.ID); 
var affectation = _nhSession.QueryOver<ProductChannel>() 
    .Where(c => c.Product.ID.IsIn(idsproduct)) 
    .ToList(); 

但仍然有N + 1(用于获取做作)执行第二查询之前。

这里是我的联想是如何宣称

<bag name="Affectations" access="property" table="Product" lazy="false"> 
     <key column="n_Product" /> 
     <one-to-many class="CTV.ProductChannel, CTV" /> 
    </bag> 

我做我的声明用ActiveRecord。

回答

1

你试过设置批量大小

<bag name="Affectations" ... batch-size='50'> 

这会阻止你的n + 1个问题,并让你保持延迟加载。基本上将批量大小设置为50会将发给数据库的查询量减少50倍。如果没有设置,如果您有99行,则会向批处理大小设置的数据库发出99个查询,您将发出2.

+0

我确实在我的问题后发现它。但它不像你在这里看到的那样行事:http://stackoverflow.com/a/6293687/277067。该文档是错误的。 – 2012-02-23 16:50:51

+0

什么不行? 'batch-size'将解决您的问题,您指出的问题是“批量大小如何工作”。你试过了,看看生成的SQL吗? – Rippo 2012-02-24 04:05:30

+0

是的,例如,如果我的批量为50,并且我有30个产品,它会首先加载25个产品的缺点,然后加载5个产品的缺陷。 – 2012-02-24 07:01:54

0
// subquery for the ids 
var idsproduct = QueryOver.Of<Product>() 
    .Where(...) 
    .Take(10); 
var affectation = _nhSession.QueryOver<Product>() 
    .WithSubquery.Where(p => p.ID).In(idsproduct)) 
    .Fetch(p => p.Affectations).Eager 
    .ToList();