Select entities with multiple and nested levels without using Include

前端 未结 3 1485
没有蜡笔的小新
没有蜡笔的小新 2020-12-11 06:05

I have the following entity:

public class Item 
{
    public int Id { get; set; }

    public int? ParentId { get; set; }
    public Item Parent { get; set; }         


        
3条回答
  •  攒了一身酷
    2020-12-11 06:30

    Let's say we have the following self-referencing table:

    public class Person
    {
        public Person()
        {
            Childern= new HashSet();
        }
    
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
    
        public int? ParentId { get; set; }
    
    
        [StringLength(50)]
        public string Name{ get; set; }
    
        public virtual Person Parent { get; set; }
    
        public virtual ICollection Children { get; set; }
    
    }
    

    And for some point of time you need to get all grandsons for specific persons.

    So, first of all I will create stored procedure(using code-first migration) to get all persons in the hierarchy for those specific persons:

    public override void Up()
    {
        Sql(@"CREATE TYPE IdsList AS TABLE   
                    ( 
                    Id Int
                    )
                    GO
    
                    Create Procedure getChildIds(
                    @IdsList dbo.IdsList ReadOnly
                    )
                    As
                    Begin
                    WITH RecursiveCTE AS
                    (
                        SELECT Id
                        FROM dbo.Persons
                        WHERE ParentId in (Select * from @IdsList)
                        UNION ALL
    
                        SELECT t.Id
                        FROM dbo.Persons t
                        INNER JOIN RecursiveCTE cte ON t.ParentId = cte.Id
                    )
                    SELECT Id From RecursiveCTE
                    End");
    }
    
    public override void Down()
    {
        Sql(@" Drop Procedure getChildIds
               Go
               Drop Type IdsList
               ");
    }
    

    After that you can use Entity Framework to load the ids(you could modify stored procedure to return persons instead of only returning ids) of persons under the passed persons(ex grandfather) :

     var dataTable = new DataTable();
     dataTable.TableName = "idsList";
     dataTable.Columns.Add("Id", typeof(int));
     //here you add the ids of root persons you would like to get all persons under them
     dataTable.Rows.Add(1);
     dataTable.Rows.Add(2);
    //here we are creating the input parameter(which is array of ids)
     SqlParameter idsList = new SqlParameter("idsList", SqlDbType.Structured);
     idsList.TypeName = dataTable.TableName;
     idsList.Value = dataTable;
     //executing stored procedure
     var ids= dbContext.Database.SqlQuery("exec getChildIds @idsList", idsList).ToList();
    

    I hope my answer will help others to load hierarchical data for specific entities using entity framework.

提交回复
热议问题