假设具有以下CTE,这些CTE返回我已经拥有的某些树数据(邻接模型)的级别(取自Linq中的分层数据- options和performance):
WITH hierarchy_cte(id, parent_id, data, lvl) AS ( SELECT id, parent_id, data, 0 AS lvl FROM dbo.hierarchical_table WHERE (parent_id IS NULL) UNION ALL SELECT t1.id, t1.parent_id, t1.data, h.lvl + 1 AS lvl FROM dbo.hierarchical_table AS t1 INNER JOIN hierarchy_cte AS h ON t1.parent_id = h.id ) SELECT id, parent_id, data, lvl FROM hierarchy_cte AS result
我想知道通过使用C#而不是SQL进行递归是否会提高性能。假设我有一个IQueryable,其中Tree是表示层次结构表中条目的实体,谁能向我展示如何执行CTE与递归C#函数相同的工作?类似于以下内容:
public void RecurseTree(IQueryable<Tree> tree, Guid userId, Guid parentId, int level) { ... currentNode.level = x ... Recurse(tree... ,level + 1) }
看到使用lambda表达式很容易做到这一点将很酷。
相比之下,SQL Server中的递归速度非常慢,但是确实可以正常工作。
我不得不说,T-SQL在某种程度上受到限制,但是它从来没有打算首先进行所有这些操作。我不相信如果您打算针对SQLServer实例运行IQueryable,则无法通过IQueryable来实现,但是您可以在运行代码的机器上的内存中使用LINQ-to-Objects来实现。紧凑的方式。
这是一种方法:
class TreeNode { public int Id; public int? ParentId; } static void Main(string[] args) { var list = new List<TreeNode>{ new TreeNode{ Id = 1 }, new TreeNode{ Id = 4, ParentId = 1 }, new TreeNode{ Id = 5, ParentId = 1 }, new TreeNode{ Id = 6, ParentId = 1 }, new TreeNode{ Id = 2 }, new TreeNode{ Id = 7, ParentId= 2 }, new TreeNode{ Id = 8, ParentId= 7 }, new TreeNode{ Id = 3 }, }; foreach (var item in Level(list, null, 0)) { Console.WriteLine("Id={0}, Level={1}", item.Key, item.Value); } } private static IEnumerable<KeyValuePair<int,int>> Level(List<TreeNode> list, int? parentId, int lvl) { return list .Where(x => x.ParentId == parentId) .SelectMany(x => new[] { new KeyValuePair<int, int>(x.Id, lvl) }.Concat(Level(list, x.Id, lvl + 1)) ); }