加载儿童的子女

时间:2015-10-08 11:28:09

标签: c# entity-framework

我有一个对象树,其大小可能是无限的。

实体类别具有其他类别实体作为子项。换句话说,一个类别可以有子类别:深度是无限的。

下面您可以看到我的实体的简化版本

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; }
}

我曾经懒得加载到几个小时前,所以我很容易得到孩子的孩子。

现在我已经禁用了延迟加载,因为我遇到了问题,我的查询是为了获得一个类别的子项。

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. 其他选择......?

4 个答案:

答案 0 :(得分:0)

据我所知,您可以使用字符串而不是lambda表达式来包含预先加载的属性。它不是很优雅,但它会给你一个解决方法:

1)找出你所拥有的最深层次,然后构建一个相应的包含字符串,例如&#34;父亲。父亲。&#34;并将其用于您的包含。我不能保证它有效,但我给它一个公平的机会。

2)首先在代码中,我不认为有这样的选择。它可能存在于EDMX中,但我完全不是这方面的专家。我建议你使用扩展方法来完成这项工作:

private static readonly queryStringForMaxDepth = WriteAMethodToFindIt();

public static IQueryable<ProductCategory> DeepProductCategories(this DbContext context){
     return context.ProductCategories.Include(queryStringForMaxDepth);
}

您将能够使用如下:

context.DeepProductCategories()
       .Where(...)

我希望这会给你一些想法。

答案 1 :(得分:0)

我之前通过使用MsSql中的视图完成了此操作。比我直接调用视图:

dbContext.Database.SqlQuery<ProductCategory>("select * from GetCategoryTree where RootCategoryId=1");

所以这给了我正是我想要的东西。所以它也是可查询的。 这是我使用的资源之一:sql recursive query parent child

and here is another sample

Someone else asked For Recursive Queries before in msdn forums

答案 2 :(得分:0)

作为您问题的可能解决方案,我建议您使用Explicit Loading。这样,您可以在每次需要时从特定类别加载子类别:

var cat=context.FirstOrDefault(c=>c.ProductCategoryId ==categoryId);

// Load the subcategories related to a given category
context.Entry(cat).Collection(p => p.Children).Load(); 

答案 3 :(得分:0)

包括......

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; }
}