计算自引用表中所有后代总数的最有效方法

时间:2017-07-06 15:03:49

标签: c# entity-framework automapper

我正在寻找一种有效的方法来计算给定类别的所有子类别(所有级别)的总数,而无需从数据库中检索所有数据

这是我的模特:

    public class CategoryViewModel
{
    public CategoryViewModel()
    {
        SubCategories = new List<CategoryViewModel>();
    }

    public Guid CategoryId { get; set; }

    [Required]
    public string Title { get; set; }

    public Guid? ParentCategoryId { get; set; }

    public virtual CategoryViewModel ParentCategory { get; set; }

    public virtual List<CategoryViewModel> SubCategories { get; set; }

    public int TotalOfDirectSubCategories { get; set; }
    public int TotalOfAllSubCategories { get; set; }
}

我的ViewModel:

            cfg.CreateMap<Category, CategoryViewModel>()
            .PreserveReferences()                
            .ReverseMap();

我的自动映射:

                data = _ctx.Categories.Where(x => x.ParentCategoryId == categoryId)
                //.Include(x => x.SubCategories)
                .ToList();

最后我的EF检索数据:

{{1}}

假设一个类别可以包含数千个子类别。由于这将是SOA解决方案,并且数据将从Web API传递到我的客户端应用程序,因此我不想在每次Web API调用时传递所有子类别数据,因此我只需要所请求类别的数据和相应的计数。

假设我们有 '猫1'&gt; 'cat 1 1'&gt; 'cat 1 1 1'

'cat 1'恰好包含2个子类别。 'cat 1 1'包含一个子类别。我可以通过调用web API方法'getCategory(null)'来检索'cat 1'数据,并检索'cat 1 1'数据我会称之为'getCategory(GuidOfCat11)'

对于'cat 1':

TotalOfDirectSubCategories - 1

TotalOfAllSubCategories - 2

同样,不会包含任何子类别

1 个答案:

答案 0 :(得分:0)

这是我能实现的最好的,你认为有更好的方法吗?

AutoMapper:

            cfg.CreateMap<Category, CategoryViewModel>()
            .PreserveReferences()
            .ForMember(x => x.TotalOfDirectSubCategories, x => x.MapFrom(z => z.SubCategories.Count))
            .ReverseMap();

填充CategoryViewModel:

        public List<CategoryViewModel> GetAllCategoriesAndTasksForParentCategoryAndUser(Guid? categoryId)
    {
        var data = new List<Category>();

        if (categoryId == null) // retrieve root level categories
        {
                data = _ctx.Categories.Where(x => x.ParentCategoryId == null)
                    .Include(x => x.SubCategories)
                    .Include(x => x.Tasks)
                    .ToList();
        }
        else
        {
                data = _ctx.Categories.Where(x => x.CategoryId == categoryId)
                    .Include(x => x.SubCategories)
                    .Include(x => x.Tasks)
                    .ToList();
        }

        var dataToReturn = Mapper.Map<List<Category>, List<CategoryViewModel>>(data);
        foreach (var category in data)
        {
            var vm = dataToReturn.First(x => x.CategoryId == category.CategoryId);

            //subCategories
            int totalCount = 0;
            SubCategoriesCount(ref totalCount, category);
            vm.TotalOfAllSubCategories = totalCount;            
        }

        return dataToReturn;

    }

最后,方法:

    private void SubCategoriesCount(ref int subCatCount, Category category)
    {
        if (category.SubCategories != null || category.SubCategories.Count() != 0)
        {
            subCatCount += category.SubCategories.Count();

            foreach (var subCat in category.SubCategories)
            {
                SubCategoriesCount(ref subCatCount, subCat);
            }
        }
    }