Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You could use supporting hierarchy table to do eager loading of unlimited levels of tree.</p> <p>So, you need to add two collections <code>Ancestors</code> and <code>Descendants</code>, both collection should be mapped as many-to-many to supporting table. </p> <pre><code>public class Tree { public virtual Tree Parent { get; set; } public virtual ICollection&lt;Tree&gt; Children { get; set; } public virtual ICollection&lt;Tree&gt; Ancestors { get; set; } public virtual ICollection&lt;Tree&gt; Descendants { get; set; } } </code></pre> <p>Ancestors will contain all ancestors (parent, grand-parent, grand-grand-parent, etc.) of the entity and <code>Descendants</code> will contain all the descendants (children, grand-children, grand-grand-children, etc) of the entity.</p> <p>Now you have to map it with EF Code First:</p> <pre><code>public class TreeConfiguration : EntityTypeConfiguration&lt;Tree&gt; { public TreeConfiguration() { HasOptional(x =&gt; x.Parent) .WithMany(x =&gt; x.Children) .Map(m =&gt; m.MapKey("PARENT_ID")); HasMany(x =&gt; x.Children) .WithOptional(x =&gt; x.Parent); HasMany(x =&gt; x.Ancestors) .WithMany(x =&gt; x.Descendants) .Map(m =&gt; m.ToTable("Tree_Hierarchy").MapLeftKey("PARENT_ID").MapRightKey("CHILD_ID")); HasMany(x =&gt; x.Descendants) .WithMany(x =&gt; x.Ancestors) .Map(m =&gt; m.ToTable("Tree_Hierarchy").MapLeftKey("CHILD_ID").MapRightKey("PARENT_ID")); } } </code></pre> <p>Now with this structure you could do eager fetch like following</p> <pre><code>context.Trees.Include(x =&gt; x.Descendants).Where(x =&gt; x.Id == id).SingleOrDefault() </code></pre> <p>This query will load entity with <code>id</code> and all of it descenadnts.</p> <p>You could populate the supporting table with following stored procedure:</p> <pre><code>CREATE PROCEDURE [dbo].[FillHierarchy] (@table_name nvarchar(MAX), @hierarchy_name nvarchar(MAX)) AS BEGIN DECLARE @sql nvarchar(MAX), @id_column_name nvarchar(MAX) SET @id_column_name = '[' + @table_name + '_ID]' SET @table_name = '[' + @table_name + ']' SET @hierarchy_name = '[' + @hierarchy_name + ']' SET @sql = '' SET @sql = @sql + 'WITH Hierachy(CHILD_ID, PARENT_ID) AS ( ' SET @sql = @sql + 'SELECT ' + @id_column_name + ', [PARENT_ID] FROM ' + @table_name + ' e ' SET @sql = @sql + 'UNION ALL ' SET @sql = @sql + 'SELECT e.' + @id_column_name + ', e.[PARENT_ID] FROM ' + @table_name + ' e ' SET @sql = @sql + 'INNER JOIN Hierachy eh ON e.' + @id_column_name + ' = eh.[PARENT_ID]) ' SET @sql = @sql + 'INSERT INTO ' + @hierarchy_name + ' ([CHILD_ID], [PARENT_ID]) ( ' SET @sql = @sql + 'SELECT [CHILD_ID], [PARENT_ID] FROM Hierachy WHERE [PARENT_ID] IS NOT NULL ' SET @sql = @sql + ') ' EXECUTE (@sql) END GO </code></pre> <p>Or even you could map supporting table to a view:</p> <pre><code>CREATE VIEW [Tree_Hierarchy] AS WITH Hierachy (CHILD_ID, PARENT_ID) AS ( SELECT [MySuperTree_ID], [PARENT_ID] FROM [MySuperTree] AS e UNION ALL SELECT e.[MySuperTree_ID], e.[PARENT_ID] FROM [MySuperTree] AS e INNER JOIN Hierachy AS eh ON e.[MySuperTree_ID] = eh.[PARENT_ID] ) SELECT [CHILD_ID], [PARENT_ID] FROM Hierachy WHERE [PARENT_ID] IS NOT NULL GO </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload