我有一个自定义的Sitecore命令,我想扩展它以确定当前项目是否具有与某个模板ID匹配的父项。
单击命令/按钮后,我将可以访问当前的Item
。
我最初的尝试,因为我遇到了escaping the FullPath
for use in a query的问题,就是遍历父项(然后是该项的父项等)以确定是否有任何匹配的模板。
然而,似乎应该有更好的方法来做到这一点。
所以给定一个项目,找出它是否具有某个模板的父项的最佳方法是什么?
答案 0 :(得分:0)
这不是一个好方法。在常规系统中,您可以在SQL中执行此操作,但Sitecore已经混淆了他们的Nexus'我认为代码是所有这些数据访问/映射逻辑发生的地方因此我不知道Sitecore的那部分是如何工作的,因此很难设法对查询进行反向工程以有效地执行此操作。 / p>
我在项目中使用的是我使用这样的递归函数。 我使用委托来确定该项是否与我正在寻找的内容相匹配,并且只是递归树 - 如果它到达根节点则退出返回null。
public delegate bool ItemSelectionCondition(Item sitecoreItem);
public static Item GetAncestor(Item sitecoreItem, ItemSelectionCondition selectionCondition)
{
Item parent = sitecoreItem.Parent;
if (selectionCondition(parent))
{
return parent;
}
else if (Sitecore.ItemIDs.RootID == parent.ID)
{
return null;
}
else
{
return GetAncestor(parent, selectionCondition);
}
}
因此,为了解决这个问题,你需要定义类似的东西:
public static bool IsTemplateX(Item item)
{
return item.TemplateID == Constants.TemplateXId;
}
这是一个非常简单的解决方案,足以灵活地处理我需要做的任何Ancestor或Parent类型的事情。
请注意,如果Sitecore没有缓存它需要查看的所有项目,那么第一次运行需要几秒钟,但随后需要花费大量时间。
编辑:由于这个答案已经得到了一些支持,我想我会解释为什么它是Sitecore中最好的方法。为什么递归方法更好,迭代是双重的,这就是共鸣。首先,它的代码较少,所以它看起来更好 - 但如果这还不够,第二个原因就是如果你要小心你如何构建你的代码并编译你的项目你将能够利用尾递归。
在Sitecore的更高版本中使用Item.Axes.Ancestors
(或Item.Axes.GetAncestors()
)的原因很糟糕是因为它有五个步骤:
这意味着您进行两倍的分配,就好像只是递归到内容树的顶部一样,但是您也排除了在第一个相关时退出递归的可能性。 item - 并避免对数据库进行不必要的调用。
我必须承认,关于使用Lucene索引的评论是正确的 - 这是几乎在所有情况下可能最快的方式,因为它可以减少您将项目缩短到单个时间的时间Sitecore查询 - 如果您索引有关您所需祖先的数据,则不会发生Sitecore查询。
答案 1 :(得分:0)
SXA方式
public static Item GetParentOfTemplate(this Item item, ID templateId)
{
if (item == null)
{
return null;
}
ItemRelationCacheValue itemRelationCacheValue = ParentOfTemplateCache.GetCacheForDatabase(item.Database.Name)?.Get(item, templateId);
if (itemRelationCacheValue != null)
{
return item.Database.GetItem(itemRelationCacheValue.OutputID);
}
Template template = TemplateManager.GetTemplate(templateId, item.Database);
if (template == null)
{
return null;
}
ID iD = item.ID;
while (item != null)
{
Template template2 = TemplateManager.GetTemplate(item);
if (template2 != null && template2.DescendsFromOrEquals(template.ID))
{
ItemRelationCacheValue value = new ItemRelationCacheValue(iD, item.Database.Name, templateId, item.ID);
ParentOfTemplateCache.GetCacheForDatabase(item.Database.Name)?.Set(value);
return item;
}
item = item.Parent;
}
return null;
}