问题描述
在 Entity Framework 6 中投影自引用多级实体.
Projecting self referencing multi level entities in Entity Framework 6.
假设我有一个 Category
实体如下:
Let's say that I have a Category
entity as follows:
public class Category
{
public int CategoryId { get; set; }
public int? ParentCategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual Category ParentCategory { get; set; }
public virtual ICollection<Category> SubCategories { get; set; }
public virtual ICollection<Product> Products { get; set; }
public Category()
{
SubCategories = new HashSet<Category>();
Products = new HashSet<Product>();
}
}
我想将具有所有层次结构的整个 Category
DbSet
映射到以下 POCO 类(同时包括子和父类别的所有可能级别):
And I would like to map the whole Category
DbSet
with all the hierarchy to a following POCO class (while including all possible levels of sub and parent categories):
public class CategoryView
{
public int Id { get; set; }
public int? ParentCategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public CategoryView ParentCategory { get; set; }
public List<CategoryView> SubCategories { get; set; }
public int ProductCount { get; set; }
public Category()
{
SubCategories = new HashSet<CategoryView>();
}
}
请记住,单个类别可能有无限级别的子类别,如下所示:
Please bear in mind that a single category may have unlimited levels of subcategories as follows:
Category (Level 0)
SubCategory1 (Level 1)
SubCategory2
SubCategory2SubCategory1 (Level 2)
SubCategory2SubCategory2
SubCategory2SubCategory2SubCategory1 (Level 3)
... (Level N)
SubCategory3
当尝试使用递归方法创建层次结构时,该方法尝试处理每个类别的子类别和父类别,得到 stackoverflow 异常
,因为它卡在第一个类别(Category
) 和第一个子类别 (SubCategory1
) 由于 ParentCategory
和 SubCategories
之间的关系.
When tried to create hierarchy with recursive a method which tries to process every single categories sub and parent categories, got stackoverflow exception
, since it get stuck between the first category (Category
) and the first subcategory (SubCategory1
) due to relation between ParentCategory
and SubCategories
.
进行这种投影(不消除父母)的最佳和优雅的方式是什么?(或者有没有?)
What is the best and elegant way of doing such projection (without eliminating parents)? (Or is there any?)
任何帮助将不胜感激.
谢谢,
推荐答案
我不能说这是最好还是优雅的方式,但它是构建这种结构的非常标准且高效的非递归方式.
I can't say if it's the best or elegant way, but it's pretty standard and efficient non recursive way of building such structure.
首先使用简单的投影加载所有类别没有父/子对象链接:
Start with loading all categories without parent / child object links using a simple projection:
var allCategories = db.Categories
.Select(c => new CategoryView
{
Id = c.CategoryId,
ParentCategoryId = c.ParentCategoryId,
Name = c.Name,
Description = c.Description,
ProductCount = c.Products.Count()
})
.ToList();
然后创建一个快速查找数据结构,用于通过Id
查找CategoryView
:
then create a fast lookup data structure for finding CategoryView
by Id
:
var categoryById = allCategories.ToDictionary(c => c.Id);
然后使用先前准备的数据结构将子类别链接到其父类别:
then link the subcategories to their parents using the previously prepared data structures:
foreach (var category in allCategories.Where(c => c.ParentCategoryId != null))
{
category.ParentCategory = categoryById[category.ParentCategoryId.Value];
category.ParentCategory.SubCategories.Add(category);
}
此时,树形链接已准备就绪.看你的需要.如果您需要真实的树表示,则返回 allCategories
或根类别:
At this point, the tree links are ready. Depending of your needs. either return the allCategories
or the root categories if you need a real tree representation:
return allCategories.Where(c => c.ParentCategoryId == null);
附:实际上,可以避免 allCategories
列表,因为 categoryById.Values
可以起到相同的作用.
P.S. Actually the allCategories
list can be avoided, since categoryById.Values
could serve the same purpose.
这篇关于在实体框架6中投影自引用多级实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!