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