EF Core 1.0:ツリー全体を照会するには?

c# entity-framework-core linq tree

質問

私はEF 7.0.0.0-rc1-finalを使用しています。

私は、GrandGrandParentからGrandParentへ、親からChildへの1対多の関係を持つツリー構造を持っています。

public class GrandGrandParent
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual List<GrandParent> GrandParents { get; set; }

    public GrandGrandParent()
    {
        this.GrandParents = new List<GrandParent>();
    }
}

public class GrandParent
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual GrandGrandParent GrandGrandParent { get; set; }
    public virtual List<Parent> Parents { get; set; }

    public GrandParent()
    {
        this.Parents = new List<Parent>();
    }
}

public class Parent
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual GrandParent GrandParent { get; set; }
    public virtual List<Child> Children { get; set; }

    public Parent()
    {
        this.Children = new List<Child>();
    }
}

public class Child
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual Parent Parent { get; set; }
}

EF Core 1.0(EF 7)を使用して、壮大な祖父母IDが与えられた場合、ツリー全体を与えるLINQクエリ(またはサブクエリ)を作成するにはどうすればよいですか?

私は1レベルアップまたはダウンを含めることができます。これは私にGrandGrandParentとGrandParentsのリストを与えます:

var ggparent1 = from ggp in myDbContext.GrandGrandParent
                .Include(ggp => ggp.GrandParents)
                where ggp.ID == 2
                select ggp;

私は子供のリストに、ツリー全体を取得したい。 foreach()ループをコード化し、手動でツリーを構築する必要がありますか?

受け入れられた回答

私はちょうどLinq形式で行くだろう:

private static void Test0(ApplicationDbContext myDbContext)
{
    var ggparent = myDbContext.GrandGrandParents
        .Include(ggp => ggp.GrandParents)
        .ThenInclude(gp => gp.Parents)
        .ThenInclude(p => p.Children)
        .FirstOrDefault(ggp => ggp.ID == 3);

    if (ggparent == null)
    {
        DebugPrint("GrandGrandParent not found");
        return;
    }

    DebugPrint("GrandGrandParent:");
    DebugPrint(ggparent);


    if (ggparent.GrandParents == null)
    {
        DebugPrint("GrandParents null");
        return;
    }

    foreach (var gparent in ggparent.GrandParents)
    {
        DebugPrint(gparent);
        if (gparent.Parents == null) continue;
        foreach (var parent in gparent.Parents)
        {
            DebugPrint(parent);
            if (parent.Children == null) continue;
            foreach (var child in parent.Children)
            {
                DebugPrint(child);
            }
        }
    }

    int changeCount = myDbContext.SaveChanges();
    DebugPrint(string.Format("ChangeCount={0}", changeCount));
}

次に、あなた自身でサブクエリを実行する必要はありません。しかし、EFが実際に作成するSQL照会を見るためにロギングを追加することができます。

完全なツリーが必要な場合は、 select必要はありません。 selectを使用すると、結果ツリーの一部を抽出したり、階層から新しい(フラット)オブジェクトを構築することができます。

グループ化されたSelectListの項目を取得するために、2つのレベル(多対多)で階層を平坦化する例を次に示します。

var result =
    (from c in dbContext.EventTypes
    join j in dbContext.EventType2EventTypes on c.Id equals j.ChildEventTypeId
    join p in dbContext.EventTypes on j.ParentEventTypeId equals p.Id
    where p.EventTypeLevel == EventTypeLevel.First && c.EventTypeLevel == EventTypeLevel.Second
    orderby p.SortOrder, p.Id, c.SortOrder, c.Id
    select new SelectListItem
    {
        Text = c.NameDe,
        Value = c.Id.ToString(),
        Group = GetParentEventTypeSelectListGroup(p.NameDe)
    }).AsNoTracking();


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