Episerver中如何用GetBySegment方法替代GetChildren().FirstOrDefault()?
解决方案:替代GetChildren的高性能实现(无需硬编码URL/位置)
首先,直接用GetBySegment()并不适合你的场景——因为该方法必须指定父节点引用和URL段(urlSegment),但你的页面位置、URL会随环境变化,无法固定这两个参数,因此没法用它来替代现有实现。
针对你的场景(系统中仅存在一个PageTypeA实例,且页面位置不固定),可以用以下两种性能更优的方式替代原GetChildren().FirstOrDefault():
方法1:使用IContentLoader.GetItems递归查询
该方法会递归遍历指定根节点下的所有内容,筛选出PageTypeA类型的页面,性能远优于GetChildren()(后者仅查询直接子节点,且会加载所有子节点再过滤):
public virtual PageTypeA GetPageTypeA() { // 递归遍历根节点下所有内容,查找PageTypeA类型的页面 var pageTypeA = _contentLoader.GetItems<PageTypeA>( ContentReference.RootPage, recursive: true, new LoaderOptions { new LanguageLoaderOption(LanguageSelector.AutoDetect()) } ).FirstOrDefault(); return pageTypeA; }
方法2:使用IContentRepository.FindPagesByCriteria精准查询
通过内容类型ID构建查询条件,直接定位到PageTypeA类型的页面,性能最优:
public virtual PageTypeA GetPageTypeA() { var contentTypeRepo = ServiceLocator.Current.GetInstance<IContentTypeRepository>(); var pageTypeA = contentTypeRepo.Load<PageTypeA>(); var criteria = new PropertyCriteriaCollection { new PropertyCriteria { Condition = CompareCondition.Equal, Name = "PageTypeID", Value = pageTypeA.ID.ToString(), Type = PropertyDataType.PageType } }; // 从根节点开始查询匹配条件的页面 var matchingPages = _contentRepository.FindPagesByCriteria(ContentReference.RootPage, criteria); return matchingPages.FirstOrDefault() as PageTypeA; }
为什么这两种方法比原实现好?
- 原
GetChildren()仅查询根节点的直接子节点,若PageTypeA页面移动到其他层级会直接失效;而上述两种方法会递归查找所有层级,适配页面位置变化。 - 性能更优:
GetItems()和FindPagesByCriteria()都是基于Episerver的底层索引查询,避免了加载大量无关内容再过滤的开销。
内容的提问来源于stack exchange,提问作者Eetu Palo
相关产品推荐
相关产品推荐

