【问题标题】:Checking each node in a tree structure, Umbraco (improving efficiency)检查树结构中的每个节点,Umbraco(提高效率)
【发布时间】:2012-07-10 00:23:34
【问题描述】:

我正在编写一些 C#(.NET) 来使用 Umbraco 4.7 将文章导入博客。简而言之,该算法旨在循环遍历每一篇现有文章,并检查它是否与我们试图从 XML 中提取的新文章具有相同的 ID。该算法运行良好,但我不禁认为有四个 foreach 循环对于我正在做的事情来说效率非常低。

foreach (Document yearNode in node.Children) //News > Years
{
    foreach (Document monthNode in yearNode.Children) //Years > Months
    {
        foreach (Document dayNode in monthNode.Children) //Months > Days
        {
            foreach (Document newsItem in dayNode.Children) //Days > Articles
            {
                // If there isn't an ID match, go ahead and create a new article node.         
            }

这是没有主要功能的基本算法,只是 foreach 循环。它比简单地循环浏览日历日期要复杂一些,因为它更多的是包含特定节点的文件夹结构。任何人都可以提出一种简化这一点的方法吗?

【问题讨论】:

  • Document 类型是否高于 Umbraco 特定类型?
  • 是的,是的。业务逻辑的一部分,link
  • 有没有机会建立文档文件夹结构的缓存,并在缓存中执行快速查找?
  • 如何检索根节点 (node)?也许您可以通过他们的DocumentType 查询叶节点?
  • 谢谢你,@MarkusJarderot,但你能解释一下你的意思吗?第一次用 Umbraco 和 C#,感觉一切都是一个节点!

标签: c# algorithm foreach umbraco


【解决方案1】:

使用通过DocumentType 获取所有文章节点的想法,您可以使用this GetDescendants extension method 的等效项来遍历特定文档类型的节点。

该方法是专门为 NodeFactory 的 Node 类编写的,但可以很容易地为 Document 重写。要使用扩展方法,您需要创建一个新类并将其设为静态。示例:

using System;
using System.Collections.Generic;
using umbraco.cms.businesslogic.web;

namespace Example
{
    static class Extensions
    {
        public static IEnumerable<Document> GetDescendants(this Document document)
        {
            foreach (Document child in document.Children)
            {
                yield return child;

                foreach (Document grandChild in child.GetDescendants())
                {
                    yield return grandChild;
                }
            }
            yield break;
        }
    }
}

然后在我们的上下文中使用该方法:

var myDocuments = new Document(folderId)
    .GetDescendants()
    .Cast<Document>()
    .Where(d => d.ContentType.Alias == "myDocumentType");

if (myDocuments.Any(d => d.Id == myId))
{
    ...
}

注意:我不知道为什么,但似乎.GetDescendants() 之后需要.OfType&lt;Document&gt;().Cast&lt;Document&gt;()。 (请参阅下面的编辑

使用 NodeFactory 的 Node 比使用 Document 更有效,因为 NodeFactory 从 XML 缓存中提取它的信息,并且不会像 Document 那样每次都调用数据库。使用 NodeFactory 的唯一缺点是它只包含那些已发布的节点,但通常您无论如何都只想使用这些节点。见Difference between Node and Document

编辑:在做了一些修改之后,我发现Document 已经包含了一个GetDescendants() 方法并且返回了一个IEnumerable,这就是为什么我们必须使用.Cast&lt;Document&gt;() .因此,如果您选择仍然使用Document,看起来您可以避免创建扩展方法。否则,如果您仍想使用上述扩展方法,则需要将其重命名为其他名称。

【讨论】:

  • +1 来自 dludlow 的另一个纯正答案。干得漂亮,继续努力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-17
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
相关资源
最近更新 更多