加载子的子的子
本文关键字:加载 | 更新日期: 2023-09-27 18:16:33
我有一个对象树,它的大小可能是无限的。
类别实体有其他类别实体作为子实体。换句话说,一个类别可以有子类别:深度是无限的。
在下面你可以看到我的实体的简化版本
public class ProductCategory : IEntity<ProductCategory>, IDeletable
{
public Guid ProductCategoryId { get; private set; }
public virtual ICollection<ProductCategory> Children { get; set; }
public virtual ProductCategory Father { get; set; }
}
直到几个小时前,我才开始使用lazy loading,所以我可以很容易地获得子节点的子节点。
现在我已经禁用了延迟加载,因为它有问题,我的查询来获取子类的如下:
public IEnumerable<ProductCategory> GetAllChildrenOfCategory(Guid categoryId)
{
var results = GetAllProductCategoriesQuery()
.Where(elt => elt.FatherId.Equals(categoryId))
.Include(elt => elt.Father)
.Include(elt => elt.Children);
return results.ToList().CloneEachElement();
}
我得到了类别的所有子元素。然而,我没有孩子的孩子的孩子的孩子…
现在我有两个问题:
是否可以编写一个查询,以便您拥有整个类别树?
或者,是否有可能配置实体框架,以便它总是给你的子类,一旦你从数据库中提取它,这样我就不必显式地包括导航属性?
其他选项……?
就我所知,您可以使用字符串而不是lambda表达式来包含用于即时加载的属性。它不是很优雅,但它会给你一个解决方案:
1)找出你拥有的最深层次,然后构造一个相应的包含字符串,如"Father.Father"。并将其用于您的包括。我不能保证它有效,但我给它一个公平的机会。
2)在代码优先,我不认为有这样的选择。它可能存在于EDMX中,但我根本不是这方面的专家。我建议你使用一种扩展方法来完成这项工作:
private static readonly queryStringForMaxDepth = WriteAMethodToFindIt();
public static IQueryable<ProductCategory> DeepProductCategories(this DbContext context){
return context.ProductCategories.Include(queryStringForMaxDepth);
}
,你可以这样使用:
context.DeepProductCategories()
.Where(...)
我以前在MsSql中使用过视图。然后我直接调用视图,像
dbContext.Database.SqlQuery<ProductCategory>("select * from GetCategoryTree where RootCategoryId=1");
所以这正是我想要的。所以它也是可查询的。下面是我使用的一个源:SQL递归查询父子
这里是另一个示例
有人在msdn论坛问过递归查询
作为您的问题的可能解决方案,我建议您使用显式加载。这样,您就可以在每次需要时从特定类别加载子类别:
var cat=context.FirstOrDefault(c=>c.ProductCategoryId ==categoryId);
// Load the subcategories related to a given category
context.Entry(cat).Collection(p => p.Children).Load();
包括…
FatherRepository.All().Including(x => x.Childs, x => x.Childs.Select(y => y.ChildChild));
父类…
public class Father
{
public int Id { get; set; }
#region Navigations Properties
public virtual List<Child> Childs { get; set; }
#endregion
}
子类…
public class Child
{
public int Id { get; set; }
public int ChildChildId { get; set; }
public int FatherId { get; set; }
#region Navigations Properties
public virtual Father Father { get; set; }
public virtual ChildChild ChildChild { get; set; }
#endregion
}
ChildChild类…
public class ChildChild
{
public int Id { get; set; }
}