[英]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.