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

时间:2016-01-08 13:36:41

标签: c# nhibernate

我希望在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]

我们如何在nhibernate中使用Session.QueryOver知道正确的父/子映射(父类具有子类的集合,子类还具有其父类的属性)?

修改

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

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

1 个答案:

答案 0 :(得分:1)

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

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

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