エンティティフレームワーク-複数レベルのプロパティを含める


376

Include()メソッドは、オブジェクトのリストに対して非常にうまく機能します。しかし、もし私が2つのレベルを深く掘り下げる必要がある場合はどうなりますか?たとえば、以下のメソッドは、ここに示されているプロパティを含むApplicationServerを返します。ただし、ApplicationsWithOverrideGroupは、他の複雑なオブジェクトを保持する別のコンテナーです。そのプロパティでInclude()も実行できますか?または、そのプロパティを完全にロードするにはどうすればよいですか?

今のところ、このメソッドは:

public IEnumerable<ApplicationServer> GetAll()
{
    return this.Database.ApplicationServers
        .Include(x => x.ApplicationsWithOverrideGroup)                
        .Include(x => x.ApplicationWithGroupToForceInstallList)
        .Include(x => x.CustomVariableGroups)                
        .ToList();
}

Enabledプロパティ(下記)のみを入力し、ApplicationまたはCustomVariableGroupプロパティ(以下)は入力しません。これを実現するにはどうすればよいですか?

public class ApplicationWithOverrideVariableGroup : EntityBase
{
    public bool Enabled { get; set; }
    public Application Application { get; set; }
    public CustomVariableGroup CustomVariableGroup { get; set; }
}

こんにちは、Expression must be a member expressionこれを試したときに例外が発生する理由:コレクションを1レベル下に含めるには:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection))
Joe.wang

1
@BobHorn、私は同じ問題を抱えています。私の場合、ネストは複数のレイヤーの深いところに行き、あなたが指摘したインクルードを実行することができました。生成されたSQLでは、すべての列がc1、c2のような別のエイリアス名で返されていることがわかります。私の質問は、私がすべてのインクルードからネストされたDTOコレクションをどのように形成できるかです: )
TechQuery、2015年

回答:


704

EF 6の場合

using System.Data.Entity;

query.Include(x => x.Collection.Select(y => y.Property))

using System.Data.Entity;のバージョンを取得するには、必ずIncludeラムダを追加してください。


EF Coreの場合

新しい方法を使用する ThenInclude

query.Include(x => x.Collection)
     .ThenInclude(x => x.Property);

1
ApplicationsWithOverrideGroupでInclude()を実行できません。インテリセンスでは表示されません。
ボブ・ホーン

ApplicationsWithOverrideGroupはリストであるため、編集を使用できません。アプリケーションは、リスト自体ではなく、リスト内の各アイテムのプロパティです。
ボブ・ホーン

1
ああ、でもあなたが提供したそのリンクは答えを提供するようです。これを試してみましょう:コレクションを1レベル下に含めるには:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection))。
ボブ・ホーン

60
使い方にSystem.Data.Entityを含めることを忘れないでください。それ以外の場合、Intellisenseはメソッドのインクルード(文字列パス)バージョンのみを提供します。
OJRaqueño2013

5
@ Includeプロパティごとに呼び出す必要があります:Db.States.Include(state => state.Cities.Select(city => city.Customers).Include(state => state.Cities.Select(city => city.Vendors)
ディエゴトーレス

72

私があなたを正しく理解していれば、ネストされたプロパティを含めることを求めています。その場合:

.Include(x => x.ApplicationsWithOverrideGroup.NestedProp)

または

.Include("ApplicationsWithOverrideGroup.NestedProp")  

または

.Include($"{nameof(ApplicationsWithOverrideGroup)}.{nameof(NestedProp)}")  

6
ありがとう、私はそれを試すことができます。私は物事を強く型付けし続け、文字列リテラルを避けることができることを望んでいました。しかし、それは...それが行われる必要がある方法です場合
ボブ・ホーン

1
あなたは近くにいた。私は、ApplicationsWithOverrideGroupがリストであることを明確にしていない可能性があります。助けてくれてありがとう!
ボブ・ホーン

@柔道、私は同じ問題を抱えています。私の場合、ネストは複数のレイヤーの深いところに行きます、私はあなたが指摘したインクルードを行うことができました。生成されたSQLでは、すべての列がc1、c2のような別のエイリアス名で返されていることがわかります。私の質問は、私がすべてのインクルードからネストされたDTOコレクションをどのように形成できるかです: )
TechQuery、2015年

2
使い方にSystem.Data.Entityを含めることを忘れないでください。それ以外の場合、IntellisenseはInclude(string path)メソッドのバージョンのみを提供します。
AlexMelw

53

EF Core: "ThenInclude"を使用して複数のレベルを読み込む:例:

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
        .ThenInclude(author => author.Photo)
    .ToList();

53
これはEF Coreのみのようです
Chris Marisic

27
参考:VS2017インテリセンスは.ThenIncludeで機能しませんでした。どうあるべきかを入力するだけで、エラーの強調表示が消えます。
JohnWrensby

4
@JohnWrensbyのコメントを強調したいのですが、Intellisenseは、これらのThenIncludeを処理するのに特に時間がかかる場合があります。これは、新しいユーザーを混乱させる可能性があります。また、単純なIncludeラムダ式が適切に処理されない場合もありました。VSに表示される「エラー」を無視して、入力してコンパイルするだけです。
Pac0 2017年

@ Pac0あなたは私の日を救った。子アイテムを見るのに苦労して、できませんでした。
Bendram

28

Entity Framework 6(.Net Coreスタイル)の小さなヘルパーを作成し、サブエンティティを適切に含めました。

今すぐNuGetにあります:Install-Package ThenInclude.EF6

using System.Data.Entity;

var thenInclude = context.One.Include(x => x.Twoes)
    .ThenInclude(x=> x.Threes)
    .ThenInclude(x=> x.Fours)
    .ThenInclude(x=> x.Fives)
    .ThenInclude(x => x.Sixes)
    .Include(x=> x.Other)
    .ToList();

パッケージはGitHub入手できます


こんにちは、私は実行時に例外があり、IncludableQueryable <observablecollection>をIncludableQueryable <genericcollection>にキャストできません
user2475096

私は最初にdbを使用していますが、すべてのエンティティのObservableCollectionsを取得するためにttファイルを変更しました。どんなヘルプでも大歓迎です。
user2475096 2018年

2
@ lenny32この拡張機能について知っておくべきことはありますか?
アーロンフドン

ナビゲート先のプロパティがナビゲート元のDbSetと1対1である場合、これは必要ありませんDbSet<One>().Include(x => x.Two.Three.Four.Five.Six)。デカルト積を計算していて帯域幅が増加する可能性があるという唯一の欠点を連鎖させることができます。
John Zabroski

23

その他のMSDNの上EFCore例あなたがいくつかの非常に複雑なことを行うことができることを示しInclude及びThenInclude

これは、取得できる複雑さの良い例です(これはすべて1つのステートメントです)。

viewModel.Instructors = await _context.Instructors

      .Include(i => i.OfficeAssignment)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Enrollments)
                .ThenInclude(i => i.Student)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Department)

      .AsNoTracking()
      .OrderBy(i => i.LastName)
      .ToListAsync();

