所以我有一个简单的表来表示支持动态N级深度的类别和子类别的树。
CategoryID int NOT NULL (PK)
ParentCategoryID int NULLABLE (FK to self)
CategoryName varchar(100) NOT NULL
我的实体(从记忆中输入,抱歉,如果这里有一个愚蠢的错误):
public class Category
{
public int CategoryId { get; set; }
public int ParentCategoryId { get; set; }
public string CategoryName { get; set; }
public virtual Category ParentCategory { get; set; }
public IDbSet<Category> ImmediateChildCategories { get; set; }
}
在C#(4.5+)的Entity Framework(6.x)中使用执行延迟的lambda表达式,如何识别作为指定类别后代的所有类别?
我喜欢的伪代码SQL查询是这样的:
SELECT * FROM Category WHERE AnyLevelOfAncestorId = 123;
我希望看到的伪代码EF查询是这样的(分页是为了强调我对执行延迟支持的需求):
_db.Categories.Where(cat => cat.HasAncestor(123)).Skip(1000).Take(25).ToList();
其他详情:
答案 0 :(得分:2)
我假设您的Category
实体类型有一个集合导航属性,用于检索其子类别(通过外键相关)。此导航属性将导致在第一次访问子类别时延迟加载子类别。您可以定义一个方法,在根及其子节点上递归调用此导航属性(例如ChildCategories
)。
public static IEnumerable<Category> GetDescendants(Category root)
{
return root.ChildCategories.Concat(root.ChildCategories.SelectMany(GetDescendants));
}
上述代码的缺点是它会发出一个单独的数据库查询来检索每个父代的子代。我不相信Entity Framework目前支持生成单个递归查询(EF 6.1.3)。相反,我建议你在数据库中定义一个递归视图,它会投射所有类别 - 后代对;将此视图包含为实体数据模型中的实体;然后从LINQ查询中查询或加入它。可以使用DBMS特定技术定义视图。 SQL Server支持recursive CTEs,recent versions of Oracle也是如此。