简体   繁体   中英

LINQ Select Statement to Map Entity Using Recursion

I have a Category Entity that has a collection of child Categories and a nullable reference to a 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; } 
}

I have the scenario where I need to "copy" an existing entity ( Zone ) which has references to Categories . Within the select statement I need to map the existing categories and their children to a new Category record so that when I save the new categories will hold a reference to the new copied Zone .

The problem I'm having is a recursion method that will loop through the current LINQ select ( x ) Category and create new Category records for each of its children s children etc.

Here is the relevant part of the current "copy" select statement I have. Do I call Where on Categories that are top level ie don't have a ParentId and then use a recursive method for the children?

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

Are you perhaps looking for a copy constructor like this?

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...
}

Usage:

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

Use a select recursive method like so:

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;
        }
    }
}

Then do an implementation:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM