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;
}
一种可能性是从单个查询填充自定义DTO
CategoryStatusDTO
{
int categoryId;
int parentCategoryId;
bool parentEnabled;
bool hasParent;
}
一旦您将DTO加载到内存中,您就可以对这些DTO执行类似的操作,并确定要加载的类别列表,然后使用IN操作按Id加载所有这些类别。