繁体   English   中英

递归类别和内部联接使用

[英]Recursive category and inner join using

我想创建递归类别。使用连接时不加载任何项目。我不希望外部连接,因为如果类别中没有项目,则不显示。我该如何解决这个问题?

public string CategoryTree(int depth)
{
    StringBuilder sBuilder;   
    using (DataContext db = new DataContext())
    {
        var query = from n in db.Categories join m in db.Products on n.CatId equals m.CategoryId where n.ParentId == depth select new{n, m};
        sBuilder = new StringBuilder("<ul>");
        foreach (var q in query)
        {
            sBuilder.Append("<li>");
            sBuilder.Append("<a href='/Product/"+q.m.ProdId+">'"+q.n.Title+"</a>"+CategoryTree(q.n.CatId));
            sBuilder.Append("</li>");
        }
        sBuilder.Append("</ul>");
    }
    return sBuilder.ToString();
}

Categories
+---------+---------------+------------+
| CatId   | Title         | ParentId   |
+---------+---------------+------------+
|    1    | Electronic    |   NULL     |
+---------+---------------+------------+
|    2    | Computer      |   NULL     |
+---------+---------------+------------+
|    3    | Television    |     1      |
+---------+---------------+------------+
|    4    | Led           |     3      |
+---------+---------------+------------+
|    5    | Printer       |     2      |
+---------+---------------+------------+
|    6    | Laser Printer |     5      |
+---------+---------------+------------+

Products
+---------+---------------+------------+
| ProdId  | ProductName   | CategoryId |
+---------+---------------+------------+
|    1    | Samsung LED   |      4     |
+---------+---------------+------------+
|    2    | Sony LED TV   |      4     |
+---------+---------------+------------+    

我将您的代码直接转换为更可行的递归函数。 我将其拆分为两个以避免实例化多个DataContext类(这可能非常慢)。 而且我还使用Linq到XML来使代码更安全地编写。

public string CategoryTree(int? parentId)
{
    using (DataContext db = new DataContext())
    {
        return CategoryTree(db, parentId).ToString();
    }
}

private XElement CategoryTree(DataContext db, int? parentId)
{
    return new XElement(
        "ul", 
        from n in db.Categories
        join m in db.Products on n.CatId equals m.CategoryId
        where n.ParentId == parentId
        select new XElement(
            "li",
            new XElement(
                "a",
                new XAttribute(
                    "href",
                    "/Product/" + m.ProdId),
                n.Title),
            CategoryTree(db, n.CatId)));
}

现在,这当然不起作用,因为对于parentId等于null ,将不返回任何元素,因为您的数据在该级别上没有任何乘积,因此联接不返回任何内容。 您必须在获取产品之前构建类别树。

所以这是您真正需要做的:

private XElement CategoryTree(DataContext db, int? parentId)
{
    return new XElement(
        "ul", 
        from n in db.Categories
        where n.ParentId == parentId
        select new XElement(
            "li",
            new XElement(
                "span",
                n.Title),
            from m in db.Products
            where m.CategoryId == n.CatId
            select new XElement(
                "div",
                new XElement(
                    "a",
                    new XAttribute(
                        "href",
                        "/Product/" + m.ProdId),
                    m.ProductName)),
            CategoryTree(db, n.CatId)));
}

现在,将构建以下树:

<ul>
  <li>
    <span>Electronic</span>
    <ul>
      <li>
        <span>Television</span>
        <ul>
          <li>
            <span>Led</span>
            <div>
              <a href="/Product/1">Samsung LED</a>
            </div>
            <div>
              <a href="/Product/2">Sony LED TV</a>
            </div>
            <ul />
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <span>Computer</span>
    <ul>
      <li>
        <span>Printer</span>
        <ul>
          <li>
            <span>Laser Printer</span>
            <ul />
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

但是,您不希望任何不包含产品的类别。 但是我们在构建树时不知道哪些不这样做,因此我们必须在以后修剪。

这是我修剪的方法:

public string CategoryTree(int? parentId)
{
    using (DataContext db = new DataContext())
    {
        var tree = CategoryTree(db, parentId);
        Action<string> prune = tag =>
        {
            foreach (var empty in tree
                .Descendants(tag)
                .Where(ul => !ul.Descendants("a").Any())
                .ToArray())
            {
                empty.Remove();
            }
        };
        prune("ul");
        prune("li");
        return tree.ToString();
    }
}

我首先修剪无产品的ul标签,但这仍然可以保留无产品的li标签,因此我也必须修剪那些产品。

这是最终结果:

<ul>
  <li>
    <span>Electronic</span>
    <ul>
      <li>
        <span>Television</span>
        <ul>
          <li>
            <span>Led</span>
            <div>
              <a href="/Product/1">Samsung LED</a>
            </div>
            <div>
              <a href="/Product/2">Sony LED TV</a>
            </div>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

我希望这是您想要的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM