web-dev-qa-db-ja.com

EntityFramework.Coreを使用して自己参照テーブルから完全な階層をロードする

この質問が次の理由と異なる理由: EF-複数のインクルードが階層データを熱心にロードします。悪い習慣ですか?

  1. 可能性のある重複は、これが悪い習慣かどうかの意見に基づく質問ですが、私の質問は、それが良い実践かどうかの意見とは関係なく、それを行う方法に関する技術的な解決策を得る傾向があります。この決定は、製品の所有者、要件エンジニア、プロジェクトマネージャー、およびその機能を必要とする顧客に任せます。
  2. 与えられた答えは、それが悪い習慣である理由を説明するか、私にとってはうまくいかないアプローチを使用します(Include()とThenInclude()を使用すると、ハードコーディングされた深度が生成されますが、柔軟な深度が必要です)。

現在のプロジェクト(.NETコアWeb API)では、自己参照テーブルから階層をロードしようとしています。

たくさんググった後、私はそのような仕事(私は些細なことだと思っていました)はささいなことではないように思われました。

さて、私は私の階層を形成するためにこのテーブルを持っています:


CREATE TABLE [dbo].[Hierarchy] (
    [Id]        INT           IDENTITY (1, 1) NOT NULL,
    [Parent_Id] INT           NULL,
    [Name]      NVARCHAR (50) NOT NULL,
    PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_Hierarchy_Hierarchy] FOREIGN KEY ([Parent_Id]) REFERENCES [dbo].[Hierarchy] ([Id])
);

Web APIでは、完全な階層を返すようにしています。おそらく特別なことの1つ(それが役立つ可能性があります)は、テーブル全体をロードしたいという事実です。

熱心な読み込みとナビゲーションプロパティを使用できることも知っています(ParentおよびInverseParent for children)


_dbContext.Hierarchy.Include(h => h.InverseParent).ThenInclude(h => h.InverseParent)...

これの問題は、これがハードコードされた深さ(たとえば、1 Include()と5 ThenInclude()を使用する場合は6レベル)をロードしますが、私の階層の深さは柔軟です。

誰でも私にいくつかのコードを与えてテーブル全体をロードし(たとえば、1つのDB呼び出しを使用した最適なシナリオでメモリに)、メソッドに完全な階層を返すようにすることはできますか?

12
monty

実際、いわゆるEF(コア)関係フィックスアップのおかげで、全体階層のロードは非常に簡単です。

次のモデルがあるとします。

public class Hierarchy
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Hierarchy Parent { get; set; }
    public ICollection<Hierarchy> Children { get; set; }
}

次に、次のコード

var hierarchy = db.Hierarchy.Include(e => e.Children).ToList();

正しく設定されたParentおよびChildrenプロパティを使用して階層全体をロードします。

参照された投稿で説明されている問題は、階層の一部のみをロードする必要がある場合に発生します。これは、LINQでのCTEのようなサポートがないために困難です。

21
Ivan Stoev

再帰cteを使用してすべてのレベルのすべての子を取得するストアドプロシージャを構築しました Entity Frameworkと再帰cteを使用して任意のレベルの自己参照テーブルのすべての子IDを取得するストアドプロシージャ

1
Simple Code