我们有这样的东西
var categories = _context.Categories.Include("Categories1.Categories1.Categories1");
该方法可以处理并处理多达4级深度的子类别(对于现在来说已经足够了,但谁知道未来)
有更好的方法吗?
更多信息
我们首先使用数据库。类别表包含以下列:
答案 0 :(得分:1)
在这种情况下,我认为递归属性可能是一个不错的选择。试图从内存中做到这一点(几年后),性能将不会很好。没有延迟加载,也没有显式加载。
public class Category {
public int Id {get; set;}
// other stuff
public List<Category> MyChildren {
get { return _context.Categories.Where(x => x.ParentCategoryId == Id).ToList<Category>(); }
}
}
这应该给您一个从给定节点开始的层次图。
var justOne = _context.Categories.FirstOrDefault(x => x.Id = <myval>);
缺点是您将不得不递归地解析/使用结果,并且可能以指数形式增长。
说明:EF不允许在递归中使用_context,它仅用于说明目的。在存储库/ UoW或业务层中,可以通过具有递归调用方法的方法的属性,使用相同的技术来“组装”完成的实体。
只是出于娱乐目的,这是相同的递归技术(但不是作为属性,现在没有时间)。
public class Category // EF entity
{
public int Id { get; set; }
public int ParentId { get; set; }
public virtual List<Category> MyChildren { get; set; }
}
public static class MVVMCategory
{
public static Category GetCategory(int id)
{
Category result = _context.Categories.FirstOrDefault(x => x.Id == id);
result.MyChildren = GetChildren(id);
return result;
}
public static List<Category> GetChildren(int id)
{
List<Category> result = _context.Categories.Where(x => x.ParentId == id).ToList<Category>();
foreach (var item in result)
{
item.MyChildren = GetChildren(item.Id);
}
return result;
}
}
需要注意的一件事。我将virtual添加到列表中以进行延迟加载,因为可以说可以“手动”加载孩子。
答案 1 :(得分:1)
首先,添加数据注释并使您的属性可读
public partial class Category
{
public Category()
{
this.Children = new HashSet<Category>();
}
[Key]
public int Id { get; set; }
public string WhatEverProperties { get; set; }
public int ParentCategoryId { get; set; }
[ForeignKey("ParentCategoryId")]
[InverseProperty("Category")]
public Category Parent { get; set; } // name "Category1" as "Parent"
[InverseProperty("Category")]
public ICollection<Category> Children { get; set; } // Name it as Children
}
然后,您不需要任何.Include(...)
语法即可显式加载父对象,它将与功能中的任何级别一起使用。假设您有一个类别,然后您将其父类别带有:
category.Parent?.Parent?.Parent....
如果您需要获得等级,请使用扩展名:
public static class CategoryExtensions
{
public static int Level(this Category category)
{
if (category.Parent == null)
{
return 0;
}
return category.Parent.Level() + 1;
}
}
还有一件事情:以下部分应该已经在您的业务规则层中,以避免加载不必要的对象。
public class CategoryBLLWhatever
{
var context = new YourContext();
public IQueryable<Category> RootCategories()
{
return context.Categories.Where(x => x.Paerent == null).Include(x => x.Children);
}
//Include parent in your query if you need it
public IQueryable<Category> WhateverQuery(Expression<Func<Category, bool>> filter)
{
return context.Categories.Where(filter).Include(x => x.Parent);
}
}