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