Nhibernate选择所有启用的类别以及所有启用的子类别等

本文关键字:启用 子类 选择 Nhibernate | 更新日期: 2023-09-27 18:29:40

我希望在nhibernate中创建一个查询,以获取所有启用的类别及其相应的启用子类别,并为这些子类别获取其启用子类别等。

例如:

Category A [enabled]
- Subcategory 1 [Enabled]
-- Subsubcategory 1 [Enabled]
--- Subsubsubcategory 1 [Enabled]
-- Subsubcategory 2 [Enabled]
--- Subsubsubcategory 1 [Disabled]
- Subcategory 2 [Disabled]
-- Subsubcategory 1 [Enabled]
Category B [enabled]

查询应返回以下结果:

Category A [enabled]
- Subcategory 1 [Enabled]
-- Subsubcategory 1 [Enabled]
--- Subsubsubcategory 1 [Enabled]
-- Subsubcategory 2 [Enabled]    
Category B [enabled]

我们如何在带有Session.QueryOver的nhibernate中做到这一点,因为我们知道做出了正确的父/子映射(父有一个子类别的集合,子类别也有一个带有parentcategory的属性)?

编辑

实现我想要的丑陋而沉重的方式。然而,这会产生大量的选择查询。如何对此进行优化?

public void GetAllEnabledCategories(){
    var allEnabledCategories = new List<Category>();
            var enabledParentCatgories = Session.QueryOver<Category>().Where(x => x.ParentCategory == null && x.Status==Status.Enabled).List().ToList();
            allEnabledCategories.AddRange(enabledParentCatgories);
            foreach (var category in enabledParentCatgories)
            {
                allEnabledCategories.AddRange(Recursive(category.SubCategories));
            }
        }
        private IEnumerable<Category> Recursive(IEnumerable<Category> subCategories)
        {
            var allEnabledCategories = new List<Category>();
            var enabledSubCategories = subCategories.Where(x => x.Status == Status.Enabled).ToList();
            allEnabledCategories.AddRange(enabledSubCategories);
            foreach (var category in enabledSubCategories)
            {
                allEnabledCategories.AddRange(Recursive(category.SubCategories));
            }
            return allEnabledCategories;
        }

编辑2:实施的解决方案

Low Flying Pelican的建议答案对我来说很好。它不会导致超过2个查询,对我来说是一个好的、高性能的解决方案。在建议的实现下面,代码可以被清理和优化,但仍然有效。

public void GetEnabledCategories()
            CategoryStatusQueryItem result = null;
            Category categoryAlias = null;
            var categoryStatusQueryItemsWithStatusEnabled = Session.QueryOver<Category>(() => categoryAlias).Where(x => x.Status == Status.Enabled)
                .SelectList(list => list
                    .Select(() => categoryAlias.Id).WithAlias(() => result.CategoryId)
                    .Select(() => categoryAlias.ParentCategory.Id).WithAlias(() => result.ParentCategoryId)
                    .Select(() => categoryAlias.Status).WithAlias(() => result.CategoryStatus))
                .TransformUsing(Transformers.AliasToBean<CategoryStatusQueryItem>())
                .List<CategoryStatusQueryItem>().ToList();
            var categoryStatusQueryItemsWithAllParentsEnabled = new List<CategoryStatusQueryItem>();
            categoryStatusQueryItemsWithAllParentsEnabled.AddRange(categoryStatusQueryItemsWithStatusEnabled.Where(x => !x.ParentCategoryId.HasValue).ToList());
            foreach (var source in categoryStatusQueryItemsWithStatusEnabled.Where(x => x.ParentCategoryId.HasValue))
            {
                if (AreAllParentsEnabled(categoryStatusQueryItemsWithAllParentsEnabled, source))
                {
                    categoryStatusQueryItemsWithAllParentsEnabled.Add(source);
                }
            }
            var categoriesWithParentsEnabled = new List<Category>();
            var categoryIdsWithAllParentsEnabled =
                categoryStatusQueryItemsWithAllParentsEnabled.Select(x => x.CategoryId).ToList();
            for (var i = 0; i < categoryIdsWithAllParentsEnabled.Count; i += 1000)
            {
                var c = categoryIdsWithAllParentsEnabled.Skip(i).Take(1000).ToList();
                var queryResult =
                    Session.QueryOver(()=>categoryAlias)
                        .Where(Restrictions.In("Id",c))
                        .List()
                        .ToList();
                categoriesWithParentsEnabled.AddRange(queryResult);
            }
        }
        public bool AreAllParentsEnabled(List<CategoryStatusQueryItem> categoriesWithStatusEnable,
            CategoryStatusQueryItem category)
        {
            var parentsEnabled = true;
            var parent = categoriesWithStatusEnable.FirstOrDefault(
                x => x.CategoryId == category.ParentCategoryId);
            if (parent==null || parent.CategoryStatus == Status.Disabled)
            {
                parentsEnabled = false;
            }
            else if (parent.ParentCategoryId.HasValue)
            {
                parentsEnabled = AreAllParentsEnabled(categoriesWithStatusEnable, parent);
            }
            return parentsEnabled;
        }

Nhibernate选择所有启用的类别以及所有启用的子类别等

一种可能性是从单个查询填充自定义DTO

CategoryStatusDTO
{
    int categoryId;
    int parentCategoryId;
    bool parentEnabled;
    bool hasParent;
}

一旦您将DTO加载到内存中,您就可以对这些DTO执行类似的操作,并确定要加载的类别列表,然后使用IN操作按Id加载所有这些类别。