使用Entity Framework Fluent语法或内联语法编写recursionCTE

在SQL和entity framework(ADO.NET实体映射)中,我对这个recursion是新的。 我正在评论pipe理工作,我有一个Comments表,该表包含列NewsID, CommentID, ParentCommentID, IndentLevel, CreatedTime

我正在尝试获取特定新闻项目的评论列表,其中所有评论都是根据父项下的孩子和创build时间安排的,如下所示:

 CommentID | time | ParentCommentID Guid1 | t1 | null Guid4 | t4 | Guid1 Guid2 | t2 | null Guid3 | t3 | Guid2 

必须优先考虑孩子的父母关系,然后创造时间。

我迄今为止所关注的是(从互联网资源和以前的计算器Q / A)

  • 如图所示,这些recursion查询很慢。 而使用entity framework这样做更慢。 但是可以实现。
  • 所以,可以通过在SQL Server中创build存储过程并使用function导入来调用它。 另一件事是在entity framework中使用Linq。
  • 在SQL Server中,以这种格式使用它

SQL:

 WITH cte_name ( column_name [,...n] ) AS ( CTE_query_definition –- Anchor member is defined. UNION ALL CTE_query_definition –- Recursive member is defined referencing cte_name. ) -- Statement using the CTE SELECT * FROM cte_name 
  • 但在尝试这个之前,我想试试Linq。

为此,我已经提到这个链接,我有这个想法: https : //stackoverflow.com/a/6225373/892788

但我试图了解代码,但徒劳无功。 有人可以给我一个关于在Entity Framework中编写recursionCTE的更好和更详细的解释吗?

 private IEnumerable<NewsComment> ArrangeComments(IEnumerable<NewsComment> commentsList, string parentNewsComntID, int level) { Guid parentNewsCommentID; if (parentNewsComntID != null) { parentNewsCommentID = new Guid(parentNewsComntID); } else parentNewsCommentID = Guid.Empty; return commentsList.Where(x => x.ParentCommentID == parentNewsCommentID).SelectMany(x => new[] { x }.Concat(ArrangeComments(commentsList, x.NewsCommentID.ToString(), level + 1)); } 

我在下面的方法中使用这个:

 return ArrangeComments(commentList,null , 0); 

我已经尝试过,似乎我无处可去。 尽pipe有对SQLrecursion的解释,但Linq并不多,但由于不那么熟悉,所以对我来说很模糊。 有人可以帮我理解这个Linq中的CTErecursion,这很好

提前致谢

AFAIK不支持LINQ和EF中的recursionCTE。 解决scheme是将CTE作为一个视图。 关于使用EF Code First和Migrations的recursion或分层查询的文章展示了如何使用EF代码优先迁移部署这样的视图。

尝试通过执行recursion客户端迭代来模拟CTE不会扩展到大数据集,并导致与服务器的交换。 请注意,您的EF代码如何返回IEnumerable而不是IQueryable ,这意味着它将实现每个级别,然后将每个条目的下一级别作为单独的请求进行连接 。 基于LINQ的解决scheme可以合理地适用于入门数量有限的浅层次结构(注意许多项目可以有这样的数据布局,用户post/答案就是一个典型的例子),但是在深层次结构中会有很多元素崩溃。

将CTE查询放到StoredProcedure,然后从代码中调用它。 EF为此提供了所有的意思(调用SP和检索结果)。 我自己也一样,工作正常。

用Linq写CTE查询是不可能的linq-to-sql中的公用表expression式(CTE)?

示例ArrangeComments是一个自我调用的recursion过程,但我敢质疑它的性能。 它从DB中提取logging,然后在内存中应用操作。

花了几个小时阅读这个问题后,我决定用C#做,而不必创build数据库视图。

注:仅用于非性能严重的操作。 具有来自http://nosalan.blogspot.se/2012/09/hierarchical-data-and-entity-framework-4.html的; 1000个节点性能的示例。

 Loading 1000 cat. with navigation properties took 15259 ms Loading 1000 cat. with stored procedure took 169 ms 

码:

 public class Category { [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public string Name { get; set; } public int? ParentId { get; set; } public virtual Category Parent { get; set; } public virtual ICollection<Category> Children { get; set; } private IList<Category> allParentsList = new List<Category>(); public IEnumerable<Category> AllParents() { var parent = Parent; while (!(parent is null)) { allParentsList.Add(parent); parent = parent.Parent; } return allParentsList; } public IEnumerable<Category> AllChildren() { yield return this; foreach (var child in Children) foreach (var granChild in child.AllChildren()) { yield return granChild; } } }