Sitefinity:使用字段值进行动态内容查询优化

Sitefinity: Dynamic Content query optimization with field values

我将尝试尽可能具体。所以我们使用 Sitefinity 8.1.5800,我有几个名为 ReleaseNotes 和 ReleaseNoteItems 的动态内容模块。 ReleaseNotes 有一些字段但没有对 ReleaseNoteItems 的引用。

Release Note Items 有字段和 ReleaseNotes 的相关数据字段。

所以我可以在不到一秒的时间内将所有 ReleaseNoteItems 作为动态内容进行查询。

然后我使用 sitefinity 提供的这些对象并将它们映射到 C# 对象,以便我可以使用强类型。此映射过程花费了将近一分钟的时间,并且仅对 322 个项目 (N+1) 使用了 600 多个查询。

简而言之:我需要比现在更快地获取所有 sitefinity 对象并将它们映射到可用的 c# 对象。

获取动态内容项的方法(需要毫秒):


private IList<DynamicContent> GetAllLiveReleaseNoteItemsByReleaseNoteParentId(Guid releaseNoteParentId)
       {
           DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(String.Empty);
           Type releasenoteitemType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ReleaseNoteItems.Releasenoteitem");
           string releaseNoteParentTypeString = "Telerik.Sitefinity.DynamicTypes.Model.ReleaseNotes.Releasenote";
           var provider = dynamicModuleManager.Provider as OpenAccessDynamicModuleProvider;
           int? totalCount = 0;

           var cultureName = "en";
           Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureName);


           Type releasenoteType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ReleaseNotes.Releasenote");

           // This is how we get the releasenote items through filtering

           DynamicContent myCurrentItem = dynamicModuleManager.GetDataItem(releasenoteType, releaseNoteParentId);

           var myMasterParent =
               dynamicModuleManager.Lifecycle.GetMaster(myCurrentItem) as DynamicContent;

           var relatingItems = provider.GetRelatedItems(
                releaseNoteParentTypeString,
                "OpenAccessProvider",
                myMasterParent.Id,
                string.Empty,
                releasenoteitemType,
                ContentLifecycleStatus.Live,
                string.Empty,
                string.Empty,
                null,
                null,
                ref totalCount,
                RelationDirection.Parent).OfType<DynamicContent>();
           IList<DynamicContent> allReleaseNoteItems = relatingItems.ToList();

           return allReleaseNoteItems;
       }

这是将 sitefinity 对象映射到 C# 对象的方法,需要将近一分钟的时间:

public IList<ReleaseNoteItemModel> GetReleaseNoteItemsByReleaseNoteParent(ReleaseNoteModel releaseNoteItemParent)
       {

          return  GetAllLiveReleaseNoteItemsByReleaseNoteParentId(releaseNoteItemParent.Id).Select(rn => new ReleaseNoteItemModel
           {

               Id = rn.Id,
               Added = rn.GetValue("Added") is bool ? (bool)rn.GetValue("Added") : false,
               BugId = rn.GetValue<string>("bug_id"),
               BugStatus = rn.GetValue<Lstring>("bugStatus"),
               Category = rn.GetValue<Lstring>("category"),
               Component = rn.GetValue<Lstring>("component"),
               @Content = rn.GetValue<Lstring>("content"),
               Criticality = rn.GetValue<Lstring>("criticality"),
               Customer = rn.GetValue<string>("customer"),
               Date = rn.GetValue<DateTime?>("date"),
               Grouped = rn.GetValue<string>("grouped"),
               Override = rn.GetValue<string>("override"),
               Patch_Num = rn.GetValue<string>("patch_num"),
               PublishedDate = rn.PublicationDate,
               Risk = rn.GetValue<Lstring>("risk"),
               Title = rn.GetValue<string>("Title"),
               Summary = rn.GetValue<Lstring>("summary"),
               Prod_Name = rn.GetValue<Lstring>("prod_name"),
               ReleaseNoteParent = releaseNoteItemParent,
               McProductId = GetMcProductId(rn.GetRelatedItems("McProducts").Cast<DynamicContent>()),

           }).ToList();

       }

有什么方法可以将这一切优化为一个查询或更好的方法吗?花费将近一分钟来映射这些对象对于我们需要对它们做的事情来说太长了。

如果没有办法,我们将不得不缓存项目或进行 SQL 查询。如果不需要,我宁愿不进行缓存或 SQL 查询。

在此先感谢您提供的所有帮助,我是新手在 Whosebug 上发布问题,所以如果您需要任何其他数据,请告诉我。

我可以想象单个发行说明下的每个发行说明项目都与同一产品相关,不是吗?

如果是这样,是否需要为每个项目执行 GetMcProductId 方法?

您对这些项目进行 .ToList() 是有原因的吗?你有没有可能避免这种情况。在我看来,大部分时间(1 分钟)都用于将所有项目转换为列表。从 Sitefinity 对象到 C# 对象的转换不是这里的罪魁祸首。

在这里查看 Arno 的回答:https://plus.google.com/u/0/112295105425490148444/posts/QrsVtxj1sCB?cfem=1

您可以使用 "Content links manager" 更快地查询动态模块关系(通过父项 -ParentItemId- 或通过子项 -ChildItemId-):

var providerName = String.Empty;
var parentTitle = "Parent";
var relatedTitle = "RelatedItem3";

DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(providerName);
Type parentType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ParentModules.ParentModule");
Type relatedType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.RelatedModules.RelatedModule");

ContentLinksManager contentLinksManager = ContentLinksManager.GetManager();

// get the live version of all parent items
var parentItems = dynamicModuleManager.GetDataItems(parentType).Where(i => i.GetValue<string>("Title").Contains(parentTitle) && i.Status == ContentLifecycleStatus.Live && i.Visible);

// get the ids of the related items.
// We use the OriginalContentId property since we work with the live vesrions of the dynamic modules
var parentItemIds = parentItems.Select(i => i.OriginalContentId).ToList();

// get the live versions of all the schedules items
var relatedItems = dynamicModuleManager.GetDataItems(relatedType).Where(i => i.Status == ContentLifecycleStatus.Live && i.Visible && i.GetValue<string>("Title").Contains(relatedTitle));

// get the content links
var contentLinks = contentLinksManager.GetContentLinks().Where(cl => cl.ParentItemType == parentType.FullName && cl.ComponentPropertyName == "RelatedField" && parentItemIds.Contains(cl.ParentItemId) && cl.AvailableForLive);

// get the IDs of the desired parent items
var filteredParentItemIds = contentLinks.Join<ContentLink, DynamicContent, Guid, Guid>(relatedItems, (cl) => cl.ChildItemId, (i) => i.OriginalContentId, (cl, i) => cl.ParentItemId).Distinct();

// get the desired parent items by the filtered IDs
var filteredParentItems = parentItems.Where(i => filteredParentItemIds.Contains(i.OriginalContentId)).ToList();