LINQ Select 使用递归映射实体的语句

LINQ Select Statement to Map Entity Using Recursion

我有一个 Category 实体,它有一个子类别集合和一个对 Parent Category.

的可为空的引用
public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }

    public Category Parent { get; set; }
    public ICollection<Category> Children { get; set; } 
}

我有这样的场景,我需要 "copy" 一个现有实体 (Zone),它引用了 Categories。在 select 语句中,我需要将现有类别及其子类别映射到新的类别记录,以便在我保存新类别时将保留对新复制的 Zone.

的引用

我遇到的问题是一种递归方法,它将遍历当前的 LINQ select (x) 类别并为其每个子项的子项等创建新的类别记录。

这是我当前 "copy" select 声明的相关部分。我是否在顶级 Categories 上调用 Where,即没有 ParentId,然后对子项使用递归方法?

Categories = zone.Categories.Where(y => !y.ParentId.HasValue).Select(x => new Category
{
     Children = WHAT DO I PUT IN HERE
     Name = x.Name,
}).ToList()

您是否正在寻找这样的复制构造函数?

public class Category 
{
    // Copy constructor, recursively called for each child.
    public Category(Category other)
    {
        Id = other.Id;
        Name = other.Name;
        ParentId = other.ParentId;
        Parent = other.Parent;
        // Use this copy constructor for each child too:
        Children = other.Children.Select(c => new Category(c)).ToList();
    }
    // We probably want the default constructor too.
    public Category() { }

    // Your Props...
}

用法:

var deepCopied = zone.Categories.Select(c => new Category(c));

像这样使用 select 递归方法:

public static class EnumerableExtensions
{
    public static IEnumerable<T> SelectRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
    {
        foreach (var parent in source)
        {
            yield return parent;

            var children = selector(parent);
            foreach (var child in SelectRecursive(children, selector))
                yield return child;
        }
    }
}

然后做一个实现:

var lookup = _dbContext.Categories.ToLookup(x => x.ParentId);
var parents = lookup[null].SelectRecursive(x => lookup[x.Id]).Where(c => c.ParentId == null).ToList();