From one to many recursive relationships with Code First

I am trying to implement a simple link with binding to EF 6.1.2 Code First.

public class Branch 
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    public int? ParentId { get; set; }

    [ForeignKey("ParentId")]
    public virtual Branch Parent { get; set; }

    public ICollection<Branch> Children { get; set; } // direct successors
}

In my application, I have exactly one root branch. And besides this single root branch, each branch has exactly one parent element (parentId of the root branch is NULL). In addition, each branch can have [0..n] matched.

I have two problems:

  • Does any additional FluentApi code need to be specified in OnModelCreating (DbModelBuilder modelBuilder) so that EF understands this one-to-many relationship? I tried this: modelBuilder.Entity<Branch>().HasOptional<Branch>(b => b.Parent).WithMany(b => b.Children).HasForeignKey(b => b.ParentId);But I'm not sure I need this at all.
  • For this branch I want to get all the children (up to the hierarchy). This is what I came up with:

.

 public IEnumerable<Branch> GetBranches(Branch anyBranch)
 {
     return anyBranch.Flatten(b => b.Children);
 }

and

 public static IEnumerable<T> Flatten<T>(this T node, Func<T, IEnumerable<T>> selector)
 {
     return selector(node).SelectMany(x => Flatten(x, selector))
                            .Concat(new[] { node });
 }

. - StackOverflow. , , .

GetBranches() ( ), Flatten(). : " . : source ". , , .

, - ? !

+4
1

Select SelectMany null,

b => b.Children

Children,

selector(node)

selector - - b => b.Children,

IEnumerable<Branch> anonymousMethod(Branch b)
{
    return b.Children;
}

, , b.Children.SelectMany(...) null.SelectMany(...), , .

Children null?

, . , virtual:

public virtual ICollection<Branch> Children { get; set; }

EF Branch , proxy, , Branch, , . , b.Children , EF , . , , .

, Flatten, , (selector(node)), (SelectMany) Flatten ( Flatten(x, selector), ).

Flatten node (.Concat(new[] { node })), ( Flatten node, ).

  • node , Flatten

    public static IEnumerable<T> Flatten<T>(this T node, Func<T,IEnumerable<T>> selector)
    {
        return new[] { node }
            .Concat(selector(node).SelectMany(x => Flatten(x, selector)));
    }    
    
  • . LINQ . , CTE ( ). ...

+7

Source: https://habr.com/ru/post/1569535/


All Articles