I am using the following Tree class:
public class Tree
{
public Tree() {}
public Guid TreeRootNodeId { get; set; }
public virtual Node TreeRootNode { get; set; }
public virtual List<Node> Nodes { get; set; }
}
with the Node implementation:
public class Node
{
public Node() {}
public Guid TreeId { get; set; }
public virtual Tree Tree { get; set; }
public Guid? LeftNodeId { get; set; }
public virtual Node LeftNode { get; set; }
public Guid? RightNodeId { get; set; }
public virtual Node RightNode { get; set; }
}
To setup up Entity Framework Core (EF) I used:
modelBuilder
.Entity<Tree>()
.HasMany(e => e.Nodes)
.WithOne(e => e.Tree);
modelBuilder
.Entity<Tree>()
.HasOne<Node>(e => e.TreeRootNode)
.WithOne(e => e.Tree)
.HasForeignKey<Tree>(e => e.TreeRootNodeId);
modelBuilder
.Entity<Node>()
.HasOne(e => e.LeftNode)
.WithMany();
modelBuilder
.Entity<Node>()
.HasOne(e => e.RightNode)
.WithMany();
For performance reasons I want to store the TreeRootNode for each Tree to not always need to query all Node objects to access the root.
The issue: when I run the migrations EF the following exception is thrown:
Cannot create a relationship between 'Node.Tree' and 'Tree.TreeRootNode', because there already is a relationship between 'Tree.Nodes' and 'Node.Tree'. Navigation properties can only participate in a single relationship.
I added a new foreing key TreeRootNodeId to the Tree object. Looking at it from a database level I don't see any issue in having a FK point to a specific Node which is my root Node. But it seems EF has limitations.
Is there a way to configure EF to allow that design? If not is there a performant work around?
I already added a boolean to the Node which indicates if the Node IsRoot. But this is causing performance issues in the long run.
Thanks for your help!
Treereference inNodeclass?NodeI want very quickly access to the root without traversing theTree(possibly using a recursive query). So my plan is to go from anyNodeto theTreeand from there directly the root.