2011-03-14 151 views
2

我有一个名为Category的对象,它具有Id,Name和OwnerId。然后我嵌套这些来创建子类别。如果一个类别拥有一个所有者ID,它就是一个子类别。子类别的数量是无限的,但每个项目只能有1个父项目。够简单。Linq to SQL嵌套对象

我的问题是,我需要装后访问一个子类别。我如何使用Linq获得拥有类别。我知道主人身份证,但我不知道主人可能有多少深度。

基本上,我正在寻找一种方式来获得类别或子类别其中ID = = X,但这种能够生活在一个子类6级以上深。

我试图避免在每个子类的每个子类循环....

回答

0

在MS SQL 2005和最多可以创建递归查询。但是,在LINQ to SQL中,你运气不佳。如果不重构数据库中的数据,则无法在单个数据库调用中遍历树。

但是...有1个解决方法我能想到的。如果能够将单个树(或树的一部分)的所有Category元素分组在一起,则可以在单个语句中预加载完整树的该部分。之后,您将能够遍历该树的该部分,而不会触发对数据库的新调用。它看起来像这样:

// Load the category that will be used as starting point. 
var subCategory = db.Categories.Single(c => c.Id == 56); 

// Performance: Load the complete group in one go. 
var categories = (
    from category in db.Categories 
    where category.GroupId == subCategory.GroupId 
    select category) 
    .ToArray(); 

// Traverse the tree and get the top-most parent (if any). 
var parent = subCategory.GetParents().LastOrDefault(); 

// Extension method to get the parents. 
public static IEnumerable<Category> GetParents(
    this Category category) 
{ 
    while (category.Parent != null) 
    { 
     // NOTE: cat.Parent will not cause a database call 
     // when the Parent is already loaded by L2S. 
     yield return cat.Parent; 
     category = category.Parent; 
    } 
} 

这当然只有在你能够确定元素为一个组时才有用。这个解决方案是否会更快取决于组的大小。当您加载(并且不使用)的对象组非常大时,它实际上会减慢应用程序的速度。

1

有存储/检索树层次结构为this fogbugz博客中解释另一种方式:

原来有这个问题,通过 乔·塞科解释一个很酷的 解决方案。而不是尝试 维护一堆父/子 关系遍布您的数据库 - 这将需要递归SQL查询来查找所有节点的后裔 - 我们标记每个 案例与“左”和“右边“值 通过遍历树 深度优先计算,并随着我们走。一个 节点的“左”值被设置时,它 穿越过程中第一次看到,而且走路时 备份树从节点离开 “正确”的值设置。 一张图片可能更有意义:

enter image description here

嵌套组SQL模式让我们添加 情况下层次结构在不牺牲性能的 。

这有什么用?现在我们只是要求 所有例2和9之间的“左”值 找到所有B的 后代在一个快速,索引 查询。的G祖先是由 发现要求与“左”小于 6(G自己的“左”)和“右”大 比6.适用于所有的数据库节点。查询大 层次

Here's another post进入更详细特别是当 - 大大提高了性能。它使用Sqlphp编写,但我认为你可以获得它的要点,并很容易在Linq中转换为Sql。