在迭代我仅通过迁移创建的自定义类型的 ContentItem 集合时,我遇到了一些 n+1 性能问题。
ContentDefinitionManager.AlterPartDefinition("MyType", part => part
.WithField("MyField", field => field
...
)
);
ContentDefinitionManager.AlterTypeDefinition("MyType", type => type
.WithPart("MyType")
);
每次我访问这部分的一个字段时,都会执行一个新查询。对于预定义的部分,我可以使用 QueryHints 来避免这种情况
var myItems = _orchardServices.ContentManager.Query().ForType("MyType")
.WithQueryHints(new QueryHints().ExpandParts<LocalizationPart()
...
);
但是我也可以为我的自定义类型的 ContentPart 执行此操作吗?这似乎不起作用:
var myItems = _orchardServices.ContentManager.Query().ForType("MyType")
.WithQueryHints(new QueryHints().ExpandParts<ContentPart>()
...
);
我如何告诉 Orchard 一口气搞定所有东西?我希望能够在不编写自己的 HQL 或直接寻址存储库的情况下做到这一点。
例子:
var myItems = _orchardServices.ContentManager.Query().ForType("MyType");
@foreach(var item in myItems.Take(100)) {
foreach(var term in item.Content.MyItem.MyTaxonomyField.Terms) {
// Executes 100 queries
<div>@term.Name</div>
}
}
TaxonomyField 不存储 id,在循环内使用 TaxonomyService 不会提高性能。现在,为了解决这个问题,我TermContentItems.Where(x => myItems.Select(i => i.Id).Contains(TermPartRecord.Id))
从循环外部的存储库中获取所有内容,以及该字段正在使用的分类法的所有术语的列表。然后在循环内:
var allTermsInThisField = termContentItems.Where(tci => tci.TermsPartRecord.Id == c.Id)
.Select(tci => terms.Where(t => t.Id == tci.TermRecord.Id).Single()).ToList()
我不是一个非常有经验的程序员,但这是我可以在不深入研究 HQL 的情况下了解如何做到这一点的唯一方法,而且对于我的目的来说它似乎过于复杂。Orchard 能否以更少的步骤完成此任务?