加载子的子的子

本文关键字:加载 | 更新日期: 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();
}

我得到了类别的所有子元素。然而,我没有孩子的孩子的孩子的孩子…

现在我有两个问题:

  1. 是否可以编写一个查询,以便您拥有整个类别树?

  2. 或者,是否有可能配置实体框架,以便它总是给你的子类,一旦你从数据库中提取它,这样我就不必显式地包括导航属性?

  3. 其他选项……?

加载子的子的子

就我所知,您可以使用字符串而不是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; }
}