Include後でどのように連鎖できるかを確認しThenInclude、それが一種の「リセット」して最上位エンティティ(インストラクター)のレベルに戻るようにします。

同じ「第1レベル」のコレクション(CourseAssignments)を複数回繰り返してから、別のThenIncludesコマンドを実行して、異なる子エンティティにアクセスすることもできます。

実際のクエリはIncludeor ThenIncludesチェーンの最後にタグ付けする必要があることに注意してください。以下は機能しません:

var query = _context.Instructors.AsQueryable();
query.Include(i => i.OfficeAssignment);

var first10Instructors = query.Take(10).ToArray();

ロギングを設定し、1つまたは2つ以上を含める場合は、クエリが制御不能にならないようにすることを強くお勧めします。実際にどのように機能するかを確認することが重要です。個々の「include」は通常、大規模な結合が冗長なデータを返さないようにするための新しいクエリです。

AsNoTracking 実際にエンティティを編集して再保存するつもりがない場合は、大幅にスピードアップできます。


CourseAssignmentとCourseのインクルードを繰り返さずに、登録と学部の両方を取得する方法はありますか?(これまでのところ、Apiは.ThenIncludeを使用してより深く、または.Includeを使用して最上位に戻ることができるようですが、同じレベルにとどまることはありませんか?)
William Jockusch

遅延読み込みが必要な場合はEF Core 2.1blogs.msdn.microsoft.com/dotnet/2018/02/02/…を調整してください。ただし、同じレベルでさらに読み込む場合は、これは仕様によるものだと思います。私はあなたが何を考えているのかわかりません-これを行うのに余計なことを必要とせず、データベースから戻ってくるものを大幅に減らします。エンティティには1つまたは2つの「同じレベル」のものが含まれる場合がありますが、大規模なプロジェクトの場合は50になる場合があります。明示的に指定すると、アプリの速度が大幅に向上します。
Simon_Weaver 2018

これは、インクルードの概念を適切に説明したものであり、レベルを再び初期レベルに「リセット」します。インクルードシステムの階層に頭を抱える手助けをしました。乾杯!
AFM-Horizo​​n

22

また、複数のインクルードを使用する必要があり、第3レベルでは複数のプロパティが必要でした

(from e in context.JobCategorySet
                      where e.Id == id &&
                            e.AgencyId == agencyId
                      select e)
                      .Include(x => x.JobCategorySkillDetails)
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.DurationType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RuleType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RateType))
                      .FirstOrDefaultAsync();

これは誰かを助けるかもしれません:)


1
繰り返すことなくこれを行うことができます.Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt......
Multinerd 2018年

まあ、それはあなたがどれだけ深く行きたいかによって異なります
dnxit

7

文字列リテラルを使用してもかまわない場合は、対応する関係の多重度に関係なく、文字列オーバーロードを使用してネストされたレベルを含めることができることを明確に述べておきます。

query.Include("Collection.Property")

1
この方法は、何時間もグーグルで検索してもどこにも見つからないため、VBでこれをコード化する方法を理解するのに役立ちました。
コーダー、

これは私にとってはうまくいきます、私はこれをたくさん使います!!! :それも.SelectMany文と組み合わせた作品query.SelectMany(x=>x.foos).Include("bar").Include("bar.docs")...
Ephie
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.