One to many recursive relationship with Code First

ef-code-first entity-framework entity-framework-6

Accepted Answer

the root of the anomaly

The reason for the exception is aSelect or SelectMany on anull gathering, in your instance the outcome of

b => b.Children

Each hierarchy's branch corresponds to aChildren When they get to the portion, the collection is accessible.


The selector the expression lambdab => b.Children This is equivalent to a technique

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

Therefore, what really occurs isb.Children.SelectMany(...) , ornull.SelectMany(...) It brings about the exception you can see.

Stopping it

Why, then, are theseChildren null collections

This is due to the absence of lazy loading. The collection needs to be in order to support lazy loading.virtual :

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

After EF retrieves aBranch It produces an object from the database.proxy object, a product of objectBranch It uses lazy loading-capable code to override virtual properties. then whenb.Children EF will run a query that populates the collection once the issue is resolved. The collection will be empty rather than null if there are no children.

Explaining flattening

What then occurs in theFlatten The first step in the approach is to get the offspring of the branch (selector(node) ), and afterwards on each of these kids (SelectMany ) theFlatten function is invoked once more (now simply as an example)Flatten(x, selector) not a method of extension).

In theFlatten Method for adding each node's children to the collection of nodes (.Concat(new[] { node }) because of this, all nodes in the hierarchy are eventually returned.Flatten returns the entry-point node.

Some comments

  1. I would update the collection so that the parent node is at the top.Flatten approach into

    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)));
  2. It is highly inefficient to lazy load a hierarchy. Actually, the best tool for querying hierarchies is not LINQ. A view in the database that makes use of a CTE is necessary to accomplish this effectively (common table expression). However, that is a different tale.

12/31/2014 2:37:28 PM

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow