EF Core:渴望加载(.Include)子类别(自我引用)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EF Core:渴望加载(.Include)子类别(自我引用)相关的知识,希望对你有一定的参考价值。
我们有类似的东西
var categories = _context.Categories.Include("Categories1.Categories1.Categories1");
这可以处理和处理深达4级的子类别(现在已足够,但谁知道未来)
有没有更好的方法呢?
更多信息
我们先使用数据库。类别表包含以下列:
- ID
- ParentCategoryId < - 这具有Category.Id的外键
答案
首先,添加数据注释并使您的属性可读
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);
}
}
另一答案
在这种特殊情况下,我认为递归属性可能是一个不错的选择。试图从记忆中做到这一点(多年),表现不会很好。没有延迟加载和没有显式加载。
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;
}
}
有一点需要注意。我将虚拟添加到列表中以进行延迟加载,因为我正在“手动”加载子项,可以这么说。
以上是关于EF Core:渴望加载(.Include)子类别(自我引用)的主要内容,如果未能解决你的问题,请参考以下文章
是否必须使用 .Include 加载 EF Core 5 中的子对象?
如何使用 EF Core Code-First 创建具有子类别的类别表? [复制]